LLVM IR: expose variables to GDB? - gdb

I am writing a custom programming language. I am generating LLVM IR as an intermediate (via LLVMlite), and I want to expose variables to GDB. This is an example of the generated IR:
; ModuleID = "tests/debuginfo.xan"
source_filename = "debuginfo.xan"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""
define void #"main"(i32 %".1", i8** %".2") !dbg !10
{
entry:
%"$argc" = alloca i32
store i32 %".1", i32* %"$argc"
%"$argv" = alloca i8**
store i8** %".2", i8*** %"$argv"
%"$a" = alloca i32
call void #"llvm.dbg.declare"(metadata i32* %"$a", metadata !12, metadata !13), !dbg !14
call void #"llvm.dbg.value"(metadata i32 0, metadata !12, metadata !13), !dbg !15
store i32 0, i32* %"$a"
ret void
}
declare i32 #"printf"(i8* %".1", ...)
declare void #"llvm.dbg.declare"(metadata %".1", metadata %".2", metadata %".3") nounwind readnone
declare void #"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3") nounwind readnone
#"NULL" = internal constant i8* inttoptr (i32 0 to i8*)
!llvm.dbg.cu = !{ !2 }
!llvm.module.flags = !{ !3, !4, !5 }
!llvm.ident = !{ !6 }
!gen-by = !{ !16 }
!0 = !DIFile(directory: "/home/proc-daemon/Dropbox/Xanathar/xanathar/tests", filename: "debuginfo.xan")
!1 = !{ }
!2 = distinct !DICompileUnit(emissionKind: FullDebug, enums: !1, file: !0, isOptimized: false, language: DW_LANG_Python, producer: "Xanathar v. a0.0.1", runtimeVersion: 0)
!3 = !{ i32 2, !"Dwarf Version", i32 4 }
!4 = !{ i32 2, !"Debug Info Version", i32 3 }
!5 = !{ i32 1, !"wchar_size", i32 4 }
!6 = !{ !"Xanathar a0.0.1" }
!7 = !DIDerivedType(baseType: null, size: 64, tag: DW_TAG_pointer_type)
!8 = !{ !7 }
!9 = !DISubroutineType(types: !8)
!10 = distinct !DISubprogram(file: !0, isDefinition: true, isLocal: false, isOptimized: false, name: "main", scope: !0, scopeLine: 1, type: !9, unit: !2, variables: !1)
!11 = !DIBasicType(encoding: DW_ATE_signed, name: "int", size: 4)
!12 = !DILocalVariable(file: !0, line: 1, name: "a", scope: !10, type: !11)
!13 = !DIExpression()
!14 = !DILocation(column: 1, line: 1, scope: !10)
!15 = !DILocation(column: 1, line: 2, scope: !10)
!16 = !{ !"Xanathar" }
I removed the previous edits. The generation code can be found here. As you can see, I have a variable $a that I am trying to declare with llvm.dbg.declare. However, although objdump --sym lists debug info (pastebin), gdb gives No locals. upon running info locals. What is the correct way to export variables? How could I generate that with LLVMlite?
Here is the compilation code:
def compile(self, name, so):
sys.stderr.write('---COMPILE---\n')
if not so:
command = 'clang {0} -g -fstandalone-debug -O0 ' + name + '.ll '
else:
command = 'clang {0} -g -fstandalone-debug -O0 -shared -undefined dynamic_lookup ' + name + '.ll '
command = command.format(self.flags)
for i in self.LOADED_MODULES:
if i["type"] == 'LINKED_SO':
command += os.path.abspath(i["FILE"]) + ' '
command = command + '-o ' + name + ('.so' if so else '.o')
# print(command)
os.system(command)
Here is the LLVM confirmation code:
def _compile_ir(self, builder):
"""
Compile the LLVM IR string with the given engine.
The compiled module object is returned.
"""
# Create a LLVM module object from the IR
self.builder = builder
self.builder.ret_void()
self.module.add_named_metadata("gen-by", ["Xanathar"])
llvm_ir = str(self.module)
try:
mod = self.binding.parse_assembly(llvm_ir)
except RuntimeError as e:
sys.stderr.write("[ERR] LLVM parsing error!\n")
sys.stderr.write(str(e))
if "expected instruction opcode" in str(e):
sys.stderr.write("\nDid you forget to return from a function?")
exit(1)
mod = 0 # Otherwise PyCharm complains about mod's usage below
mod.verify()
# Now add the module and make sure it is ready for execution
self.engine.add_module(mod)
self.engine.finalize_object()
self.engine.run_static_constructors()
return mod
(After this, the module is written to a file)
EDIT 5 (or 6, idk): As Chirag Patel suggested, I added a new debug statement to the ret instruction. Then, this happened.
(gdb) r
Starting program: /home/proc-daemon/Dropbox/Xanathar/xanathar/tests/debuginfo.xan.o
Breakpoint 1, main () at debuginfo.xan:1
1 declare $a as int32;
(gdb) info locals
Segmentation fault (core dumped)

