Как динамически выделить и получить доступ к массиву с помощью LLVM API? - PullRequest
0 голосов
/ 10 июня 2019

Я хотел бы сгенерировать LLVM IR для кода C ++, например:

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 голосов
/ 11 июня 2019

Было две проблемы:

  • Во-первых, для доступа к массиву элементов нет необходимости передавать два индекса в инструкцию GEP.
  • Второй, пятый аргумент 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)
...