如何使用LLVM API动态分配和访问数组?

时间:2019-06-10 13:30:25

标签: llvm llvm-ir

我想为这样的C ++代码生成LLVM IR:

T *arr = (T*) malloc(sizeof(T) * 100);
arr[0] = somevalue;

这是我的代码:

llvm::Type* element_type = /... some T type .../;
llvm::Type* int32type = llvm::Type::getInt32Ty(context);

auto element_size = llvm::ConstantInt::get(int32type, data_layout.getTypeAllocSize(element_type));
auto array_size = llvm::ConstantInt::get(int32type, 100);

// malloc:
auto malloc_inst = llvm::CallInst::CreateMalloc(
    ir_builder.GetInsertBlock(), 
    element_type->getPointerTo(), // T*
    element_type,                 // T
    element_size,                 // sizeof(T)
    array_size,                   // 100
    nullptr, 
    "")
ir_builder.Insert(malloc_inst);

// cast to T*:
auto arr = ir_builder.CreatePointerCast(malloc_inst, element_type->getPointerTo());

// arr[0] = somevalue:
llvm::Value *value = /... some value of type T .../
auto element_ptr = ir_builder.CreateInBoundsGEP(
    arr, { 
        llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0),
        llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0)
    });
ir_builder.CreateStore(value, element_ptr)

但是,运行生成的IR时,我得到了:

Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), function checkGEPType, file /usr/local/opt/llvm/include/llvm/IR/Instructions.h, line 847

我尝试了传递给GEP指令的各种类型的组合,但是很明显,我缺少一些基本的知识。 有人可以为此指出一个可行的例子吗?

1 个答案:

答案 0 :(得分:0)

有两个问题:

  • 首先,要访问元素数组,无需将两个索引传递给GEP指令。
  • 由于某种原因here,CreateMalloc的第二个第五个参数被强制转换为指针。在我自己完成element_size * array_size乘法之后,一切正常。

此外,由于它是自动发生的,因此不需要显式指针强制转换(从i8 *到T *)。

这是最终的工作代码:

llvm::Type* element_type = /... some T type .../;
llvm::Type* int32type = llvm::Type::getInt32Ty(context);

auto element_size = llvm::ConstantInt::get(int32type, data_layout.getTypeAllocSize(element_type));
auto array_size = llvm::ConstantInt::get(int32type, 100);
auto alloc_size = llvm::ConstantExpr::getMul(element_size, array_size);

// malloc:
auto arr = llvm::CallInst::CreateMalloc(
    ir_builder.GetInsertBlock(), 
    element_type->getPointerTo(), // T*
    element_type,                 // T
    alloc_size,                   // sizeof(T) * 100
    nullptr,
    nullptr, 
    "")
ir_builder.Insert(arr);

// arr[0] = somevalue:
llvm::Value *value = /... some value of type T .../
auto element_ptr = ir_builder.CreateInBoundsGEP(
    arr, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0));
ir_builder.CreateStore(value, element_ptr)