Related

Cannot link custom generated LLVM IR with Clang generated IR

I've been trying to link IR generated with llvm's C++ api with a another IR file generated by Clang++. The input file to Clang is a function fn I'm trying to call from the first IR file. But llvm-link doesn't replace fn's declaration with its definition.
main_ir.ll
source_filename = "top"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
#0 = private unnamed_addr constant [5 x i8] c"%d \0A\00", align 1
declare i32 #printf(...)
declare i32 #fn(i32, ...)
define internal i32 #main() {
entrypoint:
%f_call = call i32 (i32, ...) #fn(i32 2)
%printfCall = call i32 (...) #printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* #0,
i32 0, i32 0), i32 %f_call)
br label %ProgramExit
ProgramExit: ; preds = %entrypoint
ret i32 0
}
fn_ir.ll (generated with Clang)
source_filename = "libDessin.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 #_Z2fni(i32) #0 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = mul nsw i32 %3, 2
ret i32 %4
}
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-
math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-
width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-
math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-
math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-
cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false"
"use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 9.0.1-12 "}
And all llvm-link does is reproduce the contents of fn_ir.ll with the source_filename changed to llvm-link. I'd be real happy to know the bit I'm missing.
The answer is in the name mangling.
Your 'manually' generated IR has a function named fn, while clang++ emits the name _Z2fni.
You need to make the names match. Either emit the _Z2fni in the main_ir.ll, or (arguable better in this case) change the definition of fn in the fn_ir, e.g.:
extern "C" void fn(int x) {
return x * 2;
}
extern "C" tells the compiler to use C mangling convention, this is less fragile since it will work even if you change type or number of arguments of fn. However, it won't work if you want to pass C++ types into the fn, then you need to emit the right function name for the main_ir.ll.
UPD:
There two more 'discrepancies':
The fn has different arguments in the two modules: i32 vs i32, ...
The other issue is that main declared as internal. I guess it is just stripped since it is internal and it is not being called by anyone.
So just removing the internal flag should do the job for you.

Why is Clang automatically adding attributes to my functions?

I have a piece of code that I'm trying to turn into LLVM bitcode:
int main() {
volatile double n = 0.45;
for (int j = 0; j < 32; j++) {
n *= j;
}
return 0;
}
I run the following command on it:
clang -O0 -S -emit-llvm TrainingCode/trainingCode.cpp -o TrainingCode/trainingCode.ll
to generate the following LLVM bitcode (take note of the 6th line, the one with "Function Attrs"):
; ModuleID = 'TrainingCode/trainingCode.cpp'
source_filename = "TrainingCode/trainingCode.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: noinline norecurse nounwind optnone uwtable
define i32 #main() #0 {
entry:
%retval = alloca i32, align 4
%n = alloca double, align 8
%j = alloca i32, align 4
store i32 0, i32* %retval, align 4
store double 4.500000e-01, double* %n, align 8
store i32 0, i32* %j, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32, i32* %j, align 4
%cmp = icmp slt i32 %0, 32
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32, i32* %j, align 4
%conv = sitofp i32 %1 to double
%2 = load double, double* %n, align 8
%mul = fmul double %2, %conv
store double %mul, double* %n, align 8
br label %for.inc
for.inc: ; preds = %for.body
%3 = load i32, i32* %j, align 4
%inc = add nsw i32 %3, 1
store i32 %inc, i32* %j, align 4
br label %for.cond
for.end: ; preds = %for.cond
ret i32 0
}
attributes #0 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.0 (tags/RELEASE_500/final)"}
Why is clang adding the optnone attribute to main? I need LLVM to run various transformation passes on the bitcode and the optnone attribute is causing LLVM to skip over main... I need this attribute to not be added.
Compiling with -O1 seems to fix this, however this is unacceptable because I need Clang to give me unoptimized code. I want LLVM to optimize the unoptimized code given to me by Clang, but the presence of the optnone attribute is causing LLVM to not perform any optimizations.
There are clang options to disable its optimization of the LLVM-IR. See https://reviews.llvm.org/D28047 for discussion of a patch that would change them, and #Anton's answer to this question for more about using it. Some or all of these options might be the right thing:
clang -O1 -mllvm -disable-llvm-optzns -disable-llvm-passes
(The resolution of that discussion was commit rL290392: Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes', so current clang only needs one.)
Or there's the dumb way: A simple workaround is possible with sed (or your favourite text-processing tool).
You're only using this on compiler-generated code, so you don't have to worry about using regexes to parse free-form hand-written code. Thus you can match fixed formatting that the compiler always uses to make sure you operate only on the correct lines.
# tested and works on the .ll in your question
sed -i '/^; Function Attrs:\|^attributes #/ s/optnone //' *.ll
Replaces the first occurence of optnone (with a trailing space) with the empty string, on lines that start with attributes # (the one that matters) or with ; Function Attrs: (the comment).
It's an s/// command controlled by a /foo\|bar/ address regex to select which lines it operates on.
sed -i rewrites the input file(s) in-place.
This is expected. The -O0 output is not intended for further optimizations, some bits of IR are not emitted at all in order to reduce the compilation time.
So, you'd need to use -O1 -mllvm -disable-llvm-optzns if you want to get unoptimized IR that may be optimized later.
Sorry not a solution, but maybe a clue.
But be clang version released or environment variables.
Taking your code on OS X with XCODE 9:
$ clang -O0 -S -emit-llvm test.cpp -o test2.ll
$ more test2.ll
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
; Function Attrs: norecurse nounwind ssp uwtable
define i32 #main() #0 {
%1 = alloca i32, align 4
%2 = alloca double, align 8
...
; <label>:15: ; preds = %4
ret i32 0
}
attributes #0 = { norecurse nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 8.1.0 (clang-802.0.42)"}

