llvm getelementptr命令を学習していて、構造体から要素を取得しようとしています。私の構造体はこんな感じです
struct Foo {
int32_t a;
int32_t b;
int32_t c;
};
対応するllvmタイプ:
Type *getType() {
vector<Type *> tps;
tps.push_back(Type::getInt32Ty(TheContext));
tps.push_back(Type::getInt32Ty(TheContext));
tps.push_back(Type::getInt32Ty(TheContext));
StructType *tp = StructType::create(TheContext, tps, "foo_type");
return tp;
}
とテスト機能、
%foo_type = type { i32, i32, i32 }
define i32 @_func_(%foo_type) {
entry:
%1 = alloca %foo_type
store %foo_type %0, %foo_type* %1
%2 = getelementptr %foo_type, %foo_type* %1, i32 0, i32 1
%3 = load i32, i32* %2
ret i32 %3
}
しかし、コンパイルされた関数を実行すると、常に3番目の要素であるFoo :: cが取得されますが、Foo :: bは取得されないので、コードの何が問題になっていますか?問題はストアの指示かもしれないと思います。
2019.12.13を編集
パラメータとしてポインタを渡すことで、正しい答えが得られます
define i32 @_func_(%foo_type*) {
entry:
%1 = alloca %foo_type*
store %foo_type* %0, %foo_type** %1
%ptr = load %foo_type*, %foo_type** %1
%2 = getelementptr %foo_type, %foo_type* %ptr, i32 0, i32 1
%3 = load i32, i32* %2
ret i32 %3
}
したがって、問題は、以前のバージョンでコンパイルされた関数にFP(f)
実際に渡さf
れていないことであるに違いありません。
関数をcで記述し、clangにIRを出力させると、次のように表示されます。
struct Foo {
int a;
int b;
int c;
};
int bar(Foo f) {
return f.b;
}
define dso_local i32 @_Z3bar3Foo(i64, i32) #0 {
%3 = alloca %struct.Foo, align 4
%4 = alloca { i64, i32 }, align 4
%5 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %4, i32 0, i32 0
store i64 %0, i64* %5, align 4
%6 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %4, i32 0, i32 1
store i32 %1, i32* %6, align 4
%7 = bitcast %struct.Foo* %3 to i8*
%8 = bitcast { i64, i32 }* %4 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %7, i8* align 4 %8, i64 12, i1 false)
%9 = getelementptr inbounds %struct.Foo, %struct.Foo* %3, i32 0, i32 1
%10 = load i32, i32* %9, align 4
ret i32 %10
}
つまり、それ自体ではなく、bar(Foo())
実際にパラメータとして受け入れint64
てint32
いるというFoo
ことです。それは私があまり知らないいくつかのc / cppABIかもしれません。
しかし、ポインタを渡す場合、そのような問題はないので、期待どおりに機能します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加