I'm learning LLVM using the C++ API and am trying to figure out how to create structures and use them. The problem I'm running into is that when I try to allocate the structure, it seg faults.
llvm::LLVMContext ctx;
llvm::IRBuilder<> builder(ctx);
std::unique_ptr<llvm::Module> module;
std::vector<llvm::Type *> types;
types.push_back(llvm::Type::getInt16Ty(ctx));
auto structType = llvm::StructType::create(ctx, "Foo");
structType->setBody(types);
auto bb = llvm::BasicBlock::Create(ctx, "entry", nullptr);
builder.SetInsertPoint(bb);
builder.CreateAlloca(structType, nullptr, "alloctmp");
I'm obviously missing something simple. Why does the CreateAlloca call seg fault?
After getting a debug version, it was seg faulting in the CreateAlloca code because BasicBlock was null. So, I added a BasicBlock and now it's seg faulting because GlobalValue is null. How should that get set?
A couple important safety tips learned on this one.
A module must be created.
std::unique_ptr<llvm::Module> module(new llvm::Module("mod", ctx));
CreateAlloca allocates on the stack. Apparently there isn't one for top level stuff, so it has to be used within a function.
auto ft = llvm::FunctionType::get(structType, types, false);
auto fn = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, "func", module.get());
auto bb = llvm::BasicBlock::Create(ctx, "entry", fn);
Related
I am playing with llvm (and antlr), working vaguely along the lines of the Kaleidoscope tutorial. I successfully created LLVM-IR code from basic arithmetic expressions both on top-level and as function definitions, which corresponds to the tutorial chapters up to 3.
Now I would like to incrementally add JIT support, starting with the top-level arithmetic expressions. Here is my problem:
Basic comparison makes it seem as if I follow the same sequence of function calls as the tutorial, only with a simpler code organization
The generated IR code looks good
The function definition is apparently found, since otherwise the code would exit (i verified this by intentionally looking for a wrongly spelled function name)
However the call of the function pointer created by JIT evaluation always returns zero.
These snippets (excerpt) are executed as part of the antlr visitor of the main/entry-node of my grammar:
//Top node main -- top level expression
antlrcpp::Any visitMain(ExprParser::MainContext *ctx)
{
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
TheJIT = ExitOnErr( llvm::orc::KaleidoscopeJIT::Create() );
InitializeModuleAndPassManager();
// ... Code which visits the child nodes ...
}
InitializeModuleAndPassManager() is the same as in the tutorial:
static void InitializeModuleAndPassManager()
{
// Open a new context and module.
TheContext = std::make_unique<llvm::LLVMContext>();
TheModule = std::make_unique<llvm::Module>("commandline", *TheContext);
TheModule->setDataLayout(TheJIT->getDataLayout());
// Create a new builder for the module.
Builder = std::make_unique<llvm::IRBuilder<>>(*TheContext);
// Create a new pass manager attached to it.
TheFPM = std::make_unique<llvm::legacy::FunctionPassManager>(TheModule.get());
// Do simple "peephole" optimizations and bit-twiddling optzns.
TheFPM->add(llvm::createInstructionCombiningPass());
// Reassociate expressions.
TheFPM->add(llvm::createReassociatePass());
// Eliminate Common SubExpressions.
TheFPM->add(llvm::createGVNPass());
// Simplify the control flow graph (deleting unreachable blocks, etc).
TheFPM->add(llvm::createCFGSimplificationPass());
TheFPM->doInitialization();
}
This is the function which handles the top-level expression and which is also supposed to do JIT evaluation:
//Bare expression without function definition -- create anonymous function
antlrcpp::Any visitBareExpr(ExprParser::BareExprContext *ctx)
{
string fName = "__anon_expr";
llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getDoubleTy(*TheContext), false);
llvm::Function *F = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, fName, TheModule.get());
llvm::BasicBlock *BB = llvm::BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(BB);
llvm::Value* Expression=visit(ctx->expr()).as<llvm::Value* >();
Builder->CreateRet(Expression);
llvm::verifyFunction(*F);
//TheFPM->run(*F);//outcommented this because i wanted to try JIT before optimization-
//it causes a compile error right now because i probably lack some related code.
//However i do not assume that a missing optimization run will cause the problem that i have
F->print(llvm::errs());
// Create a ResourceTracker to track JIT'd memory allocated to our
// anonymous expression -- that way we can free it after executing.
auto RT = TheJIT->getMainJITDylib().createResourceTracker();
auto TSM = llvm::orc::ThreadSafeModule(move(TheModule), move(TheContext));
ExitOnErr(TheJIT->addModule(move(TSM), RT));
InitializeModuleAndPassManager();
// Search the JIT for the __anon_expr symbol.
auto ExprSymbol = ExitOnErr(TheJIT->lookup("__anon_expr"));
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double ret = FP();
fprintf(stderr, "Evaluated to %f\n", ret);
// Delete the anonymous expression module from the JIT.
ExitOnErr(RT->remove());
return F;
}
Now this is what happens as an example:
[robert#robert-ux330uak test4_expr_llvm_2]$ ./testmain '3*4'
define double #__anon_expr() {
entry:
ret float 1.200000e+01
}
Evaluated to 0.000000
I would be thankful for any ideas about what I might be doing wrong.
I'm writing a LLVM pass where I create a function with integer pointer arguments. I need to implement the body of the function as well, and in order to do so, I need the integer values that are being pointed to. I am trying to create a load instruction that I can insert at the end of the basic block that contains the function body, but I am getting an error when doing so. Things compile fine, but when I run the pass, I get a generic error.
From what I've found about LLVM, there are usually ways to create instructions that don't involve using constructors, but I couldn't find a way to do that for load instructions, so I just used one of the constructors instead. After creating the function with arguments of the integer pointer type, this is the code that I'm using to do the load:
llvm::LoadInst operandLoad(llvm::Type::getInt32Ty(ctx), argList[0], "test", basicBlock);
If I comment the above line out, my pass runs fine. I'm unsure whether this is enough to diagnose the issue, so I'll include all the code to create the function (it's slightly simplified):
void createFunction(std::string functionName, llvm::LLVMContext &ctx, llvm::Module *module) {
std::vector<llvm::Type*> typeList = {llvm::Type::getInt32PtrTy(ctx)};
// Create function type
llvm::FunctionType *functionType = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), typeList, false);
// Create function
llvm::Function *function = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, functionName, module);
std::vector<llvm::Value*> argList;
for (llvm::Function::arg_iterator it = function->arg_begin(); it != function->arg_end(); ++it) {
argList.push_back(it);
}
llvm::BasicBlock *basicBlock = llvm::BasicBlock::Create(ctx, "entry", function);
llvm::LoadInst operandLoad(llvm::Type::getInt32Ty(ctx), argList[0], "test", basicBlock);
llvm::IRBuilder<> builder(ctx);
builder.SetInsertPoint(basicBlock);
builder.CreateRet(nullptr);
}
I'm sure this is a stupid question, so sorry about that. And thanks in advance!
I write a function to create a empty basicblock:
BasicBlock* createEmptyBlock(){
llvm::LLVMContext context;
IRBuilder<> builder(context);
Function *mainFunction;
mainFunction->setDoesNotReturn();
BasicBlock* mainblock = BasicBlock::Create(context, "entrypoint", mainFunction);
return mainblock;
}
but when insert my instruction in the front of this mainblock:
Instruction *newBInst_0 = setBranchInst(F, inst, 1);//product a inst
llvm::BasicBlock *bb;
bb=createEmptyBlock();
newBInst_0->insertBefore(bb->front());//there are some errors
bb->insertInto(&F,&block);
I found some errors when I insert
What's wrong with this?
You should try to stop creating a context and builder instance each time you call createEmptyBlock. Just one context is required per thread and in general one builder instance so llvm helps you keep track of where to insert ir. This really helps with method calls such as builder.GetInsertBlock()
Also you don't need to attach a block to a function each time you create one. You're function could now look like this
BasicBlock* createEmptyBlock(){
BasicBlock* mainblock = BasicBlock::Create(context, "entrypoint");
return mainblock;
}
supposing you'd want all your block labels to be prefixed with "entrypoint". Plus, the function body is nearly a one-liner. Why not just inline it like so
Instruction *newBInst_0 = setBranchInst(F, inst, 1);//product a inst
llvm::BasicBlock *bb = BasicBlock::Create(context, "entrypoint");
bb->insertInto(&F,&block);
newBInst_0->insertBefore(bb->front());
supposing your builder and context instances are global variables (which I recommend they should).
It also looks like you're not using your builder instance much. Try exploring some of its methods such as builder.SetInsertPoint and builder.CreateCondBr
I have C++14 enabled in code (a Qt5 project) similar to the following:
auto func = [&](auto p, auto pp) {
if(!p)
return;
pp = p;
p->init();
this->member_function(pp->thing()); // replaces member_function(pp->thing());
};
MyClass *p1;
...
func(p1, m_p);
m_p->doSomething();
After receiving:
internal compiler error: Segmentation fault
Debugging I found m_pdid not change after the call to func, as I was expecting. Does generic lambda (auto) really works so? How do I go to change m_p in code like the above?
File a bug report in gcc's bugzilla. Whether your code is valid C++, or not, the compiler should not blow up with a segmentation fault.
Segmentation fault in the compiler is very bad, but have you tried using auto& pp? It looks like m_p is being passed by value, not reference.
Here is a node.js addon module I've written in C++ and built using node-gyp.
When StoreFunction I am trying to store a pointer to the function so I can use it later
When I try to invoke it later though in InvokeFunction I get a Segmentation fault. What baffled me if I examined the pointer in both functions (using cout) they are the same value.
So I'm guessing either the change of invoking context changes between calling the two functions or I don't understand what I'm pointing to.
All (ummmmmm) pointers gratefully received on my problem here..............
#include <node.h>
#include <v8.h>
using namespace v8;
v8::Persistent<v8::Function> callbackFunction;
Handle<Value> StoreFunction(const Arguments& args) {
HandleScope scope;
callbackFunction = *Local<Function>::Cast(args[0]);
return scope.Close(Undefined());
}
Handle<Value> InvokeFunction(const Arguments& args) {
HandleScope scope;
Local<Value> argv[1] = { String::New("Callback from InvokeFunction")};
callbackFunction->Call(Context::GetCurrent()->Global(), 1, argv);
return scope.Close(Undefined());
}
void init(Handle<Object> target) {
NODE_SET_METHOD(target, "StoreFunction", StoreFunction);
NODE_SET_METHOD(target, "InvokeFunction", InvokeFunction);
}
NODE_MODULE(someaddonmodule, init);
And of course some calling js...........
var myaddon = require('../build/Release/someaddonmodule');
myaddon.StoreFunction(function(data){
console.log("Called back: "+data);
});
myaddon.InvokeFunction(); //causes a segmentation fault
The answer is because we're not programming in Java any more Toto.
The pointer I created is pointing at the Local Handle, rather than the function. Holding a 'reference' to this isn't enough to stop the V8 garbage collection destroying it when the scope closes.
To deal with this an explicit request needs to be made to V8 to put aside some memory to hold
the function which done like this :
Persistent< Function > percy;
Local<Function> callbackFunction = Local<Function>::Cast(args[0]);
percy = Persistent<Function>::New(callbackFunction);
If anyone with a better understanding of V8 internals knows more than this, I'd still really like to hear your explanation :)