I am trying to follow this link in order to generate an IR representation for a c code. The c code that I am using is as follows
void main() {
int c1 = 17;
int c2 = 25;
int c3 = c1 + c2;
printf("Value = %d\n", c3);
}
Which I save it as const.c. Once it is saved, I use the following command in order to generate a .bc file.
clang -c -emit-llvm const.c -o const.bc
Once the .bc file is generated, I want to use the following command in order to generate the optimized version of the const.bc file which is named const.reg.bc.
opt -mem2reg const.bc > const.reg.bc
I don't have any issues generating these files but for some reason both of them are exactly the same and no optimization happens. The results should be different, I mean const.reg.bc should be an optimized version of the const.bc file. But for some reason it does not happen. Can someone tell me what is it that I am not doing right?
This option can be used with clang -Xclang -disable-O0-optnone to prevent generation of optnone attribute.
When you run clang somefile.c, it defaults to -O0 optimization level, which emits main function with optnone attribute. This attribute prevents optimizations, which is why you don't see the result of mem2reg.
You have to remove optnone attribute if you want opt to do work:
clang -S -emit-llvm const.c -o - | sed s/optnone// | opt -S -mem2reg
Note thet mem2reg and its counterpart reg2mem passes are not strictly optimizing. They are just converting the IR from/to SSA form.
Related
From https://github.com/riscv/riscv-llvm,
Using the llvm-riscv is fairly simple to build a full executable
however you need riscv64-unknown-*-gcc to do the assembling and
linking. An example of compiling hello world:
$ clang -target riscv64 -mriscv=RV64IAMFD -S hello.c -o hello.S
$ riscv64-unknown-elf-gcc -o hello.riscv hello.S
My question is: if I change the LLVM backend and get it to emit a new instruction in the hello.S file, how will riscv64-unknown-elf-gcc know how to convert it into object code? Do I also need to make changes in riscv64-unknown-elf-gcc so that it knows the format of the new instruction?
riscv64-unknown-elf-gcc calls as, i.e. usually GNU as from the binutils to assemble assembly code (i.e. hello.S in your snippet) into executable machine code. Thus you would have to modify the binutils if you want to assemble a new instruction.
I have successfully run llvm opt with my toy transformation pass but do not see how to use 'opt' with built-in transformation passes http://llvm.org/docs/Passes.html#introduction
I have an empty hi.c file
int main(){
}
For example, if I want to use -instcount pass,
opt -instcount hi.c
gives me strange error.
opt: hi.c:1:1: error: expected top-level entity
int main(){
^
Use opt -instcount hi.bc does not work neither, with
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.
If I use opt -inst-count -f hi.bc, the output is a messy bitcode.
Question: how should we use 'opt' with built-in transformation passes (those from the link above)? Thanks for your ideas. 'opt -help' says
opt [options] <input bitcode file>
but my example above 'opt -instcount hi.bc' does not work as expected (see above).
At first: opt only works on bitcode / readable LLVM IR files. So passing a .c file will never work.
You have to compile the .c file first with clang:
clang -emit-llvm in.c -o input.bc
The Warning you encounter says basicly everything:
WARNING: You're attempting to print out a bitcode file. This is
inadvisable as it may cause display problems. If you REALLY want to
taste LLVM bitcode first-hand, you can force output with the `-f'
option.
opt has as output the probably modified bitcode file and since you do not support an output file it will print it to stdout. That is why you get "messy" bitcode.
To use opt the way it should be you can use /dev/null to get rid of the output:
opt -inst-count input.bc -o /dev/null
or support an output file
opt -inst-count input.bc -o output.bc
or print the output as readable LLVM IR to stdout
opt -inst-count input.bc -S
or print the ouptut as readable LLVM IR file to disk
opt -inst-count input.bc -S -o output.ll
Similar to GCC, clang supports stopping at different stages when processing C/C++. For example, passing a -E flag causes it to stop after the pre-processor and -c stops before linking.
So far, I am aware of,
-E : pre-processing
-fsyntax-only : syntax checking
-S : assembly
-c : object code
Am I missing any stopping points between those, or is that it?
You can also use -S -emit-llvm to generate LLVM IR assembly files and just -emit-llvm for LLVM bitcode object files. These are the language-independent code representations that clang and other LLVM front-ends generate and pass to LLVM to compile into an executable.
It there a way to see what compiler and flags were used to create an executable file in *nix? I have an old version of my code compiled and I would like to see whether it was compiled with or without optimization. Google was not too helpful, but I'm not sure I am using the correct keywords.
gcc has a -frecord-gcc-switches option for that:
-frecord-gcc-switches
This switch causes the command line that was used to invoke the compiler to
be recorded into the object file that is being created. This switch is only
implemented on some targets and the exact format of the recording is target
and binary file format dependent, but it usually takes the form of a section
containing ASCII text.
Afterwards, the ELF executables will contain .GCC.command.line section with that information.
$ gcc -O2 -frecord-gcc-switches a.c
$ readelf -p .GCC.command.line a.out
String dump of section '.GCC.command.line':
[ 0] a.c
[ 4] -mtune=generic
[ 13] -march=x86-64
[ 21] -O2
[ 25] -frecord-gcc-switches
Of course, it won't work for executables compiled without that option.
For the simple case of optimizations, you could try using a debugger if the file was compiled with debug info. If you step through it a little, you may notice that some variables were 'optimized out'. That suggests that optimization took place.
If you compile with the -frecord-gcc-switches flag, then the command line compiler options will be written in the binary in the note section. See also the docs.
Another option is -grecord-gcc-swtiches (note, not -f but -g). According to gcc docs it'll put flags into dwarf debug info. And looks like it's enabled by default since gcc 4.8.
I've found dwarfdump program to be useful to extract those cflags. Note, strings program does not see them. Looks like dwarf info is compressed.
As long as the executable was compiled by gcc with -g option, the following should do the trick:
readelf --debug-dump=info /path/to/executable | grep "DW_AT_producer"
For example:
% cat test.c
int main() {
return 42;
}
% gcc -g test.c -o test
% readelf --debug-dump=info ./test | grep "DW_AT_producer"
<c> DW_AT_producer : (indirect string, offset: 0x2a): GNU C17 10.2.0 -mtune=generic -march=x86-64 -g
Sadly, clang doesn't seem to record options in similar way, at least in version 10.
Of course, strings would turn this up too, but one has to have at least some idea of what to look for as inspecting all the strings in real-world binary with naked eyes is usually impractical. E.g. with the binary from above example:
% strings ./test | grep march
GNU C17 10.2.0 -mtune=generic -march=x86-64 -g -O3
This is something that would require compiler support. You don't mention what compiler you are using but since you tagged your question linux I will assume you are using gcc -- which does not default the feature you're asking about (but -frecord-gcc-switches is an option to perform this).
If you want to inspect your binary, the strings command will show you everything that appears to be a readable character string within the file.
If you still have the compiler (same version) you used, and it is only one flag you're unsure about, you can try compiling your code again, once with and once without the flag. Then you can compare the executables. Your old one should be identical, or very similar, to one of the new ones.
I highly doubt it is possible:
int main()
{
}
When compiled with:
gcc -O3 -ffast-math -g main.c -o main
None of the parameters can be found in the generated object:
strings main | grep -O3
(no output)
I want to suppress specific warnings from g++. I'm aware of the -Wno-XXX flag, but I'm looking for something more specific. I want some of the warnings in -Weffc++, but not all of them. Something like what you can do with lint - disable specific messages.
Is there a built in way in gcc to do this? Do I have to write a wrapper script?
Unfortunately, this feature isn't provided by g++. In VC++, you could use #pragma warning to disable some specific warnings. In gcc, the closest you can have is diagnostic pragmas, which let you enable/disable certain types of diagnostics for certain files or projects.
Edit: GCC supports pushing/popping warnings since 4.6.4 (see changelog)
For some warnings, there is a command line switch to disable them. In order to know which switch to use, pass -fdiagnostics-show-option to gcc.
You could just use grep -v on the output.
Depending on the warning you wish to disable, you can sometimes correct in code. E.g.:
int main()
{
int i;
}
Generates: foo.cc:4: warning: unused variable 'i'
Whereas this does not:
#define MARKUSED(X) ((void)(&(X)))
int main()
{
int i;
MARKUSED(i);
}
pipe standard error to a filter that removes things you don't want to see. For example, this is my make file:
main.o: main.cpp
g++ -c -Wall main.cpp 2>&1 | grep -v Wunused-variable