LibTooling: create compilation database on the fly from compiler command line - clang

I would like to make a LibTooling tool that takes precisely the same compilation string as clang. For example
clang a.c -O3 b.c -I/myinclude -DMY_DEFINE c.c. Should be replaced by my-tool a.c -O3 b.c -I/myinclude -DMY_DEFINE c.c
Officially suggested by clang documentation way to parse arguments in LibTooling-based tools is CommonOptionsParser. It expects a different format of command-line string and by default relies on the compile_commands.json file. I can simulate desired behavior if I put all source files before -- and everything else after it, like this: my-tool a.c b.c c.c -- -O3 -I/myinclude -DMY_DEFINE. Is it possible to implement this without such hacking of parameter string using llvm/clang API?

Related

How do I tell clang memory sanitizer to ignore data from certain libraries?

For example I'd like to ignore sqlite and zlib because I know they're well tested. I grabbed the zpipe.c example and built it like this. Keep in mind I'm using -lz and not building zlib myself. I'm only building zpipe myself and want to limit the sanitize to that one file
clang -g -fsanitize=undefined,memory zpipe.c -lz
I ran echo Test | ./a.out and I got the following error
Uninitialized bytes in __interceptor_fwrite at offset 0 inside [0x7ffd61230bc0, 13)
==50435==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55767941cd85 in def /tmp/zlib-1.2.12/examples/zpipe.c:70:17
#1 0x55767941e709 in main /tmp/zlib-1.2.12/examples/zpipe.c:186:15
#2 0x7f65e834e30f in __libc_start_call_main libc-start.c
#3 0x7f65e834e3c0 in __libc_start_main#GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
#4 0x5576793981d4 in _start (/tmp/zlib-1.2.12/examples/a.out+0x211d4)
SUMMARY: MemorySanitizer: use-of-uninitialized-value /tmp/zlib-1.2.12/examples/zpipe.c:70:17 in def
Is there a way I can say assume any data that goes in and out of zlib or sqlite to be safe to use? I'll be linking both and only want to sanitize my own code
You can use an ignore list file. https://clang.llvm.org/docs/SanitizerSpecialCaseList.html
Usage:
clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c
See the documentation for details on the format of the file.

Load clang pass from within another pass

I have two LLVM passes, one which requires the outputs of the other. So in PassB I have:
void DiscoPoP::getAnalysisUsage(AnalysisUsage &Info) const{
Info.addRequired<PassA>();
}
I tried adding the snippet below to PassB, but when running clang -Xclang -load -Xclang LLVMPassB.so I get an error: undefined symbol: _ZN18PassA2IDE
static RegisterStandardPasses PassLoader(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new PassA()); });
If I load PassA in clang as well, it works: clang -Xclang -load -Xclang LLVMPassA.so -Xclang -load -Xclang LLVMPassB.so
But it seems redundant to have to load it manually if it required from the PassB. Is there a way to load PassA programmatically from PassB?
I get an error: undefined symbol: _ZN18PassA2IDE
Because the PassA isn't visible to clang.
If I load PassA in clang as well, it works: clang -Xclang -load -Xclang LLVMPassA.so -Xclang -load -Xclang LLVMPassB.so
As expected.
But it seems redundant to have to load it manually if it required from the PassB.
Only if there was a way for clang know know about PassA when passB is supplied as flag. clang has no way of knowing where LLVMPassA.so resides unless we pass as flag.
Is there a way to load PassA programmatically from PassB?
This can be done if you modify the LLVM source code and put both your passes there. Registering a pass within LLVM pass manager is straightforward. See https://reviews.llvm.org/D50658 (Hot cold splitting pass) as an example, specifically changes in lib/Transforms/IPO/PassManagerBuilder.cpp, and function createHotColdSplittingPass.

Disabling conditional macro evaluation in clang

