LLVM从结构值中提取i8 *

时间:2013-07-28 08:44:32

标签: c++ llvm llvm-ir

我正在编写一个使用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位宽的指针,等于解除引用的字符串。

例如,如果我使用i8 *成员指向字符串@WritePrimitive的原语调用"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;
}

我错过了,谢谢!

1 个答案:

答案 0 :(得分:2)

您粘贴的代码没有任何问题;我自己尝试过它并且工作正常。我猜测问题是你没有正确初始化指针,或者没有将它正确地设置到结构中。

我使用的完整代码是:

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