#include "llvm/Analysis/CFGPrinter.h" // needed for DOTGraphTraits #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/GraphWriter.h" using namespace llvm; std::vector getCallsToFunction(Function* callee, const Function* caller) { std::vector calls; if (callee == nullptr) return calls; for (auto U = callee->user_begin(), UE = callee->user_end(); U != UE; ++U) { CallInst* CI = dyn_cast(*U); if (!CI) // We are not interested in uses that are not calls continue; assert(CI->getCalledFunction() == callee); if (caller == nullptr || CI->getParent()->getParent() == caller) calls.push_back(CI); } return calls; } ConstantInt* makeInt32(int val, LLVMContext& context) { return ConstantInt::get(Type::getInt32Ty(context), val); } Instruction* getInstructionAfter(Instruction* inst) { return ++BasicBlock::iterator(inst); } std::unique_ptr loadModuleFromAsmFile(LLVMContext& context, const std::string& filename) { SMDiagnostic err; std::unique_ptr mod = parseIRFile(filename, err, context); if (!mod) { err.print(filename.c_str(), errs()); exit(1); } return mod; } std::unique_ptr loadModuleFromAsmString(LLVMContext& context, const std::string& str) { SMDiagnostic err; MemoryBufferRef memBuffer(str, "id"); std::unique_ptr mod = parseIR(memBuffer, err, context); return mod; } void saveModuleToAsmFile(const llvm::Module* mod, const std::string& filename) { std::error_code EC; raw_fd_ostream out(filename, EC, sys::fs::F_Text); if (!out.has_error()) { mod->print(out, 0); out.close(); } if (out.has_error()) { errs() << "Error saving to " << filename << "\n"; exit(1); } } void dumpCFG(const Function* F, const std::string& suffix) { std::string filename = ("cfg." + F->getName() + "." + suffix + ".dot").str(); std::error_code EC; raw_fd_ostream out(filename, EC, sys::fs::F_Text); if (!out.has_error()) { errs() << "Writing '" << filename << "'...\n"; WriteGraph(out, F, true, F->getName()); out.close(); } if (out.has_error()) { errs() << "Error saving to " << filename << "\n"; exit(1); } } Function* getOrCreateFunction(const std::string& name, Module* mod, FunctionType* funcType, std::map& typeToFuncMap) { auto it = typeToFuncMap.find(funcType); if (it != typeToFuncMap.end()) return it->second; // Give name a numerical suffix to make it unique std::string uniqueName = name + std::to_string(typeToFuncMap.size()); Function* F = dyn_cast(mod->getOrInsertFunction(uniqueName, funcType)); typeToFuncMap[funcType] = F; return F; } void runPasses(llvm::Function* F, const std::vector& passes) { legacy::FunctionPassManager FPM(F->getParent()); for (Pass* pass : passes) FPM.add(pass); FPM.doInitialization(); FPM.run(*F); FPM.doFinalization(); }