LLVM: simple example of a just-in-time compilation - c++

I'm learning LLVM and trying to compile a simple function:
int sum(int a, int b) {
return a+b;
};
on the fly.
So here's the code I have so far:
#include <string>
#include <vector>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
using namespace llvm;
static LLVMContext &Context = getGlobalContext();
static std::unique_ptr<Module> MyModule = make_unique<Module>("my compiler", Context);
Function *createFunc(IRBuilder<> &Builder, std::string Name) {
std::vector<Type*> Integers(2, Builder.getInt32Ty());
auto *funcType = FunctionType::get(Builder.getInt32Ty(), Integers, false);
auto *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, MyModule.get());
return fooFunc;
};
int main(int argc, char* argv[]) {
static IRBuilder<> Builder(Context);
auto *fooFunc = createFunc(Builder, "sum");
auto *entry = BasicBlock::Create(Context, "entry", fooFunc);
Builder.SetInsertPoint(entry);
// Fill the function body
auto args = fooFunc->arg_begin();
Value *arg1 = &(*args);
args = std::next(args);
Value *arg2 = &(*args);
auto *sum = Builder.CreateAdd(arg1, arg2, "tmp");
Builder.CreateRet(sum);
verifyFunction(*fooFunc);
// TODO: compile and run it
MyModule->dump();
return 0;
}
This compiles and when I run it I get the expected output:
; ModuleID = 'my compiler'
define i32 #sum(i32, i32) {
entry:
%tmp = add i32 %0, %1
ret i32 %tmp
}
just like in the tutorial.
But now I want to compile this function and run it from C++. I'm looking for the easiest way to do something like that:
auto compiledStuff = ...;
auto compiledFn = (int (*)(int, int))compiledStuff;
auto result = compiledFn(3, 8);
I've been digging through the official Kaleidoscope tutorial but the JIT tutorial is really complicated and seems to focus on optimizations and laziness while I still can't figure out how to easily compile a module and call a function from it.
Any help?

So, I've digged through the KaleidoscopeJIT and retrieved the most important pieces. First of all note that I'm using llvm-4.0. I've had lots of issues by not realizing how really incompatible 4.0 and lower versions are.
The code works with C++11. I'm using clang++-4.0 with following compilation flags:
llvm-config-4.0 --cxxflags --ldflags --system-libs --libs core engine
And now the entire code:
#include <string>
#include <vector>
#include <iostream>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h"
using namespace llvm;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
static LLVMContext Context;
static auto MyModule = make_unique<Module>("my compiler", Context);
Function *createFunc(IRBuilder<> &Builder, std::string Name) {
std::vector<Type*> Integers(2, Builder.getInt32Ty());
auto *funcType = FunctionType::get(Builder.getInt32Ty(), Integers, false);
auto *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, MyModule.get());
return fooFunc;
};
void updateBody(Function *fooFunc, IRBuilder<> &Builder) {
auto *entry = BasicBlock::Create(Context, "entry", fooFunc);
Builder.SetInsertPoint(entry);
auto args = fooFunc->arg_begin();
Value *arg1 = &(*args);
args = std::next(args);
Value *arg2 = &(*args);
auto *sum = Builder.CreateAdd(arg1, arg2, "tmp");
Builder.CreateRet(sum);
};
int main(int argc, char* argv[]) {
// Prepare the module
static IRBuilder<> Builder(Context);
auto *fooFunc = createFunc(Builder, "sum");
updateBody(fooFunc, Builder);
verifyFunction(*fooFunc);
// Initilaze native target
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
// Prepare jit layer
ObjLayerT ObjectLayer;
std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget());
DataLayout DL(TM->createDataLayout());
CompileLayerT CompileLayer(ObjectLayer, orc::SimpleCompiler(*TM));
auto Resolver = orc::createLambdaResolver(
[&](const std::string &Name) {
if (auto Sym = CompileLayer.findSymbol(Name, false))
return Sym;
return JITSymbol(nullptr);
},
[](const std::string &S) { return nullptr; }
);
// Add MyModule to the jit layer
std::vector<std::unique_ptr<Module>> Modules;
Modules.push_back(std::move(MyModule));
CompileLayer.addModuleSet(
std::move(Modules),
make_unique<SectionMemoryManager>(),
std::move(Resolver)
);
// Retrieve the foo symbol
std::string MangledName;
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, "sum", DL);
auto Sym = CompileLayer.findSymbol(MangledNameStream.str(), true);
// Cast to function
auto func = (int(*)(int, int))Sym.getAddress();
// Try it
std::cout << func(5, 7) << std::endl;
return 0;
}
I'm not sure if all includes are needed but anyway it works like a charm. Although I'm looking forward for any comment on how to improve it. :)

