简体   繁体   English

LLVM从结构值中提取i8 *

[英]LLVM extract i8* out of structure value

I'm writing a compiler using LLVM as a backend, I've written the front-end (parser, etc.) and now I've come to a crossroads. 我正在编写一个使用LLVM作为后端的编译器,我编写了前端(解析器等),现在我已经走到了一个十字路口。

I have a structure (%Primitive) which contains a single field, an i8* value, a pointer to a character array. 我有一个结构(%Primitive),它包含一个字段,一个i8 *值,一个指向字符数组的指针。

%Primitive = type { i8* }

In the compiler, instances of Primitive are passed around on the stack. 在编译器中, Primitive实例在堆栈上传递。 I'm trying to write this character array to standard output using the puts function, but it isn't working quite like I was hoping. 我正在尝试使用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
}

When I try to run the code (either using an ExecutionEngine or the LLVM interpreter program lli ), I get the same error; 当我尝试运行代码时(使用ExecutionEngine或LLVM解释程序lli ),我得到相同的错误; a segmentation fault. 分段错误。

The error lies in the fact that the address passed to puts is somehow the ASCII character code of the first character in the array. 错误在于传递给puts的地址在某种程度上是数组中第一个字符的ASCII字符代码。 It seems the address passed, rather than being a pointer to an array of 8 bit chars, is instead an 8 bit wide pointer that equals the dereferenced string. 似乎地址传递,而不是指向8位字符数组的指针,而是一个8位宽的指针,等于解除引用的字符串。

For example, if I call @WritePrimitive with a primitive where the i8* member points to the string "hello" , puts is called with the string address being 0x68 . 例如,如果我用一个基元调用@WritePrimitive ,其中i8 *成员指向字符串"hello" ,则调用puts ,字符串地址为0x68

Any ideas? 有任何想法吗?

Thanks 谢谢

EDIT: You were right, I was initializing my Primitive incorrectly, my new initialization function is: 编辑:你是对的,我错误地初始化了我的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;
}

I missed that, Thank You! 我错过了,谢谢!

There's nothing wrong with the code you pasted above; 您粘贴的代码没有任何问题; I just tried it myself and it worked fine. 我自己尝试过它并且工作正常。 I'm guessing the issue is that you did not initialize the pointer properly, or did not set it properly into the struct. 我猜测问题是你没有正确初始化指针,或者没有正确地将它设置到结构中。

The full code I used is: 我使用的完整代码是:

@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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM