blob: 6ceea0096ece95747401ef8fdbb40d03ee328350 [file] [log] [blame] [edit]
#include "llvm/Analysis/CFGPrinter.h" // needed for DOTGraphTraits<const Function*>
#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/GraphWriter.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
std::vector<CallInst *> getCallsToFunction(Function *callee,
const Function *caller) {
std::vector<CallInst *> calls;
if (callee == nullptr)
return calls;
for (auto U = callee->user_begin(), UE = callee->user_end(); U != UE; ++U) {
CallInst *CI = dyn_cast<CallInst>(*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<Module> loadModuleFromAsmFile(LLVMContext &context,
const std::string &filename) {
SMDiagnostic err;
std::unique_ptr<Module> mod = parseIRFile(filename, err, context);
if (!mod) {
err.print(filename.c_str(), errs());
exit(1);
}
return mod;
}
std::unique_ptr<Module> loadModuleFromAsmString(LLVMContext &context,
const std::string &str) {
SMDiagnostic err;
MemoryBufferRef memBuffer(str, "id");
std::unique_ptr<Module> 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<FunctionType *, Function *> &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<Function>(mod->getOrInsertFunction(uniqueName, funcType));
typeToFuncMap[funcType] = F;
return F;
}
void runPasses(llvm::Function *F, const std::vector<llvm::Pass *> &passes) {
legacy::FunctionPassManager FPM(F->getParent());
for (Pass *pass : passes)
FPM.add(pass);
FPM.doInitialization();
FPM.run(*F);
FPM.doFinalization();
}