How to determine if a function parameter is annotated?

I'm annotating function parameters as shown below with the label bar.
int foo (char* s __attribute__((annotate("bar")))) {
...
}
Next, I am running a function pass. How can I determine if a given function argument is annotated with the label bar?
You will have to read the llvm.var.annotation and llvm.dbg.declare intrinsics.
More specifically, here is the llvm-ir generated by your code above:
#.str = private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"
#.str.1 = private unnamed_addr constant [75 x i8] c"/tmp/compiler-explorer-compiler117030-12962-1rhu4lb.ojfaiz4cxr/example.cpp\00", section "llvm.metadata"
; Function Attrs: nounwind uwtable
define i32 #foo(char*)(i8*) #0 !dbg !6 {
%2 = alloca i8*, align 8
store i8* %0, i8** %2, align 8
call void #llvm.dbg.declare(metadata i8** %2, metadata !12, metadata !13), !dbg !14
%3 = bitcast i8** %2 to i8*
call void #llvm.var.annotation(i8* %3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* #.str, i32 0, i32 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* #.str.1, i32 0, i32 0), i32 1)
ret i32 0, !dbg !15
}
!6 = distinct !DISubprogram(name: "foo", linkageName: "foo(char*)", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!7 = !DISubroutineType(types: !8)
!8 = !{!9, !10}
!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, align: 64)
!11 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
!12 = !DILocalVariable(name: "s", arg: 1, scope: !6, file: !1, line: 1, type: !10)
The dbg.declare instruction tells you that %2 is actually the first parameter of the function (named s).
%3 is a bitcast of %2, so basically an alias.
And the the llvm.var.annotation instruction tells you that %2 is annotated with the constant string #str, which value is "bar".

clang can't optimize away global variables used only in main()?

