Passing an array to an external function - c++

I am new to LLVM, and I am learning how to use LLVM for profiling. I need to pass an array to an external method, and insert a call instruction to the method in the code. I am currently using the following code, which on execution gives a segmentation fault.
std::vector<Value*> Args(1);
//Vector with array values
SmallVector<Constant*, 2> counts;
counts.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),32, false));
counts.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),12, false));
//Array with 2 integers
Args[0]= ConstantArray::get(llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2), counts);
Here, the external function 'hook' is defined as M.getOrInsertFunction("hook", Type::getVoidTy(M.getContext()),
llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2)
(Type*)0);
After reading a few source files, I've tried using GetElementPtrInst to pass the array
std::vector<Value*> ids(1);
ids.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),0));
Constant* array = ConstantArray::get(llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2), counts);
Args[0] = ConstantExpr::getGetElementPtr(&(*array), ids, false);
but it fails with
7 opt 0x00000000006c59f5 bool llvm::isa<llvm::Constant, llvm::Value*>(llvm::Value* const&) + 24
8 opt 0x00000000006c5a0f llvm::cast_retty<llvm::Constant, llvm::Value*>::ret_type llvm::cast<llvm::Constant, llvm::Value*>(llvm::Value* const&) + 24
9 opt 0x0000000000b2b22f
10 opt 0x0000000000b2a4fe llvm::ConstantFoldGetElementPtr(llvm::Constant*, bool, llvm::ArrayRef<llvm::Value*>) + 55
11 opt 0x0000000000b33df2 llvm::ConstantExpr::getGetElementPtr(llvm::Constant*, llvm::ArrayRef<llvm::Value*>, bool) + 82
Also, in this case, 'hook' is defined as M.getOrInsertFunction("hook", Type::getVoidTy(M.getContext()),
PointerType::get(Type::getInt32PtrTy(M.getContext()),0), //when using GEP
(Type*)0);
Could someone kindly keep me a few pointers on passing arrays to an external function (say with the signature void hook(int abc[]) ). I am probably wrong all the way through, and would really appreciate some help.

A good place to start with "how do I do this c-like thing in LLVM IR" questions is to first write what you want to do in C, then compile it to LLVM IR via Clang and take a look at the result.
In your particular instance, the file:
void f(int a[2]);
void g() {
int x[2];
x[0] = 1;
x[1] = 3;
f(x);
}
Will compile to:
define void #g() nounwind {
%x = alloca [2 x i32], align 4
%1 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 0
store i32 1, i32* %1, align 4
%2 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 1
store i32 3, i32* %2, align 4
%3 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 0
call void #f(i32* %3)
ret void
}
declare void #f(i32*)
So we can see the clang compiled g to receive i32*, not an array. That means you need a way to get an address to the first element of the array from the array itself, and a getelementptr instruction is a straightforward way of doing that.
Notice, however, that you want to generate a GEP (getelementptr instruction), for example via GetElementPtrInst::create. A gep constant expression, which is what you're trying to generate here, is something else, and will only work on compile-time constants.

You should use Clang to compile it. Then, check the boundaries of the array and if all the elements are defined.

Related

llvm - Access And Call Function Pointer In A Global Array Without Horrible Pointer Hacking

