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 doStuffs 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.)

0
2019-09-19 13:46:33
origem
0 respostas

Veja mais perguntas por marcas