バックエンドとして LLVM を使用してコンパイラを作成しています。フロントエンド (パーサーなど) を作成しましたが、今は岐路に立っています。
単一のフィールド、i8* 値、文字配列へのポインターを含む構造体 (%Primitive) があります。
%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* メンバーが stringを@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;
}
私はそれを逃しました、ありがとう!