If I plug this c++ program into clang (version 3.7)
///*
#include "stdio.h"
#include "stdint.h"
//extern int printf(const unsigned char*, ...);
extern "C" void __cxa_pure_virtual() { }
struct A
{
virtual void foo() = 0;
};
struct B : A
{
uint32_t x;
B(int x) : x(x) { }
virtual void foo()
{
printf("This is a test %d\n", x);
}
};
//*/
uint64_t thing = 0;
float other = 10.0f;
B b(12345);
int main()
{
thing++;
A* a = &b;
other *= 3.14159f;
a->foo();
}
And compile with clang -emit-llvm main.cpp -fno-rtti -O3 -S, then I get the following byte code:
; ModuleID = 'main.cpp'
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i686-pc-linux-gnu"
%struct.B = type { %struct.A, i32 }
%struct.A = type { i32 (...)** }
$_ZN1B3fooEv = comdat any
$_ZTV1B = comdat any
#thing = global i64 0, align 8
#other = global float 1.000000e+01, align 4
#b = global %struct.B { %struct.A { i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* #_ZTV1B, i64 0, i64 2) to i32 (...)**) }, i32 12345 }, align 4
#_ZTV1B = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.B*)* #_ZN1B3fooEv to i8*)], comdat, align 4
#.str = private unnamed_addr constant [19 x i8] c"This is a test %d\0A\00", align 1
#llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
; Function Attrs: nounwind readnone
define void #__cxa_pure_virtual() #0 {
entry:
ret void
}
define i32 #main() #1 {
entry:
%0 = load i64, i64* #thing, align 8, !tbaa !1
%inc = add i64 %0, 1
store i64 %inc, i64* #thing, align 8, !tbaa !1
%1 = load float, float* #other, align 4, !tbaa !5
%mul = fmul float %1, 0x400921FA00000000
store float %mul, float* #other, align 4, !tbaa !5
%vtable = load void (%struct.A*)**, void (%struct.A*)*** bitcast (%struct.B* #b to void (%struct.A*)***), align 4, !tbaa !7
%2 = load void (%struct.A*)*, void (%struct.A*)** %vtable, align 4
tail call void %2(%struct.A* getelementptr inbounds (%struct.B, %struct.B* #b, i32 0, i32 0))
ret i32 0
}
; Function Attrs: nounwind
define linkonce_odr void #_ZN1B3fooEv(%struct.B* nocapture readonly %this) unnamed_addr #2 comdat align 2 {
entry:
%x = getelementptr inbounds %struct.B, %struct.B* %this, i32 0, i32 1
%0 = load i32, i32* %x, align 4, !tbaa !9
%call = tail call i32 (i8*, ...) #printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* #.str, i32 0, i32 0), i32 %0)
ret void
}
; Function Attrs: nounwind
declare i32 #printf(i8* nocapture readonly, ...) #2
attributes #0 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.7.1 "}
!1 = !{!2, !2, i64 0}
!2 = !{!"long long", !3, i64 0}
!3 = !{!"omnipotent char", !4, i64 0}
!4 = !{!"Simple C/C++ TBAA"}
!5 = !{!6, !6, i64 0}
!6 = !{!"float", !3, i64 0}
!7 = !{!8, !8, i64 0}
!8 = !{!"vtable pointer", !4, i64 0}
!9 = !{!10, !11, i64 4}
!10 = !{!"_ZTS1B", !11, i64 4}
!11 = !{!"int", !3, i64 0}
If you look at the main function, I have two variables that are useless. Sure I increment one and I do some multiplication on another, but I never use the values in them ever.
But if you look at the output of the byte code, it looks like it is still doing the useless math.
Is it just me or is this a bug?
Those variables are variables in global scope. The compiler simply couldn't figure out whether or not those variables could be declared and referenced in other translation units.
I'd be surprised if any modern C++ compiler is sophisticated enough to figure out that execution flow could not escape this translation unit, in a defined manner, and thus it would be safe to optimize away unused global variables in this translation unit.
No, I don't believe that this is a bug, as your variables are globals.
Clang cannot remove this math as it can't know that any externally called function (like the printf function, in a different translation unit) doesn't declare extern float other; and somehow uses it.
Try writing:
int main()
{
uint64_t thing = 0;
float other = 10.0f;
B b(12345);
thing++;
A* a = &b;
other *= 3.14159f;
a->foo();
}

LLVM "Instruction does not dominate all uses" - Inserting new Instruction

I am getting the following error while inserting an instruction using an llvm pass:
Instruction does not dominate all uses!
%add = add nsw i32 10, 2
%cmp3 = icmp ne i32 %a.01, %add
Broken module found, compilation aborted!
I have the source code in a bitcode file whose snippet is:
if.then: ; preds = %entry
%add = add nsw i32 10, 2
br label %if.end
if.else: ; preds = %entry
%sub = sub nsw i32 10, 2
br label %if.end
if.end: ; preds = %if.else, %if.then
%a.0 = phi i32 [ %add, %if.then ], [ %sub, %if.else ]
%a.01 = call i32 #tauInt32Ty(i32 %a.0) ; line A
%add3 = add nsw i32 %a.01, 2
%add4 = add nsw i32 %a.01, 3
%call5 = call i32 (i8*, ...)* #printf(i8* getelementptr inbounds ([7 x i8]* #.str2, i32 0, i32 0), i32 %add3, i32 %add4)
I want to insert a new instruction after "line A" which is :
%cmp3 = icmp ne i32 %a.01, %add
And I have written a function pass whose snippet of the code which does this task is :
for (Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb) {
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
std::string str;
if(isa<CallInst>(i))// || true) {
BasicBlock::iterator next_it = i;
next_it++;
Instruction* next = dyn_cast<Instruction>(&*next_it);
CallInst* ci = dyn_cast<CallInst>(&*i);
Function* ff = ci->getCalledFunction();
str = ff->getName();
errs()<<"> "<<str<<"\n";
if(!str.compare("tauInt32Ty")) {
hotPathSSA1::varVersionWithPathsSet::iterator start = tauArguments[&*ci].begin();
hotPathSSA1::varVersionWithPathsSet::iterator end = tauArguments[&*ci].end();
Value* specArgs = start->second; // specArgs points to %add
ICmpInst* int1_cmp_56 = new ICmpInst(next, ICmpInst::ICMP_NE, ci, specArgs, "cmp3");
}
}
}
}
I have not encountered such a problem jet but I think your problem is the if statement. %add belonges to the if.then BasicBlock and it is not accessable from the if.end block. This is why the phi instruction "chooses" which value is available %add or %sub. So you have to take %a.0 for your IcmpInst as argument not %add.