LLVM C++ Library: allocate, store and load

Joshua Brunhuber
joshtastic-blog
Published in
2 min readFeb 25, 2016

Today I want to explain you how to allocate, store and load variables using the LLVM Library for C++.

Assume we have the following case:

int a = 5;
print(a);

Variable declaration

At first we have to allocate memory for our variable a. This can be done with an alloca-instruction. It will allocate the memory we need on the stack.

Let’s tell llvm how much space we have to allocate. In our example we have a simple int (32bit or 4 byte).

llvm::Type *type = llvm::Type::getInt32Ty(llvm::getGlobalContext());

Then create an alloca-instruction in our current block (insert_point):

llvm::AllocaInst *llvm_alloca_inst = new llvm::AllocaInst(type, "a", insert_point);

Now we have an instance of an alloca-instruction with the type-information, the name of our variable and the block in which llvm will insert the bytecode.

The llvm_alloca_inst variable is also the pointer to the address where llvm allocated the memory for our int.

Note: In a real application we can save the alloca instruction in a symbol table. This can be done with a map for example. For the key we can use the identifier of our variable and as value we can set the alloca instruction so we’re able to load and store the variable from everywhere in our compiler.

Variable initialisation

To store our value in the allocated space we need a store instruction.

new llvm::StoreInst(llvm_emitted_assignment_value, symbol->llvm_ptr, false, insert_point);

The llvm_emitted_assignment_value is the emitted llvm::Value which contains the actual value of the int variable. The next argument is the pointer to the alloca-instruction we created in the last step. It tells llvm where it should store the value. Then we say that the variable isn’t volatile and it should insert the code in our insert_block.

Load a value

In our example on the top of the page we have a print function and pass the variable as parameter. So we want to load the variable as a parameter value. The emitIdentifierExpression() will return us an identifier. Then we have to load the value behind the identifier.

llvm::Value *llvm_parameter_value = emitIdentifierExpression();

In the next step we check if the emitted value is an internal llvm pointer. I just want to ensure that the emitIdentifierExpression() returned the right type.

llvm_parameter_value->getType()->isPointerTy()

If the check returns true we assign the real value behind it. There we finally use the load instruction.

llvm_parameter_value = builder->CreateLoad(llvm_parameter_value);

Note: builder is the instance of the IRBuilder

Now the llvm_parameter_value contains actual value. So we can pass it to our function and print the number.

--

--

Joshua Brunhuber
joshtastic-blog

iOS Developer📱 Nature🌲🍂 I also like music 🎸 and photography 📷