Llvm_executionengine fails to execute pointer operations correctly - ocaml

I'm trying to generate code to box and unbox values in my untyped language. For evaluating a simple integer literal 3, I generate:
define i64 #0() {
entry:
%value = alloca { i64, [10 x i8], <10 x i64> }
%boxptr = getelementptr inbounds { i64, [10 x i8], <10 x i64> }* %value, i32 0, i32 0
store i64 3, i64* %boxptr
%boxptr1 = getelementptr inbounds { i64, [10 x i8], <10 x i64> }* %value, i32 0, i32 0
%load = load i64* %boxptr1
ret i64 %load
}
Seems right, and lli evaluates it to 3, but Llvm_executionengine evaluates the function to 216172782113783808 (junk value). The code from my toplevel.ml looks like:
open Llvm_executionengine
let the_execution_engine = ExecutionEngine.create_interpreter the_module
let print_and_jit se =
let f = sexpr_matcher se in
let result = ExecutionEngine.run_function f [||] the_execution_engine in
print_string "Evaluated to ";
print_int (GenericValue.as_int result);
What's wrong with my interpreter?

Related

LLVM: how to fix "Referring to an argument in another function"

I'm trying to write a function pass in LLVM that replaces
read(file_descriptor, buffer, size) with
klee_make_symbolic(buffer, size, name_of_symbol)
However, I'm running into some trouble while trying to re-use the arguments of the old function.
Running my function pass breaks the newly inserted function. Returning with an error:
Referring to an argument in another function!
call void #klee_make_symbolic(i8* %1, i64 %2, i8* getelementptr inbounds ([5 x i8], [5 x i8]* #0, i32 0, i32 0)), !dbg !27
LLVM ERROR: Broken function found, compilation aborted!
Here is the relevant part of my code:
llvm::CallInst *CI = llvm::dyn_cast<llvm::CallInst>(&*I);
llvm::Function *func(CI->getCalledFunction());
llvm::StringRef func_name(func->getName());
for(std::string s : mksym_func_list){
if(func_name.equals(s)){
tmp = I;
flag = true;
llvm::errs() << *I << "\n";
I++;
llvm::errs() << *I << "\n";
llvm::IRBuilder<> builder(&*I);
std::vector<llvm::Value*> args(3, NULL);
if(func_name == "read"){
int counter = 0;
for(auto arg = func->arg_begin(); arg != func->arg_end(); arg++){
if(counter == 1){
//args[0] = builder.CreateAdd(llvm::dyn_cast<llvm::Value>(arg), llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0, true));
args[0] = arg;
}else if(counter == 2){
//args[1] = builder.CreateAdd(llvm::dyn_cast<llvm::Value>(arg), llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), 0, true));
args[1] = arg;
}
counter++;
}
llvm::Value *sym = builder.CreateGlobalStringPtr("test");
args[2] = sym;
llvm::errs() << "foge\n";
builder.CreateCall(func_mksym, args);
llvm::errs() << "unge\n";
llvm::errs() << "hage\n";
llvm::errs() << *I << "\n";
}
break;
}
}
}
if(!flag) I++; else flag = false;
}
I expect the read function to be replaced with klee_make_symbolic, but LLVM opt tool is returning with an error.
EDIT:
I have changed the code so that it iterates through operands instead of arguments. Now I am able to instrument the code but now the program itself crashes when the new function gets called.
The program works if I replace read with klee_make_symbolic by hand. But it still fails when I use a LLVM pass to do it.
I even checked the .ll files to confirm that there isn't anything wrong with it.
debug.ll:
store i8** %1, i8*** %5, align 8
call void #llvm.dbg.declare(metadata i8*** %5, metadata !16, metadata !DIExpression()), !dbg !17
call void #llvm.dbg.declare(metadata [4 x i8]* %6, metadata !18, metadata !DIExpression()), !dbg !22
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !23
%12 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !24
%13 = call i64 #strlen(i8* %12) #4, !dbg !25
%14 = call i64 #read(i32 0, i8* %11, i64 %13), !dbg !26
call void #llvm.dbg.declare(metadata i32* %7, metadata !27, metadata !DIExpression()), !dbg !28
%15 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 0, !dbg !29
debug_mksym.ll:
store i8** %1, i8*** %5, align 8
call void #llvm.dbg.declare(metadata i8*** %5, metadata !16, metadata !DIExpression()), !dbg !17
call void #llvm.dbg.declare(metadata [4 x i8]* %6, metadata !18, metadata !DIExpression()), !dbg !22
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !23
call void #klee_make_symbolic(i8* %11, i64 4, i8* getelementptr inbounds ([5 x i8], [5 x i8]* #0, i32 0, i32 0)), !dbg !24
call void #llvm.dbg.declare(metadata i32* %7, metadata !25, metadata !DIExpression()), !dbg !24
%12 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 0, !dbg !26
output of klee:
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee -replay-path tests/debug/fprclap/debug-000.path tests/debug/obj/debug_symbolic.bc > tests/debug/fprclap/debug.out
KLEE: output directory is "/home/shinjitumala/E_DRIVE/TiTech/2019/undergraduate_research/CLAP/tests/debug/obj/klee-out-0"
KLEE: Using Z3 solver backend
KLEE: WARNING: undefined reference to function: printf
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x2a)[0x5634b57be61a]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4llvm3sys17RunSignalHandlersEv+0x3e)[0x5634b57bc70e]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(+0x145a859)[0x5634b57bc859]
/usr/lib/libpthread.so.0(+0x13d00)[0x7fa2ab2d7d00]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor4forkERNS_14ExecutionStateENS_3refINS_4ExprEEEb+0x1ce2)[0x5634b468e6a2]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor18executeInstructionERNS_14ExecutionStateEPNS_12KInstructionE+0x4867)[0x5634b4699317]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor3runERNS_14ExecutionStateE+0x9fe)[0x5634b46a180e]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor17runFunctionAsMainEPN4llvm8FunctionEiPPcS5_+0xa7a)[0x5634b46a25fa]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(main+0x2d0f)[0x5634b463b52f]
/usr/lib/libc.so.6(__libc_start_main+0xf3)[0x7fa2aac77ee3]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_start+0x2e)[0x5634b467875e]
/bin/sh: 1 行: 20587 Segmentation fault (コアダンプ) /home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee -replay-path tests/debug/fprclap/debug-000.path tests/debug/obj/debug_symbolic.bc > tests/debug/fprclap/debug.out
make: *** [Makefile:46: fprclap] エラー 139
arg_* iterators iterate over Functions formal arguments. You actually want to iterate over CallInsts operands with value_op_begin()/value_op_end().

