Frage

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.

War es hilfreich?

Lösung

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.

Andere Tipps

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top