Skip to content

Commit

Permalink
Example how to load and call fcn from linked code
Browse files Browse the repository at this point in the history
  • Loading branch information
examon committed Oct 20, 2018
1 parent 747eba5 commit ff7d75b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 32 deletions.
51 changes: 34 additions & 17 deletions apex/apex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ bool APEXPass::runOnModule(Module &M) {
// Remove all functions (along with dependencies) that are not in the @path.
moduleRemoveFunctionsNotInPath(M, apex_dg, path);

// Swap call to @target with return.
// Put exit() call before @target function call.
logPrintUnderline("Getting/picking callsite for @" + ARG_TARGET_FCN);
{
Function *target_fcn = M.getFunction(ARG_TARGET_FCN);
Expand Down Expand Up @@ -104,6 +104,23 @@ bool APEXPass::runOnModule(Module &M) {
}
logPrint("- call instruction to @" + ARG_TARGET_FCN + " found");

{
logPrint("\nTEST: calling libprint() from lib.c.");
// TODO: Test externally linked code.
// TODO: Getting: LLVM ERROR: Program used external function
// 'libprint' which could not be resolved!

Constant *_lib_print = M.getOrInsertFunction(
"libprint", Type::getVoidTy(M.getContext()), (Type *)0);
Function *lib_print_fcn = cast<Function>(_lib_print);
logPrint("- libprint() from lib:");
lib_print_fcn->dump();
Instruction *lib_print_call_inst =
CallInst::Create(lib_print_fcn, "", chosen_instruction);
logPrintFlat("- call instruction to libprint(): ");
lib_print_call_inst->dump();
}

logPrint(
"\nInserting call instruction to exit() before chosen instruction.");
// Create vector of types and put one integer into this vector.
Expand Down Expand Up @@ -141,21 +158,6 @@ bool APEXPass::runOnModule(Module &M) {
}
logPrintFlat("- exit call instruction created: ");
exit_call_inst->dump();

// TODO: Test externally linked code.
// TODO: Getting: LLVM ERROR: Program used external function
// 'libprint' which could not be resolved!

logPrint("\nWIP: Testing lib loadout.");
Constant *_lib_print = M.getOrInsertFunction(
"libprint", Type::getVoidTy(M.getContext()), (Type *)0);
Function *lib_print_fcn = cast<Function>(_lib_print);
logPrint("- libprint() from lib:");
lib_print_fcn->dump();
Instruction *lib_print_call_inst =
CallInst::Create(lib_print_fcn, "", chosen_instruction);
logPrintFlat("- call instruction to libprint(): ");
lib_print_call_inst->dump();
}

logPrintUnderline("\nFinal Module Dump:");
Expand Down Expand Up @@ -1008,6 +1010,7 @@ void APEXPass::apexDgFindDataDependencies(

/// Goes over all functions in module. If there is some function in module
/// that is not in the @path, put it for removal along it all its dependencies.
/// Note: Functions that are in @PROTECTED_FCNS, will NOT be removed.
void APEXPass::moduleRemoveFunctionsNotInPath(Module &M,
APEXDependencyGraph &apex_dg,
std::vector<Function *> &path) {
Expand All @@ -1025,15 +1028,29 @@ void APEXPass::moduleRemoveFunctionsNotInPath(Module &M,
module_fcn_to_be_removed = false;
}
}
// @module_fcn is inside @PROTECTED_FCNS, do not remove it.
// Inside @PROTECTED_FCNS could be some function from external library,
// or debug functions or whatever that we do not want to optimize out.
for (std::string &protected_fcn_id : PROTECTED_FCNS) {
if (protected_fcn_id == module_fcn.getGlobalIdentifier()) {
module_fcn_to_be_removed = false;
}
}

if (true == module_fcn_to_be_removed) {
functions_to_be_removed.push_back(&module_fcn);
}
}

logPrintFlat("- path: ");
functionVectorFlatPrint(path);
logPrintFlat("- functions_to_be_removed: ");
logPrintFlat("- functions to be removed: ");
functionVectorFlatPrint(functions_to_be_removed);
logPrintFlat("- protected functions: ");
for (std::string &protected_fcn_id : PROTECTED_FCNS) {
logPrintFlat(protected_fcn_id + ", ");
}
logPrint("");
}