Program used external function 'llvm.returnaddress.i8' which could not be resolved

I want to use llvm.returnaddress.i8 in a pass for getting return value of a function.
After I execute ../llvm/bin/lli test_re.bc, I get
LLVM ERROR: Program used external function 'llvm.returnaddress.i8' which could not be resolved!
I don't know how to solve it. Is there any suggestion? Thanks!
The intrinsic is called llvm.returnaddress, not llvm.returnaddress.i8.
declare i8* #llvm.returnaddress(i32)
declare i32 #printf(i8*, ...)
#fmt = constant [20 x i8] c"Return address: %p\0a\00"
define i32 #main() {
%fmt = getelementptr [20 x i8], [20 x i8]* #fmt, i32 0, i32 0
%ra = call i8* #llvm.returnaddress(i32 0)
call i32 (i8*, ...) #printf(i8* %fmt, i8* %ra)
ret i32 0
}

expected comma after getelementptr's type. LLVM

(1) #str = private constant [13 x i8] c"Hello World\0A\00"
(2) define i32 #main(){
(3) %r2 = getelementptr [13 x i8]* #str, i32 0, i32 0
(4) ret i32 0
(5) }
I've got an error error in the line 3: expected comma after getelementptr's type. How to deal with it?
getelemtptr expects the type that you are indexing (without the pointer) as it's first argument. In your case that would be [13 x i8], so you probably want to do something like this:
%r2 = getelementptr [13 x i8], [13 x i8]* #str, i32 0, i32 0

LLVM: ERROR: Constant unimplemented for type

Why does the LLVM pure interpreter performs differently from the JIT-enabled interpreter with respect of array constants? (LLVM 3.8.1)
I have the following code:
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128 :128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-macosx10.9.0"
%MyType = type { i8* }
define i32 #main(i32 %argc, i8** %argv) nounwind uwtable {
%const.arr = alloca [8 x i8], align 8
store [8 x i8] c"\D0\CFT\15\01\00\00\00", [8 x i8]* %const.arr
%1 = bitcast [8 x i8]* %const.arr to %MyType*
ret i32 0
}
If I compile this with llvm-as test.llvm and lli test.llvm.bc, I get no error.
On the other hand, If I hit lli -force-interpreter test.llvm.bc I get the following error:
LLVM ERROR: ERROR: Constant unimplemented for type: [8 x i8]
Inspecting the code, I don't see anything wrong with it. Why does it perform differently when I force the interpreter?

Trouble understanding llvm.global.annotations

I am trying to understand the global annotations which I get with a kernel from llvm but I am kinda confused on a couple of things.
#sgv = internal constant [4 x i8] c"222\00"
#fgv = internal constant [0 x i8] zeroinitializer
#lvgv = internal constant [0 x i8*] zeroinitializer
#llvm.global.annotations = appending global [1 x { i8*, i8*, i8*, i8*, i32 }] [{ i8*, i8*, i8*, i8*, i32 } { i8* bitcast (void (float addrspace(1)*, float addrspace(1)*, float addrspace(1)*)* #add_kernel to i8*), i8* getelementptr inbounds ([4 x i8]* #sgv, i32 0, i32 0), i8* getelementptr inbounds ([0 x i8]* #fgv, i32 0, i32 0), i8* bitcast ([0 x i8*]* #lvgv to i8*), i32 0 }], section "llvm.metadata"
define void #add_kernel(float addrspace(1)* %out, float addrspace(1)* %in1, float addrspace(1)* %in2) #0 {
So I can understand the sgv, fgv & lvgv part. However, when I am looking at the global annotations the parts I am confused about it is this.
[1 x { i8*, i8*, i8*, i8*, i32 }] -- what does the first list mean
[{ i8*, i8*, i8*, i8*, i32 } --> This part before the kernel. What does this signify.
i8* getelementptr inbounds ([4 x i8]* #sgv, i32 0, i32 0), --> In this part am
assuming the i32 0, i32 0 refer to the GEP indexes ?
I need a little more explanation on how this annotation is structured and what is the use of this global annotation.
I think that the part which confuses you is the literal struct - which starts with the struct's type and follows with constants for all the struct's field. 4 of these constants are constant expressions.
Here's a basic breakdown of the AST (not including [, {, }, ], and ,) - click for larger version:
I was too lazy to drill down into the constant expressions as well - but they are basically all in the format <type> <instruction> ( <instruction args>... ) - see more in the language reference.