LLVM IR включает массивы в качестве базового типа, поэтому инструкция «store» в IR возьмет объект массива и сохранит его по указателю на память.
Я компилирую в среду C , поэтому мне нужно преобразовать инструкции "store" в вызовы memcpy. Я пытался использовать IRBuilder для облегчения работы, но я застрял на том, как получить адрес объекта.
Функция, которую я написал, выглядит следующим образом:
bool convert_array_store_to_memcpy(llvm::StoreInst *instruction)
{
llvm::Type *value_type = instruction->getValueOperand()->getType();
if (!value_type->isArrayTy())
return false;
/* set up IRBuilder and get the pieces of the store */
llvm::IRBuilder<> Builder(llvm::getGlobalContext());
Builder.SetInsertPoint(instruction);
llvm::Value *destination = instruction->getPointerOperand();
llvm::Value *source = instruction->getValueOperand();
/* get the number of bytes by getting the size of the array (elements*element-size) */
llvm::ArrayType *array_type = cast<ArrayType>(value_type);
uint64_t element_count = array_type->getNumElements();
llvm::Type *element_type = array_type->getElementType();
DataLayout *targetData = new DataLayout(mod);
uint64_t element_size = targetData->getTypeAllocSize(element_type);
uint64_t size = element_count*element_size;
/* PROBLEM: I am trying to take the address of the start of the array */
llvm::Type *i32_type = llvm::IntegerType::getInt32Ty(llvm::getGlobalContext());
llvm::Constant *constant_int = llvm::ConstantInt::get(i32_type, 0, true);
Value *indexList[1] = {constant_int};
/* NEW PROBLEM:indexList seems to be the wrong type or contain the wrong type of thing */
llvm::Value *pointer_to_source = Builder.CreateGEP(source, ArrayRef<Value*>(indexList, 1));
unsigned alignment = instruction->getAlignment();
if (!array_type)
fprintf(stderr, "ERROR!\n");
/* insert the memcpy */
llvm::CallInst *memcpy_call = Builder.CreateMemCpy(destination,
pointer_to_source,
size,
alignment,
instruction->isVolatile());
/* erase the store */
instruction->eraseFromParent();
return true;
} /* convert_array_store_to_memcpy */
Это компилируется, но я получаю следующую ошибку времени выполнения при вызове IRBuilder :: CreateGEP:
... / llvm / install / include / llvm / IR / Instructions.h: 782 : llvm :: Type * llvm :: checkGEPType (llvm :: Type *): Утверждение `Ty &&" Недопустимые индексы GetElementPtrInst для типа! "'не удалось.
Обратите внимание, что я использую LLVM 3.6 под Linux.
РЕДАКТИРОВАТЬ: ясно, что вызов createGEP отправляет ноль вместо константного нуля - целью было получить адрес нулевого элемента массива. Я отредактировал вышеуказанную функцию с моей последней попыткой, которая заключается в попытке отправить массив индексов длины 1 в createGEP. Это также не работает внутри getIndexedType, который возвращает указатель NULL, который я, опять же, не понимаю.
Примечание: я использую пример из предыдущего ответа StackOverflow: Вставка инструкции GetElementpointer в LLVM IR