3

バックエンドとして 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"puts0x68

何か案は?

ありがとう

編集:あなたは正しかった、私は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;
}

私はそれを逃しました、ありがとう!

4

1 に答える 1

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
}
于 2013-07-28T11:36:23.930 に答える