I'd like to generate LLVM IR for a C++ code like this:
T *arr = (T*) malloc(sizeof(T) * 100);
arr[0] = somevalue;
Here's my code:
llvm::Type* element_type = /... some T type .../;
llvm::Type* int32type = llvm::Type::getInt32Ty(context);
auto element_size = llvm::ConstantInt::get(int32type, data_layout.getTypeAllocSize(element_type));
auto array_size = llvm::ConstantInt::get(int32type, 100);
// malloc:
auto malloc_inst = llvm::CallInst::CreateMalloc(
ir_builder.GetInsertBlock(),
element_type->getPointerTo(), // T*
element_type, // T
element_size, // sizeof(T)
array_size, // 100
nullptr,
"")
ir_builder.Insert(malloc_inst);
// cast to T*:
auto arr = ir_builder.CreatePointerCast(malloc_inst, element_type->getPointerTo());
// arr[0] = somevalue:
llvm::Value *value = /... some value of type T .../
auto element_ptr = ir_builder.CreateInBoundsGEP(
arr, {
llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0)
});
ir_builder.CreateStore(value, element_ptr)
However, when running generated IR I'm getting:
Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), function checkGEPType, file /usr/local/opt/llvm/include/llvm/IR/Instructions.h, line 847
I tried different combinations of types passed to the GEP instruction, but it's obvious I'm missing something basic.
Can someone point me to a working example for this?
There were two issues:
First, to access element array there's no need to pass two indices into GEP instruction.
Second, 5th argument of CreateMalloc is casted to a pointer for some reason here. After doing the multiplication of element_size * array_size by myself everything worked.
Also, explicit pointer cast (from i8* to T*) was not needed as it happens automatically.
Here's the final working code:
llvm::Type* element_type = /... some T type .../;
llvm::Type* int32type = llvm::Type::getInt32Ty(context);
auto element_size = llvm::ConstantInt::get(int32type, data_layout.getTypeAllocSize(element_type));
auto array_size = llvm::ConstantInt::get(int32type, 100);
auto alloc_size = llvm::ConstantExpr::getMul(element_size, array_size);
// malloc:
auto arr = llvm::CallInst::CreateMalloc(
ir_builder.GetInsertBlock(),
element_type->getPointerTo(), // T*
element_type, // T
alloc_size, // sizeof(T) * 100
nullptr,
nullptr,
"")
ir_builder.Insert(arr);
// arr[0] = somevalue:
llvm::Value *value = /... some value of type T .../
auto element_ptr = ir_builder.CreateInBoundsGEP(
arr, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0));
ir_builder.CreateStore(value, element_ptr)
Related
I want to pass an array to LLVM IR Function, and get value by index. The code as follows, but it dont't work.
Function *FooF =
Function::Create(FunctionType::get(Type::getInt32Ty(Context), {ArrayType::getInt32PtrTy(Context), Type::getInt32Ty(Context)}, false),
Function::ExternalLinkage, "foo", M);
// Add a basic block to the FooF function.
BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FooF);
IRBuilder<> builder(BB);
// Get pointer to array
Value *arg1 = FooF->arg_begin();
// Get index
Value *index = arg1+1;
// Get first_element
Value *first_element = builder.CreateExtractElement(arg1, index);
builder.CreateRet(first_element);
// Now we create the JIT.
ExecutionEngine* EE = EngineBuilder(std::move(Owner)).create();
using FunctionPtr = int(*)(int32_t *, int);
FunctionPtr func = reinterpret_cast<FunctionPtr>(EE->getFunctionAddress("foo")) ;
int32_t array[3] = {1,2,3};
int first = func(array, 0);
}
I just started with LLVM. I am using C++ to create a compiler for Pascal-like language. Given that print functions are system calls, how do I map from my language writeln(5) to the system function printf ("%d",5)? I thought that code below should do it.
NamedValues.clear();
vector<Type *> Doubles(1, Type::getInt32Ty(TheContext));
FunctionType * FT = FunctionType::get(Type::getInt32Ty(TheContext), Doubles, false);
Function * function = Function::Create(FT, Function::ExternalLinkage, "writeln", TheModule.get());
// create function body
BasicBlock * BB = BasicBlock::Create(TheContext, "entry", function);
Builder.SetInsertPoint(BB);
// get param
Function::arg_iterator AI = function->arg_begin();
Value * val = AI;
AI->setName("val");
// get format string
string format = "%d";
Constant * ConstStr = ConstantDataArray::getString(TheContext, format.c_str());
ConstStr = new GlobalVariable(*TheModule, ConstStr->getType(), true, GlobalValue::InternalLinkage, ConstStr, format);
Constant * Idxs[] = {ConstantInt::get(Type::getInt32Ty(TheContext), 0), 0};
Idxs[1] = Idxs[0];
// make params
vector<Type *> params;
params.push_back(PointerType::getUnqual(Type::getInt8Ty(TheContext)));
// get printf function
FunctionCallee PrintF = TheModule->getOrInsertFunction("printf", FunctionType::get(Type::getVoidTy(TheContext), params, true));
// call
/*
* CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = None,
const Twine &Name = "", MDNode *FPMathTag = nullptr)
*/
Builder.CreateCall(PrintF.getFunctionType(), ConstantExpr::getGetElementPtr(ConstStr->getType(), ConstStr, Idxs), val);
Builder.CreateRet(Builder.getInt32(0));
main_loop();
Error I got:
Assertion failed: (Ty == cast<PointerType>(C->getType()->getScalarType())->getElementType()), function getGetElementPtr, file /Users/ustynov/Documents/Study/HOMEWORKS/semestralwork/llvm/lib/IR/Constants.cpp, line 2012.
I recently switched my project to using a linear memory allocator that I wrote myself (for learning). When I initialize the allocator, I pass it a pointer to a block of memory that was VirtualAlloc-ed beforehand. Before writing the allocator, I was using this block directly just fine.
In my test case, I am using the allocator to allocate memory for a Player* in that initial big block of memory. To make sure every was working, I tried accessing the block of memory directly as I had before to make sure the values were changing according to my expectations. That's when I hit a memory access error. Using the VS debugger/watch window, I have a reasonable idea of what is happening and when, but I am hoping to get some help with the question of why. I'll lay out the relevant pieces of code below.
Virtual Alloc call, later referred to by memory->transientStorage
win32_State.gameMemoryBlock = VirtualAlloc(baseAddress, (size_t)win32_State.totalSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
Allocator definition
struct LinearAllocator {
void* currentPos;
size_t totalSize;
void* startPos;
size_t usedMemory;
size_t numAllocations;
LinearAllocator();
LinearAllocator(size_t size, void* start);
LinearAllocator(LinearAllocator&) = delete;
~LinearAllocator();
void* allocate(size_t size, uint8 alignment);
void clear();
};
Player and Vec2f definitions
struct Player {
Vec2f pos;
bool32 isFiring;
real32 timeLastFiredMS;
};
union Vec2f {
struct {
real32 x, y;
};
real32 v[2];
};
Relevant Allocator Implementation Details
void* LinearAllocator::allocate(size_t size, uint8_t alignment) {
if (size == 0 || !isPowerOfTwo(alignment)) {
return nullptr;
}
uint8_t adjustment = alignForwardAdjustment(currentPos, alignment);
if (usedMemory + adjustment + size > totalSize) {
return nullptr;
}
uint8_t* alignedAddress = (uint8*)currentPos + adjustment;
currentPos = (void*)(alignedAddress + size);
usedMemory += size + adjustment;
numAllocations++;
return (void*)alignedAddress;
}
inline uint8_t alignForwardAdjustment(void* address, uint8_t alignment) {
uint8_t adjustment = alignment - ( (size_t)address & (size_t)(alignment - 1));
if (adjustment == alignment) {
return 0; // already aligned
}
return adjustment;
}
inline int32_t isPowerOfTwo(size_t value) {
return value != 0 && (value & (value - 1)) == 0;
}
Initialization code where I attempt to use allocator
// **Can write to memory fine here**
((float*)memory->transientStorage)[0] = 4.f;
size_t simulationAllocationSize = memory->transientStorageSize / 2 / sizeof(real32);
simulationMemory = LinearAllocator(simulationAllocationSize, &memory->transientStorage + (uint8_t)0);
for (int i = 0; i < MAX_PLAYERS; i++) {
Player* p = (Player*)simulationMemory.allocate(sizeof(Player), 4);
// **also works here**
((real32*)memory->transientStorage)[0] = 3.f;
p->pos.x = 0.f; // **after this line, I got the unable to read memory error**
p->pos.y = 0.f;
p->isFiring = false;
p->timeLastFiredMS = 0.f;
// **can't write **
((real32*)memory->transientStorage)[0] = 1.f;
}
// **also can't write**
((real32*)memory->transientStorage)[0] = 2.f;
real32 test = ((real32*)memory->transientStorage)[0];
My running assumption is that I'm missing something obvious. But the only clue I have to go off of is that it changed after setting a value in the Player struct. Any help here would be greatly appreciated!
Looks like this is your problem:
simulationMemory = LinearAllocator(simulationAllocationSize,
&memory->transientStorage + (uint8_t)0);
There's a stray & operator, causing you to allocate memory not from the allocated memory block that memory->transientStorage points to but from wherever memory itself lives.
This is turns causes the write to p->pos.x to overwrite the value of transientStorage.
The call to LinearAllocator should be just
simulationMemory = LinearAllocator(simulationAllocationSize,
memory->transientStorage + (uint8_t)0);
I'm trying to use the LLVM C++ bindings to write a pass which generates the following IR
%1 = call i64 #time(i64* null) #3
#time here is the C standard library time() function.
Here's the code I've written
void Pass::Insert(BasicBlock *bb, Type *timety, Module *m) {
Type *timetype[1];
timetype[0] = timety;
ArrayRef<Type *> timeTypeAref(timetype, 1);
Value *args[1];
args[0] = ConstantInt::get(timety, 0, false);
ArrayRef<Value *> argsRef(args, 1);
FunctionType *signature = FunctionType::get(timety, false);
Function *timeFunc =
Function::Create(signature, Function::ExternalLinkage, "time", m);
IRBuilder<> Builder(&*(bb->getFirstInsertionPt()));
AllocaInst *a1 = Builder.CreateAlloca(timety, nullptr, Twine("a1"));
CallInst *c1 = Builder.CreateCall(timeFunc, args, Twine("time"));
}
This compiles, but results in the following error when run
Incorrect number of arguments passed to called function!
%time = call i64 #time(i64 0)
As I understand this, I need to pass an int64 pointer which deferences to nullptr, but I'm unable to figure out how to do that.
LLVM provides a ConstantPointerNull class which does exactly what I want - it returns a null pointer of the required type.
All that needs to be changed is the line beginning with args[0] = ... to
args[0] = ConstantPointerNull::get(PointerType::get(timety, 0));.
I am working on an example from the LLVM Essentials book. The section is called Emitting if-else condition IR, and I keep getting the following error.
Assertion failed: (getOperand(0)->getType() == getOperand(1)->getType()
&& "Both operands to ICmp instruction are not of the same type!"),
function AssertOK,
file /usr/local/Cellar/llvm/3.6.2/include/llvm/IR/Instructions.h, line
997. Abort trap: 6
I've spent hours trying to figure this out, but I'm at my wit's end. I'm sure it's something minor, but I have no idea. The code I am using is below.
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include <vector>
#include <iostream>
#include <typeinfo>
using namespace llvm;
static LLVMContext &Context = getGlobalContext();
static Module *ModuleOb = new Module("my compiler", Context);
static std::vector<std::string> FunArgs;
typedef SmallVector<BasicBlock *, 16> BBList;
typedef SmallVector<Value *, 16> ValList;
Function *createFunc(IRBuilder<> &Builder, std::string Name) {
std::vector<Type *> Integers(FunArgs.size(), Type::getInt32Ty(Context));
FunctionType *funcType =
llvm::FunctionType::get(Builder.getInt32Ty(), Integers, false);
Function *fooFunc = llvm::Function::Create(
funcType, llvm::Function::ExternalLinkage, Name, ModuleOb);
return fooFunc;
}
void setFuncArgs(Function *fooFunc, std::vector<std::string> FunArgs) {
unsigned Idx = 0;
Function::arg_iterator AI, AE;
for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE;
++AI, ++Idx)
AI->setName(FunArgs[Idx]);
}
BasicBlock *createBB(Function *fooFunc, std::string Name) {
return BasicBlock::Create(Context, Name, fooFunc);
}
GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) {
ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty());
GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name);
gVar->setLinkage(GlobalValue::CommonLinkage);
gVar->setAlignment(4);
return gVar;
}
Value *createArith(IRBuilder<> &Builder, Value *L, Value *R) {
return Builder.CreateMul(L, R, "multmp");
}
Value *createIfElse(IRBuilder<> &Builder, BBList List, ValList VL) {
Value *Condtn = VL[0];
Value *Arg1 = VL[1];
BasicBlock *ThenBB = List[0];
BasicBlock *ElseBB = List[1];
BasicBlock *MergeBB = List[2];
Builder.CreateCondBr(Condtn, ThenBB, ElseBB);
Builder.SetInsertPoint(ThenBB);
Value *ThenVal = Builder.CreateAdd(Arg1, Builder.getInt32(1), "thenaddtmp");
Builder.CreateBr(MergeBB);
Builder.SetInsertPoint(ElseBB);
Value *ElseVal = Builder.CreateAdd(Arg1, Builder.getInt32(2), "elseaddtmp");
Builder.CreateBr(MergeBB);
unsigned PhiBBSize = List.size() - 1;
Builder.SetInsertPoint(MergeBB);
PHINode *Phi = Builder.CreatePHI(Type::getInt32Ty(getGlobalContext()), PhiBBSize, "iftmp");
Phi->addIncoming(ThenVal, ThenBB);
Phi->addIncoming(ElseVal, ElseBB);
return Phi;
}
int main(int argc, char *argv[]) {
FunArgs.push_back("a");
FunArgs.push_back("b");
static IRBuilder<> Builder(Context);
GlobalVariable *gVar = createGlob(Builder, "x");
Function *fooFunc = createFunc(Builder, "foo");
setFuncArgs(fooFunc, FunArgs);
BasicBlock *entry = createBB(fooFunc, "entry");
Builder.SetInsertPoint(entry);
Value *Arg1 = fooFunc->arg_begin();
Value *constant = Builder.getInt32(16);
Value *val = createArith(Builder, Arg1, constant);
Value *val2 = Builder.getInt32(100);
Value *Compare = Builder.CreateICmpULT(val, val2, "cmptmp");
Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond");
ValList VL;
VL.push_back(Condtn);
VL.push_back(Arg1);
BasicBlock *ThenBB = createBB(fooFunc, "then");
BasicBlock *ElseBB = createBB(fooFunc, "else");
BasicBlock *MergeBB = createBB(fooFunc, "ifcont");
BBList List;
List.push_back(ThenBB);
List.push_back(ElseBB);
List.push_back(MergeBB);
Value *v = createIfElse(Builder, List, VL);
Builder.CreateRet(v);
verifyFunction(*fooFunc);
ModuleOb->dump();
return 0;
}
I know the issue is occurring at this location. I've tried to dynamically cast both to the same type, but still not compiling.
Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond");
The problem is with these two lines:
Value *Compare = Builder.CreateICmpULT(val, val2, "cmptmp");
Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond");
The first icmp instruction evaluates to a value of type i1, and you're trying to compare that to a value of type i32.
Your best bet would be to avoid the second icmp altogether, as it's superfluous (it will evaluate to the same value as Compare). Just use Compare as your condition.
Otherwise, you'd have to make sure the types match -- in this case you can just use Builder.getInt1(false) instead of Builder.getInt32(0). More generally you might use Builder.CreateIntCast to insert trunc or zext or sext instructions as needed.