logPrint("\nCollecting instruction dependencies for each function that has "
Expand Down
4 changes: 3 additions & 1 deletion apex/apex.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <llvm/Analysis/CallGraph.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/LegacyPassManager.h>

#include <llvm/Support/CommandLine.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>

Expand All @@ -31,6 +30,9 @@
using namespace llvm;
using namespace dg;

/// Protected functions IDs. These will not be removed by APEXPass.
std::vector<std::string> PROTECTED_FCNS = {"libprint", "printf"};

/// Command line arguments for opt.
cl::opt<std::string> ARG_SOURCE_FCN("source",
cl::desc("Specify source function."),
Expand Down
30 changes: 16 additions & 14 deletions build_and_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ 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"
#BYTECODE_FROM_INPUT_BASIC_OPTS="bytecode_from_input_basic_opts.bc" # Some basic optimizations (see BASIC_OPTS).
BYTECODE_FROM_LIB="bytecode_from_lib.bc" # Compiled libraries from ${INPUT_LIB}
BYTECODE_FROM_LINKED_INPUT_LIB="bytecode_from_linked.bc" # Linked input and lib bytecode. APEXPass will work with this.
LINKED_DISASSEMBLY="bytecode_from_linked.ll"
BYTECODE_FROM_APEX="bytecode_from_apex.bc" # APEXPass bytecode.

# Optimizations that are ran before APEXPass
BASIC_OPTS="-dce -loop-simplify -simplifycfg"
Expand Down Expand Up @@ -74,17 +74,19 @@ 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}
llvm-link build/${BYTECODE_FROM_LIB} build/${BYTECODE_FROM_INPUT} -S -o=build/${LINKED_DISASSEMBLY}
llvm-as build/${LINKED_DISASSEMBLY} -o build/${BYTECODE_FROM_LINKED_INPUT_LIB}

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

# run our pass
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
# run APEXPass without additional opts
opt -o build/${BYTECODE_FROM_APEX} -load build/apex/libAPEXPass.so -apex -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_FROM_LINKED_INPUT_LIB} > /dev/null
# run APEXPass with ${BASIC_OPTS}
#opt -o build/${BYTECODE_FROM_APEX} -load build/apex/libAPEXPass.so -apex ${BASIC_OPTS} -source=${SOURCE_FCN} -target=${TARGET_FCN} < build/${BYTECODE_FROM_LINKED_INPUT_LIB} > /dev/null


# ==============================================================================
# Generate callgraphs before and after =========================================
Expand All @@ -105,7 +107,7 @@ dot callgraph_no_opt.dot -Tsvg -O
#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
opt -dot-callgraph ../${BYTECODE_FROM_APEX} > /dev/null
mv callgraph.dot callgraph_apex_opt.dot
dot callgraph_apex_opt.dot -Tsvg -O

Expand Down Expand Up @@ -151,7 +153,7 @@ 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_AND_APEX}
llvm-dis build/${BYTECODE_FROM_APEX}
llvm-dis build/${BYTECODE_FROM_LIB}


Expand All @@ -167,5 +169,5 @@ lli build/${BYTECODE_FROM_INPUT}
#lli build/${BYTECODE_FROM_INPUT_BASIC_OPTS}

# run pass and execute modified bytecode
echo "========= Running ${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX}"
lli build/${BYTECODE_FROM_INPUT_BASIC_OPTS_AND_APEX}
echo "========= Running ${BYTECODE_FROM_APEX}"
lli build/${BYTECODE_FROM_APEX}

0 comments on commit ff7d75b

Please sign in to comment.