I am learning LLVM basics. I am trying to get into the builder framework and have set up the module, a function header etc, but I have not been able yet to figure out a way to create a simple sequence like this in builder:
%0 = 41
%1 = add i32 42, %0
Meaning how can I use the pseudo register notation through the builder framework?
I have tried to create a plus instruction based on two constants. The core line I'm using to generate the (integer) addition is:
Value *L = (Value *)m_left->Create_LLVM( );
Value *R = (Value *)m_right->Create_LLVM();
if ( L == 0 || R == 0 ) return 0;
llvm::Value *p_instruction = Get_Builder().CreateAdd( L, R, "addtmp" );
This contains lots of my own functions but I guess the basics is clear. I get a Value pointer for the left and right operands which are both constants and then create an add operation with the builder framwork. Again the module and builder are set up correctly, when I call dump() I see all the other stuff I do, but this line above does not create any IR code.
I would expect it co create something like
%4 = add i32 %3, %2
or something similar. Am I misunderstanding something fundamental about the way operations are to be constructed with the builder or is it just some small oversight of some detail?
Thanks
Hard to say what you are doing wrong without the fancy Create_LLVM()
functions but in general for adding two constants:
You have to create 2 ConstantInt
:
const auto& ctx = getGlobalContext(); // just your LLVMContext
auto* L = ConstantInt::get(Type::getInt32Ty(ctx), 41);
auto* R = ConstantInt::get(Type::getInt32Ty(ctx), 42);
const auto& builder = Get_Builder();
builder.Insert(L); // just a no-op in standard builder impl
builder.Insert(R); // just a no-op in standard builder impl
builder.CreateAdd(L, R, "addtmp");
You should get:
%addtmp = add i32 41, i32 42;
You said that your builder is set up correctly, so it will add the add
at the end of the BasicBlock
it currently operates on. And I assume you have allready created a Function
with at least one BasicBlock
.
Edit: What will bring give you an add instruction in any way is to create it just calling the C++ API without the builder:
BinaryOperator* add = BinaryOperator::Create(BinaryOps::Add, L, R, "addtmp", BB);
where BB is the current BasicBlock
.
To get something more sophisticated (adding to variables) the canonical way is this:
At first you need some memory. The AllocaInst
allocates memory on the stack:
You can use the builder for this:
auto* A = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "a");
auto* B = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "b");
For simplicity I'll just take the constants from above and store them in A and B.
To store values we need StoreInst
:
builder.CreateStore (L, A, /*isVolatile=*/false);
builder.CreateStore (R, B, /*isVolatile=*/false);
For the addition we load the value from memory to a register using LoadInst
:
auto* addLHS = builder.CreateLoad(A);
auto* addRHS = builder.CreateLoad(B);
Finally the addition as above: auto* add = builder.CreateAdd(addLHS, addRHS , "add");
And with the pointer to add you can go on, e.g., returning it or storing it to another variable.
The IR should look like this:
define i32 foo() {
entry:
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 41, i32* %a, align 4
store i32 42, i32* %b, align 4
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%add = add i32 %0, %1
ret i32 %add
}