I am having quite some trouble programmatically accessing a function pointer in a global array programmatically. I have a global array of function pointers, my "lookup table" which I basically I am using for "overloads". Every time I try to GetElementPointer (GEP)/getelementptr an element in this array with the desired type, I get a runtime assertion:
warp_compiler: /root/.conan/data/llvm-core/13.0.0/_/_/package /6efbb14f313e71b5e1dbf77c1c011f47614b7c7c/include/llvm/IR/
Instructions.h:960: static llvm::GetElementPtrInst* llvm::GetElementPtrInst::Create(
llvm::Type*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, const llvm::Twine&, llvm::Instruction*):
Assertion `cast<PointerType>(Ptr->getType()->getScalarType()) ->isOpaqueOrPointeeTypeMatches(PointeeType)'
failed.
Aborted (core dumped)
Now the type of the array when compiled is [3 x i32 (i32)*] by default it tries to do a a GEP on [3 x i32 (i32)*]* with element type [3 x i32 (i32)*] which does not work.
If I manaually edit the code to be:
%option_address = getelementptr i32 (i32)*, [3 x i32 (i32)*]* #my_function_1_table, i32 %7
Or too:
%option_address = getelementptr i32 (i32)*, [3 x i32 (i32)*] #my_function_1_table, i32 %7
it works just dandy, the ladder is really what I am looking to do. But I cant seem to do it probrammatically because of this exception.
I have tried casting the array to i32 (i32)* with:
auto first_element = context->builder.CreatePointerBitCastOrAddrSpaceCast(
(llvm::Value*) lookup_table_global,
(llvm::Type*) function->getType(),
"cast"
);
Then trying to access the elements with something like:
auto element = context->builder.CreateGEP(
(llvm::Type*) function->getType(),
first_element,
index_array,
"option_address"
);
But I get that exception again, and it does work if I type it manually into the IR
%option_address = getelementptr i32 (i32)*, i32 (i32)* #my_function_1_table, i32 %7
Seems like a pretty regular way to access an array, right?
But I cant seem to do it programmatically, because if the assertion, I even tried to make a work around by tryng to inherit from GetElementPtrInst directly and omitting the assertion, but couldn't (because its constructor is private).
Currently, my solution is to cast the array to a i32 (i32)* then to a [1 x i32 (i32)*] then do the GEP on a [1 x i32(i32)*]* with a [1 x i32(i32)]
%option_address = getelementptr [1 x i32 (i32)*], [1 x i32 (i32)*]* bitcast ([3 x i32 (i32)*]* #my_function_1_table to [1 x i32 (i32)*]*), i32 %7
This is horrible.
Does anyone know how I can simply access the function pointers I need from a global (constant) array so they can be called?
Also is my current solution portable?
Thank you!
Sorry you've run into this challenging aspect of LLVM. It definitely causes confusion.
There is an entire webpage dedicated to trying to help folks understand the counter-intuitive design of this instruction. While the design is well motivated from within LLVM, it causes lots of folks confusion and frustration when they first encounter it.
The challenge you're hitting is because a GEP instruction in LLVM always operates on a pointer, and with global variables, that pointer is to the variable. When the global variable is an array as in your case, this is extra confusing -- GEP has to go through an extra layer of pointer before it gets to the array you're trying to index with it.
The first section of the GEP site I mentioned above specifically explains how the first index to a GEP works -- it indexes the base pointer directly.
The second section then specifically clarifies why global variables end up surprising here. The global variable, #my_function_1_table in your case, is a pointer to itself. You'll have to index that with a simple i32 0 index first. Then you can add an additional index into the array that global variable points to.
So for a global variable with type [3 x i32 (i32)*], if you want to extract the second element of the array, you need:
%fptr = getelementptr [3 x i32 (i32)*], [3 x i32 (i32)*]* #my_function_1_table, i32 0, i32 2
The first i32 0 here indexes the global itself. The second index of i32 2 indexes into the array.
You can also use Clang to get example LLVM IR that can help explain how to do things. For example, here is some C++ that does something similar to what you're trying to do:
using FPtrT = int (*)(int);
extern FPtrT function_ptrs[3];
int test(int i) {
FPtrT fptr = function_ptrs[i];
return (*fptr)(42);
}
And this turns into the following LLVM IR after some basic optimizations (-O1):
#function_ptrs = external dso_local local_unnamed_addr global [3 x i32 (i32)*], align 16
define dso_local i32 #_Z4testi(i32 %0) local_unnamed_addr #0 {
%2 = sext i32 %0 to i64
%3 = getelementptr inbounds [3 x i32 (i32)*], [3 x i32 (i32)*]* #function_ptrs, i64 0, i64 %2
%4 = load i32 (i32)*, i32 (i32)** %3, align 8, !tbaa !4
%5 = call i32 %4(i32 42)
ret i32 %5
}
attributes #0 = { mustprogress uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
Here you can see %3 is doing a dynamic (and inbounds, but that's orthogonal) version of this indexing.
You can play with this kind of IR generation using Compiler Explorer: https://cpp.compiler-explorer.com/z/ETa8nvTvh
Once you're using the API to create this two index GEP it should start working for you.
Also, just so you (or others) reading this don't get confused: the LLVM IR syntax changed here recently, so the latest versions of LLVM don't look quite the same. You can switch from Clang v13 to a more recent one to see what it looks like, for example here: https://cpp.compiler-explorer.com/z/Kc4er413G

Break constant GEPs

I need to break constant GEPs. I found an old BreakConstantGEPs pass and I try to use it with newer LLVM version. For the code:
int tab[1]={1};
void fun()
{
int val=tab[0];
}
without performing pass I get the following .ll file:
#tab = dso_local global [1 x i32] [i32 1], align 4
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void #mult() #0 {
%1 = alloca i32, align 4
%2 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* #tab, i64 0, i64 0), align 4
store i32 %2, i32* %1, align 4
ret void
}
Then I perform the pass. GEP is properly recognized. Here I present most important parts of the pass (full code in link above).
Creating new GEP instruction:
GetElementPtrInst::CreateInBounds(CE->getOperand(0), Indices, CE->getName(), InsertPt) //in original code GetElementPtrInst::Create() is used
Replacing:
I->replaceUsesOfWith (CE, NewInst);
I->removeFromParent();
Unfortunately, the module verifier outputs errors:
Instruction referencing instruction not embedded in a basic block!
%2 = getelementptr inbounds [1 x i32], [1 x i32]* #tab, i64 0, i64 0
<badref> = load i32, i32* %2, align 4
Instruction does not dominate all uses!
<badref> = load i32, i32* %2, align 4
store i32 <badref>, i32* %1, align 4
in function fun
LLVM ERROR: Broken function found, compilation aborted!
What am I doing wrong?
Remove I->removeFromParent(); and it should work.
LLVM uses linked lists to represent most of its data, a Module holds global values (global variables, aliases and functions) in a linked list, a Function holds basic blocks in a linked list, and BasicBlock holds Instructions in a linked list. Thinking about this as memory ownership, the Instruction is owned by the BasicBlock and will be deleted when the BasicBlock is deleted. If you delete a Function then it will delete all the BasicBlocks it owns, which deletes all the Instructions and so on. We use linked lists instead of vectors in order to make moving instructions less expensive, you can hoist an instruction by detaching it from its parent basic block, and inserting it elsewhere.
When you created the instruction with GetElementPtrInst::CreateInBounds([...], InsertPt) you created a new getelementptr instruction and it was inserted in your code at the InsertPt insertion point (just any other instruction will do). Perfect.
Then you called I->removeFromParent() which removes the instruction from its basic block. It still exists as a C++ object but it has no parent basic block, it does not belong to any block or function or module, it never runs. Why did you do that? You probably didn't mean to do that. Or maybe you wanted to insert it somewhere other than the InsertPt?

How to use CreateInBoundsGEP in cpp api of llvm to access the element of an array?

I am new to llvm programming, and I am trying to write cpp to generate llvm ir for a simple C code like this:
int a[10];
a[0] = 1;
I want to generate something like this to store 1 into a[0]
%3 = getelementptr inbounds [10 x i32], [10 x i32]* %2, i64 0, i64 0
store i32 1, i32* %3, align 16
And I tried CreateGEP: auto arrayPtr = builder.CreateInBoundsGEP(var, num); where var and
num are both of type llvm::Value*
but I only get
%1 = getelementptr inbounds [10 x i32], [10 x i32]* %0, i32 0
store i32 1, [10 x i32]* %1
I searched google for a long time and looked the llvm manual but still don't know what Cpp api to use and how to use it.
Really appreciate it if you can help!
Note that the 2nd argument to IRBuilder::CreateInBoundsGEP (1st overload) is actually ArrayRef<Value *>, which means it accepts an array of Value * values (including C-style array, std::vector<Value *> and std::array<Value *, LEN> and others).
To generate a GEP instruction with multiple (child) addresses, pass an array of Value * to the second argument:
Value *i32zero = ConstantInt::get(contexet, APInt(32, 0));
Value *indices[2] = {i32zero, i32zero};
builder.CreateInBoundsGEP(var, ArrayRef<Value *>(indices, 2));
Which will yield
%1 = getelementptr inbounds [10 x i32], [10 x i32]* %0, i32 0, i32 0
You can correctly identify that %1 is of type i32*, pointing to the first item in the array pointed to by %0.
LLVM documentation on GEP instruction: https://llvm.org/docs/GetElementPtr.html

LLVM: How to create char array reference

I am trying to implement an opt pass that will compress string constants in ROM and then, at the cost of CPU + RAM, re-materialize the values at runtime. Before implementing compression, I just want to place all strings in a table, and do a lookup.
Example:
printf("Hello");
Would become the equivalent of
char placeholder[6];
int strID = 0;
tableLookup(placeholder, 0 /*ID*/); // Fill array
printf(placeholder);
The LLVM IR I was able to generate looks like the following:
%fakeString = alloca [10 x i8], align 1
call void #llvm.dbg.declare(metadata [10 x i8]* %fakeString, metadata !60, metadata !25), !dbg !64
%arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %fakeString, i32 0, i32 0, !dbg !65
call void #tableLookup(i8* %arraydecay, i32 0) #2, !dbg !66
How would I be able to create this programatically? The two main pieces I am missing:
1. How to create the array reference (after creating the alloca instruction)
2. How to get result from tableLookup and replace the operand in the old printf()
Any help would be much appreciated!

C++/LLVM: Runtime code generation and STL container

Assume a simple partial evaluation scenario:
#include <vector>
/* may be known at runtime */
int someConstant();
/* can be partially evaluated */
double foo(std::vector<double> args) {
return args[someConstant()] * someConstant();
}
Let's say that someConstant() is known and does not change at runtime (e.g. given by the user once) and can be replaced by the corresponding int literal. If foo is part of the hot path, I expect a significant performance improvement:
/* partially evaluated, someConstant() == 2 */
double foo(std::vector<double> args) {
return args[2] * 2;
}
My current take on that problem would be to generate LLVM IR at runtime, because I know the structure of the partially evaluated code (so I would not need a general purpose partial evaluator).
So I want to write a function foo_ir that generates IR code that does the same thing as foo, but not calling someConstant(), because it is known at runtime.
Simple enough, isn't it? Yet, when I look at the generated IR for the code above:
; Function Attrs: uwtable
define double #_Z3fooSt6vectorIdSaIdEE(%"class.std::vector"* %args) #0 {
%1 = call i32 #_Z12someConstantv()
%2 = sext i32 %1 to i64
%3 = call double* #_ZNSt6vectorIdSaIdEEixEm(%"class.std::vector"* %args, i64 %2)
%4 = load double* %3
%5 = call i32 #_Z12someConstantv()
%6 = sitofp i32 %5 to double
%7 = fmul double %4, %6
ret double %7
}
; Function Attrs: nounwind uwtable
define linkonce_odr double* #_ZNSt6vectorIdSaIdEEixEm(%"class.std::vector"* %this, i64 %__n) #1 align 2 {
%1 = alloca %"class.std::vector"*, align 8
%2 = alloca i64, align 8
store %"class.std::vector"* %this, %"class.std::vector"** %1, align 8
store i64 %__n, i64* %2, align 8
%3 = load %"class.std::vector"** %1
%4 = bitcast %"class.std::vector"* %3 to %"struct.std::_Vector_base"*
%5 = getelementptr inbounds %"struct.std::_Vector_base"* %4, i32 0, i32 0
%6 = getelementptr inbounds %"struct.std::_Vector_base<double, std::allocator<double> >::_Vector_impl"* %5, i32 0, i32 0
%7 = load double** %6, align 8
%8 = load i64* %2, align 8
%9 = getelementptr inbounds double* %7, i64 %8
ret double* %9
}
I see, that the [] was included from the STL definition (function #_ZNSt6vectorIdSaIdEEixEm) - fair enough. The problem is: It could as well be some member function, or even a direct data access, I simply cannot assume the data layout to be the same everywhere, so at development-time, I do not know the concrete std::vector layout of the host machine.
Is there some way to use C++ metaprogramming to get the required information at compile time? i.e. is there some way to ask llvm to provide IR for std::vector's [] method?
As a bonus: I would prefer to not enforce the compilation of the library with clang, instead, LLVM shall be a runtime-dependency, so just invoking clang at compile time (even if I do not know how to do this) is a second-best solution.
Answering my own question:
While I still have no solution for the general case (e.g. std::map), there exists a simple solution for std::vector:
According to the C++ standard, the following holds for the member function data()
Returns a direct pointer to the memory array used internally by the
vector to store its owned elements.
Because elements in the vector are guaranteed to be stored in
contiguous storage locations in the same order as represented by the
vector, the pointer retrieved can be offset to access any element in
the array.
So in fact, the object-level layout of std::vector is fixed by the standard.