diff --git a/apex/apex.cpp b/apex/apex.cpp index 42157c7..a10a09b 100644 --- a/apex/apex.cpp +++ b/apex/apex.cpp @@ -94,13 +94,50 @@ bool APEXPass::runOnModule(Module &M) { logPrintUnderline("Removing functions and dependency blocks that do not " "affect calculated path."); removeUnneededStuff(M, path, blocks_functions_callgraph, - function_dependency_blocks, source_function_id, - target_function_id); + function_dependency_blocks); logPrintUnderline("Inserting exit call after target instructions."); - moduleInsertExitAfterTarget(M, target_function_id); + moduleInsertExit(M, target_function_id); - // TODO: extract data + logPrintUnderline("Extracting data."); + // TODO: extract operand from target instruction and pass it as arg to dump. + { + Instruction *insertion_point = + const_cast(target_instructions_.back()); + std::vector params_tmp = {Type::getInt32Ty(M.getContext())}; + ArrayRef params = makeArrayRef(params_tmp); + FunctionType *fType = + FunctionType::get(Type::getVoidTy(M.getContext()), params, false); + Constant *temp = M.getOrInsertFunction("lib_dump_int", fType); + Function *dump_fcn = cast(temp); + + insertion_point->dump(); + for (unsigned i = 0; i < insertion_point->getNumOperands(); ++i) { + logPrint("- op"); + Value *op = insertion_point->getOperand(i); + op->dump(); + } + + Value *dump_arg_val = + ConstantInt::get(Type::getInt32Ty(M.getContext()), 123456); + dump_arg_val->dump(); + + ArrayRef dump_params = + makeArrayRef(dump_arg_val); + CallInst *dump_call_inst = CallInst::Create(dump_fcn, dump_params, ""); + + if (insertion_point->isTerminator()) { + logPrintFlat("- @insertion_point is terminator, inserting " + + dump_fcn->getGlobalIdentifier() + " before: "); + insertion_point->dump(); + dump_call_inst->insertBefore(insertion_point); + } else { + logPrintFlat("- @insertion_point is NOT terminator, inserting " + + dump_fcn->getGlobalIdentifier() + " after: "); + insertion_point->dump(); + dump_call_inst->insertAfter(insertion_point); + } + } logPrintUnderline("Stripping debug symbols from every function in module."); stripAllDebugSymbols(M); @@ -775,8 +812,8 @@ void APEXPass::moduleFindTargetInstructionsOrDie(Module &M, /// Inserts lib_exit() call at the end of the @target_instructions_. // TODO: Rename this method. -void APEXPass::moduleInsertExitAfterTarget( - Module &M, const std::string &target_function_id) { +void APEXPass::moduleInsertExit(Module &M, + const std::string &target_function_id) { logPrint("Supplied target instructions from: " + target_instructions_.back()->getFunction()->getGlobalIdentifier()); @@ -815,9 +852,8 @@ void APEXPass::moduleInsertExitAfterTarget( logPrint("- loaded function: " + exit_fcn->getGlobalIdentifier()); // Create exit call instruction. - unsigned EXIT_CODE = 9; Value *exit_arg_val = - ConstantInt::get(Type::getInt32Ty(M.getContext()), EXIT_CODE); + ConstantInt::get(Type::getInt32Ty(M.getContext()), APEX_DONE); 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 @@ -857,9 +893,7 @@ void APEXPass::removeUnneededStuff( std::map> &blocks_functions_callgraph, std::map> - &function_dependency_blocks, - const std::string &source_function_id, - const std::string &target_function_id) { + &function_dependency_blocks) { // Mapping from function to dependency blocks. Blocks belong to function. // We are going to keep these function:blocks. diff --git a/apex/apex.h b/apex/apex.h index bbb4b20..b89fe04 100644 --- a/apex/apex.h +++ b/apex/apex.h @@ -42,14 +42,22 @@ bool VERBOSE_DEBUG = false; /// Error code when we want to crash APEXPass. int FATAL_ERROR = -1; +/// Exit code when we want to successfully exit. +int APEX_DONE = 0; + /// Function LLVMNodes connected via the data dependencies. using DependencyBlock = std::vector; /// Protected functions IDs. These will not be removed by APEXPass. std::vector PROTECTED_FCNS = { - "lib_test", "lib_exit", "exit", // These come from c-code/lib.c. - "printf", // Maybe remove prints? - "llvm.dbg.declare" // Introduced with debug symbols. + // These belong to the lib_exit() + "lib_exit", "exit", + // These belong to the lib_dump_int() + "lib_dump_int", "abs", "log10", "floor", "fopen", "fputs", "fclose", "exit", + "sprintf", + "printf", // Maybe remove prints? + "llvm.dbg.declare", "llvm.stackrestore", + "llvm.stacksave", // Introduced with debug symbols. }; /// Command line arguments for opt. @@ -141,8 +149,7 @@ class APEXPass : public ModulePass { void moduleParseCmdLineArgsOrDie(void); void moduleFindTargetInstructionsOrDie(Module &M, const std::string &file, const std::string &line); - void moduleInsertExitAfterTarget(Module &M, - const std::string &target_function_id); + void moduleInsertExit(Module &M, const std::string &target_function_id); void findPath(Module &M, std::map> @@ -158,9 +165,7 @@ class APEXPass : public ModulePass { std::map> &blocks_functions_callgraph, std::map> - &function_dependency_blocks, - const std::string &source_function_id, - const std::string &target_function_id); + &function_dependency_blocks); void stripAllDebugSymbols(Module &M); }; diff --git a/build_and_run.sh b/build_and_run.sh index 5287ef7..9dfa656 100755 --- a/build_and_run.sh +++ b/build_and_run.sh @@ -15,7 +15,7 @@ INPUT_LIB="c-code/lib.c" INPUT_SOURCE="c-code/test_dependencies_minimal.c" FILE="c-code/test_dependencies_minimal.c" -LINE=47 +LINE=43 # Generated bytecodes during all stages of processing. @@ -70,7 +70,7 @@ clang-format -style=llvm -i apex/*.cpp apex/*.h echo "========= Compiling input." # compile external libraries -clang -O0 -g -c -emit-llvm ${INPUT_LIB} -o build/${BYTECODE_FROM_LIB} +clang -O0 -lm -g -c -emit-llvm ${INPUT_LIB} -o build/${BYTECODE_FROM_LIB} # compile without anything clang -O0 -g -c -emit-llvm ${INPUT_SOURCE} -o build/${BYTECODE_FROM_INPUT} diff --git a/c-code/lib.c b/c-code/lib.c index c5c0cab..c5ad502 100644 --- a/c-code/lib.c +++ b/c-code/lib.c @@ -1,12 +1,37 @@ #include #include +#include -void lib_test(void) -{ - printf("lib_test() from lib.c\n"); -} - +/// Function used for getting out of the program, usually after calling @lib_dump_int(). void lib_exit(int exit_code) { exit(exit_code); } +/// Function used for dumping value @i to file @APEX_OUTPUT. +void lib_dump_int(int i) { +#define APEX_OUTPUT "apex.out" + // Figure out number of digits @i has. + // So we can allocate big enough buffer. + int i_digits = 0; + if (i == 0) { + i_digits = 1; + } else { + i_digits = floor(log10(abs(i)))+1; + } + // Store @i as string into @i_string buffer. + char i_string[i_digits+2]; + sprintf(i_string, "%d\n", i); + + // Save @i_string into @APEX_OUTPUT + int status = 0; + FILE *f = fopen(APEX_OUTPUT, "w+"); + if (f != NULL) { + if (fputs(i_string, f) != EOF) { + status = 1; + } + fclose(f); + } + if (status != 1) { + printf("Error: Could not save to file!\n"); + } +} \ No newline at end of file