#define NUM 1
#if(NUM)
if(globalglobalInteger){
result = 1;
}
#else
result=2
#endif
Given the above code , the requirement is that the conditional macro #if should not be evaluated and all code under #if and #else should be passed for further processing.
Basically I want both the active and inactive part(code under #if and code under #else) to be present in the clang AST.
Is this possible in clang ?
Is there any pre-processor flag available
for doing this in clang?
Saw that there is flag called -fdirectives-only in gcc which disables macro expansion but could not find similar flag in clang
Preprocessing takes places before parsing and AST generation, so you can't have
non-expanded defines and macros in the AST.
However, there are means for handling non-preprocessed code - such as registering to clang preprocessor callbacks (the PPCallbacks interface) or through the pp-trace tool
(disclamer: I don't have experience with this myself).
References:
Clang AST dump doesn't show #defines
http://clang-developers.42468.n3.nabble.com/Preprocessor-Parser-interaction-td3754583.html
http://www.llvm.org/devmtg/2016-11/Slides/Trull-ExtendingClangASTMatchers.pdf
With regards to flags, clang has no equivalent to gcc's -fdirectives-only. For keeping both parts of the macro in output,
you could disable preprocessing altogether, similar to gcc's -fpreprocessed - which will effectively disable macro expansion (but still macros will be absent from the AST).
You could insepct the AST generated for non-preprocessed source files with these commands:
clang -xcpp-output -Xclang -ast-dump -c foo.c
clang -xc++-cpp-output -Xclang -ast-dump -c foo.cpp
HTH - good luck!

How to create a call graph of an iOS app?

I'm looking for a relatively simple way of creating a call graph of an iOS app (or a framework), using it's Xcode project or the obj code it emits.
The project files are a combination of Objective C, Swift and C++.
I've already tried clang's scan-build, but haven't had any luck turning the .dot files into graphViz graphs. I ended up with hundreds of .dot files and after dot, for over an hour, tries to load them up, nothing happens.
I've also tried to use opt, by adding this to my build line:
-S -emit-llvm -o - | opt -dot-callgraph -S
(from this SO question
but I get only a 107 byte callgraph.dot file and that doesn't have anything notable in it.
I think these errors are what make the output useless:
clang-5.0: warning: 'linker' input unused [-Wunused-command-line-argument]
clang-5.0: warning: argument unused during compilation: '-emit-llvm' [-Wunused-command-line-argument]

How parse Perl 6 code using STD.pm6 grammar?

I would like minimal working example of parsing Perl 6 code from Perl 6 using STD.pm6
Running something like this
use v6;
use STD.pm6;
my $j = slurp 'e:\src\perl6\valid-p6-script.p6';
my $o = STD::Grammar.parse($j);
say $o.perl;
under debugger give me absolutely weird output:
e:\src\prg\perl6>c:\rakudo\bin\perl6-debug-m.bat -I. p6.p6
>>> LOADING p6.p6
>>> LOADING E:\src\prg\perl6\STD.pm6
Unhandled exception: ctxlexpad needs an MVMContext
at gen/moar/m-CORE.setting:15136 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm::24)
from gen/moar/m-CORE.setting:15250 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:AT-KEY:95)
from gen/moar/m-CORE.setting:4291 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:postcircumfix:<{ }>:4294967295)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:736 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm::82)
from gen/moar/m-CORE.setting:2826 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:sink-all:168)
from gen/moar/m-CORE.setting:10187 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:sink:36)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:730 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm:unhandled:114)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:721 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm::25)
from gen/moar/m-Metamodel.nqp:3586 (C:\rakudo\share\nqp\lib/Perl6/Metamodel.moarvm:enter:28)
from gen/moar/m-CORE.setting:5190 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:CALL-ME:57)
from gen/moar/m-BOOTSTRAP.nqp:2749 (C:\rakudo/share/nqp/lib/Perl6/BOOTSTRAP.moarvm::93)
from gen\moar\stage2\NQPHLL.nqp:1425 (C:\rakudo\share\nqp\lib/NQPHLL.moarvm:command_eval:380)
from src/Perl6/Compiler.nqp:59 (C:\rakudo\share\nqp\lib/Perl6/Compiler.moarvm:command_eval:93)
from gen\moar\stage2\NQPHLL.nqp:1365 (C:\rakudo\share\nqp\lib/NQPHLL.moarvm:command_line:114)
from gen/moar/m-perl6-debug.nqp:497 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:MAIN:190)
from gen/moar/m-perl6-debug.nqp:440 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<mainline>:68)
from <unknown>:1 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<main>:8)
from <unknown>:1 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<entry>:9)
or without debugger:
e:\src\prg\perl6>c:\rakudo\bin\perl6.bat -I. p6.p6
===SORRY!=== Error while compiling E:\src\prg\perl6\STD.pm6
Semicolon form of 'grammar' without 'unit' is illegal. You probably want to use 'unit grammar'
at E:\src\prg\perl6\STD.pm6:8
------> :ver<6.0.0.alpha>:auth<http://perl.org>;<HERE><EOL>
from p6.p6:2
STD.pm6 was the reference grammar/verifier maintained by Larry during the development of the various Perl 6 compilers (Rakudo, Pugs, Niecza, ...). It comes with a dedicated tool called viv that translates it to Perl 5. As far as I know, it never ran on any of the mainstream compilers.
With the 6.c language release, the torch of reference implementation has essentially passed on to Rakudo, which uses its own grammar written in NQP to parse Perl 6.
While this Grammar (in combination with the corresponding actions) can be used for manual parsing by importing these modules :from<NQP>, the more friendly approach (eg no need to declare $*LINEPOSCACHE) would be via the corresponding compiler object:
say nqp::getcomp('perl6').eval($source, :target<parse>).dump;
Other targets of interest might be :target<syntaxcheck> as well as the more low-level :target<ast> or for the curious perhaps even :target<mast>.
Working example from #perl6 conversation:
use nqp;
use Perl6::Grammar:from<NQP>;
use Perl6::Actions:from<NQP>;
my $source = q|say "hello world";|;
my $*LINEPOSCACHE;
my $p6c = Perl6::Grammar.parse($source, :actions(Perl6::Actions.new()));
say $p6c.dump

Resources