I am trying to declare local variable and set the value on my own using c++ API. The closest thing I found is this
auto AI = new AllocaInst(llvm::Type::getInt32Ty(context), 0, "local", entry);
entry is a BasicBlock. However it just produces %local = alloca i32 and not the value. How can I change its value?
Related
Starting with the caleidoscope tutorial and a stack exchange question (question) I tried to output some array-creation and access code with LLVM. The idea is to have an "alloca" stack variable "a" which holds a double* pointing to an array allocated with malloc.
The generated code fails, and I believe that the main problem is my Call to "CreateInBoundsGEP" in C++.
So my main question in one sentence is "How to Call CreateInBoundsGEP so that it outputs the right IR code?"
What i tried is the following:
My allocation code is created as output of the llvm c++ interface's "CreateMalloc" call from the question referenced above.
%a = alloca double*, align 8
%malloccall = tail call i8* #malloc(i32 48)
%0 = bitcast i8* %malloccall to double*
store double* %0, double** %a, align 8
This code looks good to me, but it already leads to an error/warning when checked with verifyFunction().
Call parameter type does not match function signature!
i32 48
Sadly it does not tell me, what the right parameter type would be (i64?). The IR reference does not refer to the "malloc"-function call at all but mentions a "malloc" IR-operation instead (reference)!
My main problem (also leading to memory errors if not caught before) occurs with write access to the array.
My first try was copying (more or less) directly from the referenced stack exchange question 1:
//ret is the base adress of the pointer, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* to the array index
auto element_ptr = Builder->CreateInBoundsGEP(ret, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);
Which outputs (for a[1]=5 as input code)
%acc_tmp = getelementptr inbounds double*, double** %a, i32 1
store double 5.000000e+00, double** %acc_tmp, align 8
This creates a "verifyFunction" error and I can see that "double**" should probably be "double*".
Since I also got a deprecation warning, I decided to try the CreateInBoundsGEP with a type parameter.
Since the documentation does not tell me whether "Type" should be the element or pointer type, I tried both
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType()->getPointerTo(), ret, index, "acc_tmp");
Or
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret, index, "acc_tmp");
Both do not work, the first version outputs the same code as without passing a type, the second version leads to
static llvm::GetElementPtrInst *llvm::GetElementPtrInst::Create(llvm::Type *, llvm::Value *, ArrayRef<llvm::Value *>, const llvm::Twine &, llvm::Instruction *): Assertion `cast<PointerType>(Ptr->getType()->getScalarType()) ->isOpaqueOrPointeeTypeMatches(PointeeType)' failed.
As I noticed in my original question, there is one pointer* too much in my instruction. Initially I did not understand why this is the case, but then I found the answer to my problem in a seemingly unrelated question 1:
If you directly use the return value of "CreateMalloc" as argument for a "CreateInBoundsGEP", the Code that I originally copied from 2 will work.
However in my case there is one more step involved: I store the "CreateMalloc" return value in a local variable, which in turn is referenced by a pointer allocated with "alloca". Because of this, I need one additional dereferencing step compared to the original Code Snippet to access my array elements.
As mentioned in 1 a dereference in LLVM-IR is just a "load". So a correct array access code looks like
//ret is the pointer to(!) the base adress of the array, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* holding the array index
llvm::Value* index = visit(ctx->index).as<llvm::Value*>();
llvm::Value* ret_deref = Builder->CreateLoad(llvm::Type::getDoubleTy(*TheContext)->getPointerTo(),ret,"deref_tmp");
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret_deref, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);
I'm trying to store the value of a global variable into a local variable in a function in my custom LLVM Pass.
the global variable is defined as
GlobalVariable* gvar_int32_test = new GlobalVariable(
/*Module=*/ M,
/*Type=*/ IntegerType::get(M.getContext(), 32),
/*isConstant=*/ false,
/*Linkage=*/ GlobalValue::CommonLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"global_test_var");
gvar_int32_test->setAlignment(4);
The local variable I intend to store into is originally being used as the store location for a call instruction. I attempt to get this value using
Value* localVar = ci->getOperand(0) //ci is the call instruction
using an IR builder, I attempt to write a store instruction as:
StoreInst* strLocIns = builder.CreateStore(gvar_int32_test, localVar, false);
//my intent is to create an instruction that means localvar = globalvar;
Similarly, earlier in the code I attempt to store the value in the return instruction of a called function to the global variable
Value* value = ri->getReturnValue(); //ri is the return instruction
// Some more code, including setting the IR builder insertion point
StoreInst* strIns = builder.CreateStore(value, gvar_int32_test, false);
//here the intention is globalvar = localvar
when I try to compile my with my pass included, I get the error:
Store operand must be a pointer.
store i32* #global_test_var, i32 %5
I'm not sure what I am doing wrong. Both of the arguments for the variables that I pass to the IR builder are pointers, but the IR is somehow broken. I think that i32 %5 should be i32* %5 to indicate that %5 points to an i32, but I don't know how to fix my code to make that happen. How do I fix this error?
Swap the operands of store: first is what and second - where.
I want to store data about each stack memory that is being allocated and changed.
To do so, I thought I'd need a data structure of some sort in which I can store the related data, such as the value of the local variable, and any change of it, e.g. before a store instruction.
Moreover, I should be able to check the value with the one saved in the data structure before any read of the local variable (e.g. load instruction).
If we assume that the IR looks like this
%1 = alloca i32,
[...]
%20 = store i32 0, %1
I need to change the above code to look like the below
%18 = call __Checking
%19 = <storing the return value from __Checking into a data structure>
%20 = store i32 0, %1
My problem is I cannot figure out how to store the returned value from the library called __Checking into a StructType I defined at the beginning.
My relevant code
if (StoreInst *SI = dyn_cast<StoreInst>(&I)){
Value* newValue = IRB.CreateCall(....);
Type* strTy[] = { Type::getInt64Ty(m.getContext()),
Type::getInt64Ty(m.getContext()) };
Type* t = StructType::create(strTy);
}
You didn't provide any specific information on the type returned by __Checking (or even where does __Checking come from) and the internals of the StructType, so I'm going to suggest to abstract that behaviour away in a runtime library (most likely in C).
This will allow you to setup function calls in those parts of the IR that you require to store (or compare, etc.) a value. The function(s) would take as arguments the value and the StructType (and anything else required) and perform the desired action in plain C (e.g. store the value).
For example, using part of your posted IR (names prefixed with myruntime_ should be defined in your runtime library):
%0 = alloca %myruntime_struct
[...]
%18 = call #__Checking
%19 = call #myruntime_storevalue(%2, %18, /* other arguments? */)
%20 = store i32 0, %1
I'm new to llvm and I'm writing a small llvm IR Builder.
I use the IRBuilder and all these Create* functions to generate my IR.
What I'm trying to do is to create a load instruction which create a new SSA local variable with value of a previously allocated llvm::Value.
What I expected to have :
%2 = load i32* %1
With %2 results of load instruction and %1 my previously allocated Value (CreateAlloca)
Here is what I tried :
// Get Ptr from Val
Value* ptr = ConstantExpr::getIntToPtr((Constant*)loc[n],PointerType::getUnqual(builder->getInt32Ty()));
// Générate load instruction with the new Ptr
builder->CreateLoad(ptr);
And here is what I have :
%2 = load i32* null
loc is an array which contains all my llvm::Value*
Can you please tell me what I'm doing wrong ? Or maybe if I'm on a bad way ?
Thanks.
ConstantExpr::getIntToPtr() creates a constant expression. So in effect, what you're trying to generate is equivalent to this IR:
%2 = load i32* inttoptr (i32 %1 to i32*)
But this is illegal since a constant expression, as hinted by its name, only supports constants, and %1 isn't a constant. ConstantExpr::getIntToPtr() requires a Constant as a first argument to verify it, but you passed it a non-constant value which was forcefully cast to a constant.
The correct way to convert a non-constant integer to a pointer is with IRBuilder::createIntToPtr. However, since you say the previous value (loc[n]) was created via an alloca then it's already a pointer, and you don't need to perform any conversion: just do builder->CreateLoad(loc[n]).
By the way, the proper way to cast a Value to a Constant in LLVM is not via a c-style cast but via cast<>, like so: cast<Constant>(loc[n]).
I'm planning to create a data structure optimized to hold assembly code. That way I can be totally responsible for the optimization algorithms that will be working on this structure. If I can compile while running. It will be kind of dynamic execution. Is this possible? Have any one seen something like this?
Should I use structs to link the structure into a program flow. Are objects better?
struct asm_code {
int type;
int value;
int optimized;
asm_code *next_to_execute;
} asm_imp;
Update: I think it will turn out, like a linked list.
Update: I know there are other compilers out there. But this is a military top secret project. So we can't trust any code. We have to do it all by ourselves.
Update: OK, I think I will just generate basic i386 machine code. But how do I jump into my memory blob when it is finished?
It is possible. Dynamic code generation is even mainstream in some areas like software rendering and graphics. You find a lot of use in all kinds of script languages, in dynamic compilation of byte-code in machine code (.NET, Java, as far as I know Perl. Recently JavaScript joined the club as well).
You also find it used in very math-heavy applications as well, It makes a difference if you for example remove all multiplication with zero out of a matrix multiplication if you plan to do such a multiplication several thousand times.
I strongly suggest that you read on the SSA representation of code. That's a representation where each primitive is turned into the so called three operand form, and each variable is only assigned once (hence the same Static Single Assignment form).
You can run high order optimizations on such code, and it's straight forward to turn that code into executable code. You won't write that code-generation backend on a weekend though...
To get a feeling how the SSA looks like you can try out the LLVM compiler. On their web-site they have a little "Try Out" widget to play with. You paste C code into a window and you get something out that is close to the SSA form.
Little example how it looks like:
Lets take this integer square root algorithm in C. (arbitrary example, I just took something simple yet non-trivial):
unsigned int isqrt32 (unsigned int value)
{
unsigned int g = 0;
unsigned int bshift = 15;
unsigned int b = 1<<bshift;
do {
unsigned int temp = (g+g+b)<<bshift;
if (value >= temp) {
g += b;
value -= temp;
}
b>>=1;
} while (bshift--);
return g;
}
LLVM turns it into:
define i32 #isqrt32(i32 %value) nounwind {
entry:
br label %bb
bb: ; preds = %bb, %entry
%indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ]
%b.0 = phi i32 [ 32768, %entry ], [ %tmp23, %bb ]
%g.1 = phi i32 [ 0, %entry ], [ %g.0, %bb ]
%value_addr.1 = phi i32 [ %value, %entry ], [ %value_addr.0, %bb ]
%bshift.0 = sub i32 15, %indvar
%tmp5 = shl i32 %g.1, 1
%tmp7 = add i32 %tmp5, %b.0
%tmp9 = shl i32 %tmp7, %bshift.0
%tmp12 = icmp ult i32 %value_addr.1, %tmp9
%tmp17 = select i1 %tmp12, i32 0, i32 %b.0
%g.0 = add i32 %tmp17, %g.1
%tmp20 = select i1 %tmp12, i32 0, i32 %tmp9
%value_addr.0 = sub i32 %value_addr.1, %tmp20
%tmp23 = lshr i32 %b.0, 1
%indvar.next = add i32 %indvar, 1
%exitcond = icmp eq i32 %indvar.next, 16
br i1 %exitcond, label %bb30, label %bb
bb30: ; preds = %bb
ret i32 %g.0
}
I know it looks horrible at first. It's not even pure SSA-Form. The more you read on that representation the more sense it will make. And you will also find out why this representation is so widely used these days.
Encapsulating all the info you need into a data-structure is easy. In the end you have to decide if you want to use enums or strings for opcode names ect.
Btw - I know I didn't gave you a data-structure but more a formal yet practical language and the advice where to look further.
It's a very nice and interesting research field.
Edit: And before I forget it: Don't overlook the built in features of .NET and Java. These languates allow you to compile from byte-code or source code from within the program and execute the result.
Cheers,
Nils
Regarding your edit: How to execute a binary blob with code:
Jumping into your binary blob is OS and platform dependent. In a nutshell you have invalide the instruction cache, maybe you have to writeback the data-cache and you may have to enable execution rights on the memory-region you've wrote your code into.
On win32 it's relative easy as instruction cache flushing seems to be sufficient if you place your code on the heap.
You can use this stub to get started:
typedef void (* voidfunc) (void);
void * generate_code (void)
{
// reserve some space
unsigned char * buffer = (unsigned char *) malloc (1024);
// write a single RET-instruction
buffer[0] = 0xc3;
return buffer;
}
int main (int argc, char **args)
{
// generate some code:
voidfunc func = (voidfunc) generate_code();
// flush instruction cache:
FlushInstructionCache(GetCurrentProcess(), func, 1024);
// execute the code (it does nothing atm)
func();
// free memory and exit.
free (func);
}
I assume you want a data structure to hold some kind of instruction template, probably parsed from existing machine code, similar to:
add r1, r2, <int>
You will have an array of this structure and you will perform some optimization on this array, probably changing its size or building a new one, and generate corresponding machine code.
If your target machine uses variable width instructions (x86 for example), you can't determine your array size without actually finishing parsing the instructions which you build the array from. Also you can't determine exactly how much buffer you need before actually generating all the instructions from optimized array. You can make a good estimate though.
Check out GNU Lightning. It may be useful to you.
In 99% of the cases, the difference in performance is negligible. The main advantage of classes is that the code produced by OOP is better and easier to understand than procedural code.
I'm not sure in what language you're coding - note that in C# the major difference between classes and structs is that structs are value types while classes are reference types. In this case, you might want to start with structs, but still add behavior (constructor, methods) to them.
Not discussing the technical value of optimize yourself your code, in a C++ code, choosing between a POD struct or a full object is mostly a point of encapsulation.
Inlining the code will let the compiler optimize (or not) the constructors/accessors used. There will be no loss of performance.
First, set a constructor
If you're working with a C++ compiler, create at least one constructor:
struct asm_code {
asm_code()
: type(0), value(0), optimized(0) {}
asm_code(int type_, int value_, int optimized_)
: type(type_), value(value_), optimized(_optimized) {}
int type;
int value;
int optimized;
};
At least, you won't have undefined structs in your code.
Are every combination of data possible?
Using a struct like you use means that any type is possible, with any value, and any optimized. For example, if I set type = 25, value = 1205 and optimized = -500, then it is Ok.
If you don't want the user to put random values inside your structure, add inline accessors:
struct asm_code {
int getType() { return type ; }
void setType(int type_) { VERIFY_TYPE(type_) ; type = type_ ; }
// Etc.
private :
int type;
int value;
int optimized;
};
This will let you control what is set inside your structure, and debug your code more easily (or even do runtime verification of you code)
After some reading, my conclusion is that common lisp is the best fit for this task.
With lisp macros I have enormous power.