diff --git a/apex/apex.cpp b/apex/apex.cpp index 8d8e99d..501f582 100644 --- a/apex/apex.cpp +++ b/apex/apex.cpp @@ -122,20 +122,24 @@ bool APEXPass::runOnModule(Module &M) { logPrint("ERROR: exit function is not in symbol table."); exit(-1); } - Function *f = cast(temp); - logPrint("- loaded function: " + f->getGlobalIdentifier()); - f->dump(); + Function *exit_fcn = cast(temp); + logPrint("- loaded function: " + exit_fcn->getGlobalIdentifier()); // Create exit call instruction. - IRBuilder<> builder = IRBuilder<>(M.getContext()); - Value *one = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0); - CallInst *exit_call = builder.CreateCall(f, one); - if (nullptr == exit_call) { + Value *exit_arg_val = ConstantInt::get(Type::getInt32Ty(M.getContext()), 9); + ArrayRef exit_params = makeArrayRef(exit_arg_val); + // CallInst::Create build call instruction to @exit_fcn that has @exit_params. + // Empty string "" means that the @exit_call_inst will not have return variable. + // @exit_call_inst is inserted BEFORE @chosen_instruction. + CallInst *exit_call_inst = + CallInst::Create(exit_fcn, exit_params, "", chosen_instruction); + + if (nullptr == exit_call_inst) { logPrint("ERROR: could not create exit call instruction."); exit(-1); } logPrintFlat("- exit call instruction created: "); - exit_call->dump(); + exit_call_inst->dump(); } logPrintUnderline("\nFinal Module Dump:"); diff --git a/build_and_run.sh b/build_and_run.sh index 67b3c62..5b687e2 100755 --- a/build_and_run.sh +++ b/build_and_run.sh @@ -15,11 +15,15 @@ INPUT_SOURCE="test_dependencies_minimal.c" SOURCE_FCN="main" TARGET_FCN="y" +INPUT_LIB="lib.c" # Generated bytecodes during all stages of processing. BYTECODE_FROM_INPUT="bytecode_from_input.bc" # No optimizations. BYTECODE_FROM_INPUT_BASIC_OPTS="bytecode_from_input_basic_opts.bc" # Some basic optimizations (see BASIC_OPTS). BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX="bytecode_from_input_basic_opts_and_apex.bc" # BASIC_OPTS + APEXPass. +BYTECODE_FROM_LIB="bytecode_from_lib.bc" +BYTECODE_LINKED="bytecode_linked.bc" +LINKED="linked.ll" # Optimizations that are ran before APEXPass BASIC_OPTS="-dce -loop-simplify -simplifycfg" @@ -62,17 +66,25 @@ clang-format -style=llvm -i apex/*.cpp apex/*.h # ============================================================================= # Compile to bytecode and run basic opts and than our opt ===================== -echo "========= Compiling and running APEXPass." +echo "========= Compiling input." + +# compile external libraries +clang -O0 -c -emit-llvm c-code/${INPUT_LIB} -o build/${BYTECODE_FROM_LIB} # compile without anything clang -O0 -c -emit-llvm c-code/${INPUT_SOURCE} -o build/${BYTECODE_FROM_INPUT} +llvm-link build/${BYTECODE_FROM_LIB} build/${BYTECODE_FROM_INPUT} -S -o=build/${LINKED} +llvm-as build/${LINKED} -o build/${BYTECODE_LINKED} + +echo "========= Running APEXPass." + # run some basic optimizations, so the IR is cleaner -opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS} ${BASIC_OPTS} build/${BYTECODE_FROM_INPUT} > /dev/null +#opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS} ${BASIC_OPTS} build/${BYTECODE_FROM_INPUT} > /dev/null # run our pass -#opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} -load build/apex/libAPEXPass.so -apex -dce -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_FROM_INPUT_BASIC_OPTS} > /dev/null -opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} -load build/apex/libAPEXPass.so -apex -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_FROM_INPUT_BASIC_OPTS} > /dev/null +opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} -load build/apex/libAPEXPass.so -apex -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_LINKED} > /dev/null +#opt -o build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} -load build/apex/libAPEXPass.so -apex -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_FROM_INPUT_BASIC_OPTS} > /dev/null # ============================================================================== # Generate callgraphs before and after ========================================= @@ -89,9 +101,9 @@ opt -dot-callgraph ../${BYTECODE_FROM_INPUT} > /dev/null mv callgraph.dot callgraph_no_opt.dot dot callgraph_no_opt.dot -Tsvg -O -opt -dot-callgraph ../${BYTECODE_FROM_INPUT_BASIC_OPTS} > /dev/null -mv callgraph.dot callgraph_default_opt.dot -dot callgraph_default_opt.dot -Tsvg -O +#opt -dot-callgraph ../${BYTECODE_FROM_INPUT_BASIC_OPTS} > /dev/null +#mv callgraph.dot callgraph_default_opt.dot +#dot callgraph_default_opt.dot -Tsvg -O opt -dot-callgraph ../${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} > /dev/null mv callgraph.dot callgraph_apex_opt.dot @@ -138,8 +150,9 @@ cd ../.. echo "========= Disassembling llvm bytecode." llvm-dis build/${BYTECODE_FROM_INPUT} -llvm-dis build/${BYTECODE_FROM_INPUT_BASIC_OPTS} +#llvm-dis build/${BYTECODE_FROM_INPUT_BASIC_OPTS} llvm-dis build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX} +llvm-dis build/${BYTECODE_FROM_LIB} # ============================================================================== @@ -150,8 +163,8 @@ echo "========= Running ${BYTECODE_FROM_INPUT}" lli build/${BYTECODE_FROM_INPUT} # run bytecode after basic opts -echo "========= Running ${BYTECODE_FROM_INPUT_BASIC_OPTS}" -lli build/${BYTECODE_FROM_INPUT_BASIC_OPTS} +#echo "========= Running ${BYTECODE_FROM_INPUT_BASIC_OPTS}" +#lli build/${BYTECODE_FROM_INPUT_BASIC_OPTS} # run pass and execute modified bytecode echo "========= Running ${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX}" diff --git a/c-code/lib.c b/c-code/lib.c new file mode 100644 index 0000000..6ad63be --- /dev/null +++ b/c-code/lib.c @@ -0,0 +1,6 @@ +#include + +void print() +{ + printf("PRINT() from LIB\n"); +} diff --git a/c-code/test_dependencies_minimal.c b/c-code/test_dependencies_minimal.c index ea09652..da086af 100644 --- a/c-code/test_dependencies_minimal.c +++ b/c-code/test_dependencies_minimal.c @@ -1,30 +1,36 @@ #include #include -void test(void) { - return; -} int x(void) { +// printf("x: in\n"); +// printf("x: out\n"); return 10; } int y(int n) { + printf("y: in\n"); int tmp = n+n; + printf("y: out\n"); return tmp; } int z(void) { +// printf("z: in\n"); int tmp = 1; +// printf("z: out\n"); return tmp; } int n(void) { + printf("n: in\n"); int y_ret = y(10); + printf("n: out\n"); return y_ret; } int main(void) { + printf("main: in\n"); int x_ret = x(); int y_ret = y(x_ret); @@ -36,5 +42,6 @@ int main(void) { int n_ret = n(); int n_store = n_ret; + printf("main: out\n"); return 0; }