Using the provided KaleidoscopeJIT.h this is pretty straightforward (I'm using LLVM 4.0.0 in this example):
// Your existing includes here.
#include "llvm/Support/TargetSelect.h" // For InitializeNativeTarget() etc.
#include "KaleidoscopeJIT.h"
int main() {
// Your existing main body here.
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
orc::KaleidoscopeJIT jit;
MyModule->setDataLayout(jit.getTargetMachine().createDataLayout());
auto moduleHandle = jit.addModule(std::move(MyModule)); // JIT-compile MyModule.
auto symbol = jit.findSymbol("sum"); // Get the compiled sum function.
auto sumFunc = (int(*)(int, int)) symbol.getAddress(); // Cast it.
auto result = sumFunc(42, 42); // Call it.
assert(result == 84); // VoilĂ .
}

Related

CompileLayerT::addModule crashed for no reason

I'm trying to create a llvm JIT in my code:
#include <iostream>
#include <vector>
#include <memory>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Verifier.h"
#include "KaleidoscopeJIT.h"
#include "llvm/Support/TargetSelect.h"
int main() {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
llvm::LLVMContext context;
llvm::orc::KaleidoscopeJIT jit;
auto module = std::make_unique<llvm::Module>("top", context);
llvm::IRBuilder<> builder(context);
module->setDataLayout(jit.getTargetMachine().createDataLayout());
llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getVoidTy(), false);
llvm::Function *mainFunc =
llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module.get());
llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "", mainFunc);
builder.SetInsertPoint(entry);
module->print(llvm::errs(), nullptr);
auto H = jit.addModule(std::move(module));
...
...
}
when comes to the addModule, the program crashed(interrupted by signal 11: SIGSEGV), I debugged the stack:
llvm::Instruction::getNumSuccessors() const 0x0000565102dbd7e0
llvm::BranchProbabilityInfo::updatePostDominatedByUnreachable(llvm::BasicBlock const*) 0x000056510361d797
llvm::BranchProbabilityInfo::calculate(llvm::Function const&, llvm::LoopInfo const&, llvm::TargetLibraryInfo const*) 0x00005651036220ef
llvm::BranchProbabilityInfoWrapperPass::runOnFunction(llvm::Function&) 0x00005651036225bd
llvm::FPPassManager::runOnFunction(llvm::Function&) 0x0000565102ddc640
llvm::FPPassManager::runOnModule(llvm::Module&) 0x0000565102ddc8b3
llvm::legacy::PassManagerImpl::run(llvm::Module&) 0x0000565102ddcc7e
llvm::orc::SimpleCompiler::operator() CompileUtils.h:68
llvm::orc::LegacyIRCompileLayer<llvm::orc::LegacyRTDyldObjectLinkingLayer, llvm::orc::SimpleCompiler>::addModule IRCompileLayer.h:84
llvm::orc::KaleidoscopeJIT::addModule KaleidoscopeJIT.h:66
main main.cpp:34
__libc_start_main 0x00007f8d8ee38b97
_start 0x0000565102cdc1ca
The KaleidoscopeJIT.h:
//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Contains a simple JIT definition for use in the kaleidoscope tutorials.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace llvm {
namespace orc {
class KaleidoscopeJIT {
public:
using ObjLayerT = LegacyRTDyldObjectLinkingLayer;
using CompileLayerT = LegacyIRCompileLayer<ObjLayerT, SimpleCompiler>;
KaleidoscopeJIT()
: Resolver(createLegacyLookupResolver(
ES,
[this](const std::string &Name) {
return ObjectLayer.findSymbol(Name, true);
},
[](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
TargetMachine &getTargetMachine() { return *TM; }
VModuleKey addModule(std::unique_ptr<Module> M) {
auto K = ES.allocateVModule();
cantFail(CompileLayer.addModule(K, std::move(M)));
ModuleKeys.push_back(K);
return K;
}
void removeModule(VModuleKey K) {
ModuleKeys.erase(find(ModuleKeys, K));
cantFail(CompileLayer.removeModule(K));
}
JITSymbol findSymbol(const std::string Name) {
return findMangledSymbol(mangle(Name));
}
private:
std::string mangle(const std::string &Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
JITSymbol findMangledSymbol(const std::string &Name) {
#ifdef _WIN32
// The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported
// flag to decide whether a symbol will be visible or not, when we call
// IRCompileLayer::findSymbolIn with ExportedSymbolsOnly set to true.
//
// But for Windows COFF objects, this flag is currently never set.
// For a potential solution see: https://reviews.llvm.org/rL258665
// For now, we allow non-exported symbols on Windows as a workaround.
const bool ExportedSymbolsOnly = false;
#else
const bool ExportedSymbolsOnly = true;
#endif
// Search modules in reverse order: from last added to first added.
// This is the opposite of the usual search order for dlsym, but makes more
// sense in a REPL where we want to bind to the newest available definition.
for (auto H : make_range(ModuleKeys.rbegin(), ModuleKeys.rend()))
if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly))
return Sym;
// If we can't find the symbol in the JIT, try looking in the host process.
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
#ifdef _WIN32
// For Windows retry without "_" at beginning, as RTDyldMemoryManager uses
// GetProcAddress and standard libraries like msvcrt.dll use names
// with and without "_" (for example "_itoa" but "sin").
if (Name.length() > 2 && Name[0] == '_')
if (auto SymAddr =
RTDyldMemoryManager::getSymbolAddressInProcess(Name.substr(1)))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
#endif
return nullptr;
}
ExecutionSession ES;
std::shared_ptr<SymbolResolver> Resolver;
std::unique_ptr<TargetMachine> TM;
const DataLayout DL;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
std::vector<VModuleKey> ModuleKeys;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
But if I run codes in https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl04.html, it works well, so I guess the environment is right.
Any idea why it crashed?
AlexDenisov's comment is right: BasicBlocks should end with terminator instructions. Try adding
builder.CreateRetVoid();
to your code between the call to builder.setInsertPoint and module->print.

How to save a modified llvm bitcode to a given filename?

I've successfully managed to modify a given input bitcode that
was read from a file as described in this SO post.
Now I want to save it to some output bitcode filename, with
something similar to saveIRFile(module,"myOutputBC.bc");.
Here is the main.cpp file I'm using, but I can't seem to find
the proper API to do the desired save.
/**********************/
/* LLVM INCLUDE FILES */
/**********************/
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IR/LLVMContext.h"
/**************/
/* NAMESPACES */
/**************/
using namespace std;
using namespace llvm;
int main(int argc, char **argv)
{
LLVMContext ctx;
SMDiagnostic Err;
unique_ptr<Module> M = parseIRFile(argv[1],Err,ctx);
if (M)
{
Module *module = M.get();
for (auto
func = module->begin();
func != module->end();
func++)
{
errs() << func->getName() << "\n";
// modify func's basic blocks ...
// and save with saveIRFile(module,"myOutputBC.bc");
}
}
return 0;
}
Any help is very much appreciated, thanks!
Something like this should do:
std::error_code ec;
ToolOutputFile result("myOutputBC.bc", ec, sys::fs::F_None);
WriteBitcodeToFile(*module, result.os());
result.keep();
Note that if you're using an old version of LLVM ToolOutputFile may be called tool_output_file.

failing to parse C++ using llvm and clang

I'm writing a little tool with llvm to parse C and C++ code, but I can't seem to get it to successfully parse C++ at all. I'm probably missing something obvious.
This is what I have so far:
#include <iostream>
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Parse/ParseAST.h"
class MyASTConsumer : public clang::ASTConsumer {
public:
bool HandleTopLevelDecl(clang::DeclGroupRef d);
virtual ~MyASTConsumer() { }
};
bool MyASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef d)
{
for(auto ii = d.begin(); ii != d.end(); ii++)
{
printf("decl type: %s\n", (*ii)->getDeclKindName());
auto namedDecl = llvm::dyn_cast<clang::NamedDecl>(*ii);
if(namedDecl)
{
printf("name: %s\n", namedDecl->getName().data());
}
}
return true;
}
int main(int, char **argv)
{
using clang::CompilerInstance;
using clang::TargetOptions;
using clang::TargetInfo;
using clang::FileEntry;
using clang::DiagnosticOptions;
using clang::TextDiagnosticPrinter;
using clang::SrcMgr::CharacteristicKind;
using clang::StringRef;
using clang::DirectoryLookup;
using llvm::MemoryBuffer;
using clang::LangOptions;
using clang::FrontendOptions;
using clang::LangStandard;
using clang::CompilerInvocation;
using clang::InitializePreprocessor;
using clang::Preprocessor;
using clang::PreprocessorOptions;
using clang::HeaderSearch;
using clang::HeaderSearchOptions;
CompilerInstance ci;
DiagnosticOptions diagnosticOptions;
ci.createDiagnostics();
CompilerInvocation *invocation = new CompilerInvocation;
LangOptions &langOpts = ci.getLangOpts();
langOpts.RTTI = 1;
langOpts.Bool = 1;
langOpts.CPlusPlus11 = 1;
langOpts.GNUKeywords = 1;
langOpts.CXXExceptions = 1;
langOpts.POSIXThreads = 1;
langOpts.SpellChecking = 1;
invocation->setLangDefaults(langOpts, clang::IK_CXX, LangStandard::lang_gnucxx11);
ci.setInvocation(invocation);
llvm::IntrusiveRefCntPtr<TargetOptions> pto( new TargetOptions() );
pto->Triple = llvm::sys::getDefaultTargetTriple();
llvm::IntrusiveRefCntPtr<TargetInfo> pti(TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr()));
ci.setTarget(pti.getPtr());
ci.createFileManager();
auto &fileManager = ci.getFileManager();
ci.createSourceManager(fileManager);
llvm::IntrusiveRefCntPtr<HeaderSearchOptions> headerSearchOpts( new HeaderSearchOptions() );
ci.createPreprocessor();
auto &pp = ci.getPreprocessor();
pp.setPredefines(builtinMacros);
HeaderSearch &headerSearch = pp.getHeaderSearchInfo();
for(auto &inc: builtinIncludePaths)
{
auto dirEntry = fileManager.getDirectory(StringRef(inc), true);
DirectoryLookup dirLookup(dirEntry, CharacteristicKind::C_System, false);
headerSearch.AddSearchPath (dirLookup, true);
}
MyASTConsumer *astConsumer = new MyASTConsumer();
ci.setASTConsumer(astConsumer);
ci.createASTContext();
const FileEntry *pFile = fileManager.getFile(argv[1]);
auto &sourceManager = ci.getSourceManager();
sourceManager.createMainFileID(pFile);
ci.getDiagnosticClient().BeginSourceFile(
ci.getLangOpts(),
&pp
);
clang::ParseAST(pp, astConsumer, ci.getASTContext());
ci.getDiagnosticClient().EndSourceFile();
return 0;
}
It does parse C just fine, but it errors out on the namespace keyword and extern "C" { blocks. So far I'm stumped. If anyone has a clue, something I'm missing, please share.
I believe I figured out the problem. You should always call setInvocation on the compiler instance before calling a lot of the methods on the compiler instance, as it actually just proxies to the invocation.
I moved the setInvocation call to right after the CompilerInvocation object is created, and things now work.

How to properly insert a function call using LLVM?

I'm trying to set up a pass that will insert a couple of global variables as well as a couple of function calls at the beginning of main. However, I believe I have an issue with setting up the function description correctly. My code compiles, but when I try to run the pass I get this error:
void llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, const llvm::Twine&):
Assertion `(Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy-
>getNumParams())) && "Calling a function with bad signature!"' failed.
Here is the code I have written so far:
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Module.h"
using namespace llvm;
namespace{
struct fun_insert : public FunctionPass{
static char ID;
fun_insert():FunctionPass(ID){}
virtual bool runOnFunction(Function &F){
if (F.getName() == "main"){
for (inst_iterator I = inst_begin(F), E= inst_end(F); I != E; ++I){
Instruction *inst = &*I;
if(dyn_cast<AllocaInst> (inst)){
errs() << "test" << "\n";
GlobalVariable *virtAddr = new GlobalVariable(*F.getParent(),
Type::getInt8PtrTy(F.getContext()), false,
GlobalValue::ExternalLinkage, 0, "virt_addr");
virtAddr->setAlignment(4);
Module *M = F.getParent();
Constant *c = M->getOrInsertFunction("open",
IntegerType::get(F.getContext(),32),
PointerType::get(Type::getInt8PtrTy(F.getContext(), 8),8),
IntegerType::get(F.getContext(),32), NULL);
Function *open = cast<Function>(c);
//ConstantInt *a = ConstantInt::get(M->getContext(), APInt(32, 9437184));
IRBuilder<> builder(inst);
Value *strPtr = builder.CreateGlobalStringPtr("/dev/mem", ".str");
ConstantInt *a = builder.getInt32(9437184);
//CallInst *openRet = builder.CreateCall2(open, strPtr, a, "open");
builder.CreateCall2(open, strPtr, a, "open");
}
errs() << *inst <<"\n";
}
}
return false;
}
};
}
char fun_insert::ID=0;
static RegisterPass<fun_insert>
X("fun_insert", "Insert Function Test", false, false);
Thanks for any help!
I believe I have resolved the issue. The issue did lie with the function declaration and call. I adjusted the code as follows:
Constant *c = M->getOrInsertFunction("open",
FunctionType::getInt32Ty(F.getContext()),
Type::getInt8PtrTy(F.getContext()),
Type::getInt32Ty(F.getContext()),
NULL);
Function *open = cast<Function>(c);
IRBuilder<> builder(inst);
Value *strPtr = builder.CreateGlobalStringPtr("/dev/mem", ".str");
ConstantInt *a = builder.getInt32(9437184);
builder.CreateCall2(open,strPtr,a);

segfault at the end of the main()

I am compiling a program agains LLVM-CLANG. This is the main
#include <iostream>
#include "CompilerFactory.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
int main(int argc, char const *argv[])
{
using clang::CompilerInstance;
using clang::TargetOptions;
using clang::TargetInfo;
using clang::FileEntry;
using clang::Token;
using clang::DiagnosticOptions;
using clang::TextDiagnosticPrinter;
CompilerInstance ci;
CSFV::CompilerFactory::GetCompilerInstance(ci);
const FileEntry *pFile = ci.getFileManager().getFile("test.c");
ci.getSourceManager().createMainFileID(pFile);
ci.getPreprocessor().EnterMainSourceFile();
ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(),
&ci.getPreprocessor());
Token tok;
do
{
ci.getPreprocessor().Lex(tok);
if (ci.getDiagnostics().hasErrorOccurred())
break;
ci.getPreprocessor().DumpToken(tok);
std::cerr << std::endl;
} while (tok.isNot(clang::tok::eof));
ci.getDiagnosticClient().EndSourceFile();
return 0;
}
and this is the included class
//If they are not defined we have an error at compile time
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include "llvm/Support/Host.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
namespace CSFV{
class CompilerFactory
{
public:
CompilerFactory();
~CompilerFactory();
/// \brief Generate and returns a compiler instance object
static void GetCompilerInstance(CompilerInstance &ci){
DiagnosticOptions diagOpts;
TextDiagnosticPrinter* diagPrinter =
new TextDiagnosticPrinter(llvm::outs(), &diagOpts, true);
ci.createDiagnostics(diagPrinter);
llvm::IntrusiveRefCntPtr<TargetOptions> pto (new TargetOptions());
pto->Triple = llvm::sys::getDefaultTargetTriple();
TargetInfo *pti =
TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr());
ci.setTarget(pti);
ci.createFileManager();
ci.createSourceManager(ci.getFileManager());
ci.createPreprocessor();
return;
}
};
} //end of namespace CSFV
For some reason I get a segfault at the end of the execution of the main. What am I missing?
I don't know if this is the same problem I had, but what I did was declare the targetoptions as a new pointer.
eg:
clang::TargetOptions *targetOpts=new clang::TargetOptions;
I have a feeling targetinfo cleans it up when itself is destroyed.