Como faço para gerar a estrutura de valores de retorno no LLVM IR que são compatíveis com C?
Com a minha LLVM baseado no brinquedo compilador, eu quero compilar o equivalente a este código em C:
struct a { long a[4]; };
struct b { long b[2]; };
struct a doStuff(struct b);
struct a myFunction(struct b v) {
return doStuff(v);
}
Enquanto o myFunction
está escrito em meu brinquedo linguagem de programação, doStuff
é uma função C e a de chamada de função myFunction
está também escrito em C.
No momento, o meu compilador gera o seguinte código:
define { [4 x i64] } @myFunction({ [2 x i64] } %%0) {
entry:
%%arg = alloca { [2 x i64] }
store { [2 x i64] } %%0, { [2 x i64] }* %%arg
%%arg1 = load { [2 x i64] }, { [2 x i64] }* %%arg
%%call_to_doStuff = call { [2 x i64] } @doStuff({ [2 x i64] } %%arg1)
ret { [4 x i64] } %%call_to_doStuff
}
Este código êxito em chamar de doStuff
, mas, em seguida, segfaults porque doStuff
s argumento de b
só contém lixo.
Quando eu uso o clang para traduzir o acima C a tradução de myFunction
, eu posso ver que ele está usando uma convenção de chamada diferente e sret
:
%%struct.a = type { [4 x i64] }
%%struct.b = type { [2 x i64] }
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @myFunction(%%struct.a* noalias sret %%0, i64 %%1, i64 %%2) #0 {
%%4 = alloca %%struct.b, align 8
%%5 = bitcast %%struct.b* %%4 to { i64, i64 }*
%%6 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %%5, i32 0, i32 0
store i64 %%1, i64* %%6, align 8
%%7 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %%5, i32 0, i32 1
store i64 %%2, i64* %%7, align 8
%%8 = bitcast %%struct.b* %%4 to { i64, i64 }*
%%9 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %%8, i32 0, i32 0
%%10 = load i64, i64* %%9, align 8
%%11 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %%8, i32 0, i32 1
%%12 = load i64, i64* %%11, align 8
call void @doStuff(%%struct.a* sret %%0, i64 %%10, i64 %%12)
ret void
}
declare dso_local void @doStuff(%%struct.a* sret, i64, i64) #1
Estou certo de que o meu problema está relacionado com a forma de estruturas, são devolvidos? E como eu poderia mudar o meu IR gerador para emitir a devida sret
com o código? Existe um Passe para que?
(Eu estou direcionando o Linux x86_64.)