我正在编写一个使用 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;
}
我错过了,谢谢!