LLVM извлекают i8 * из структурного значения

Я пишу компилятор, используя LLVM в качестве бэкэнда, я написал внешний интерфейс (синтаксический анализатор и т. Д.) И теперь я попал на перепутье.

У меня есть структура (% Primitive), которая содержит одно поле, значение i8 *, указатель на массив символов.

%Primitive = type { i8* }

В компиляторе экземпляры Primitive передаются по стеку. Я пытаюсь записать этот массив символов в стандартный вывод, используя puts функция, но она не работает так, как я надеялся.

declare i32 @puts(i8*) ; Declare the libc function 'puts'

define void @WritePrimitive(%Primitive) {
entry:
%1 = extractvalue %Primitive %0, 0 ; Extract the character array from the primitive.
%2 = call i32 @puts(i8* %1) ; Write it
ret void
}

Когда я пытаюсь запустить код (либо с помощью ExecutionEngine или программы интерпретатора LLVM lli), Я получаю ту же ошибку; ошибка сегментации.

Ошибка заключается в том, что адрес передан puts каким-то образом является символьным кодом ASCII первого символа в массиве. Кажется, что переданный адрес, а не указатель на массив из 8-битных символов, вместо этого представляет собой 8-битный указатель, равный разыменованной строке.

Например, если я позвоню @WritePrimitive с примитивом, где член i8 * указывает на строку "hello", puts вызывается с адресом строки 0x68,

Есть идеи?

Спасибо

РЕДАКТИРОВАТЬ: Вы были правы, я инициализировал мой Primitive неправильно, моя новая функция инициализации:

llvm::Value* PrimitiveHelper::getConstantPrimitive(const std::string& str, llvm::BasicBlock* bb)
{
ConstantInt* int0 = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0);
Constant* strConstant = ConstantDataArray::getString(getGlobalContext(), str, true);

GlobalVariable* global = new GlobalVariable(module,
strConstant->getType(),
true, // Constant
GlobalValue::ExternalLinkage,
strConstant,
"str");

Value* allocated = new AllocaInst(m_primitiveType, "allocated", bb);

LoadInst* onStack1 = new LoadInst(allocated, "onStack1", bb);

GetElementPtrInst* ptr = GetElementPtrInst::Create(global, std::vector<Value*>(2,int0), "", bb);

InsertValueInst* onStack2 = InsertValueInst::Create(onStack1, ptr, std::vector<unsigned>(1, 0), "", bb);

return onStack2;
}

Я пропустил это, спасибо!

3

Решение

Нет ничего плохого в коде, который вы вставили выше; Я только попробовал это сам, и это работало отлично. Я предполагаю, что проблема в том, что вы неправильно инициализировали указатель или неправильно установили его в структуру.

Полный код, который я использовал:

@str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"
; Your code
%Primitive = type { i8* }

declare i32 @puts(i8*) ; Declare the libc function 'puts'

define void @WritePrimitive(%Primitive) {
entry:
%1 = extractvalue %Primitive %0, 0 ; Extract the character array from the primitive.
%2 = call i32 @puts(i8* %1) ; Write it
ret void
}

; /Your code

define void @main() {
%allocated = alloca %Primitive
%onstack1 = load %Primitive* %allocated
%onstack2 = insertvalue %Primitive %onstack1, i8* getelementptr ([13 x i8]* @str, i64 0, i64 0), 0
call void @WritePrimitive(%Primitive %onstack2)
ret void
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]