mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Added support for using a temporary to implement emulated ABI return from inline asm, could be easier to use, but I think this will do. It's so extremely target dependent in any case that doing a completely generic approach seems hard.
This commit is contained in:
@@ -629,7 +629,7 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
}
|
||||
remap_inargs(a->code, inn+a->out.size(), asmIdx);
|
||||
if (!code.empty())
|
||||
code += " ; ";
|
||||
code += "\n\t";
|
||||
code += a->code;
|
||||
}
|
||||
asmblock->s.clear();
|
||||
@@ -671,8 +671,13 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
args.insert(args.end(), outargs.begin(), outargs.end());
|
||||
args.insert(args.end(), inargs.begin(), inargs.end());
|
||||
llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), "");
|
||||
|
||||
// capture abi return value
|
||||
if (useabiret)
|
||||
{
|
||||
if (p->asmBlock->retemu)
|
||||
p->asmBlock->asmBlock->abiret = DtoLoad(p->asmBlock->asmBlock->abiret);
|
||||
else
|
||||
p->asmBlock->asmBlock->abiret = call;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,8 +88,9 @@ struct IRAsmBlock
|
||||
AsmBlockStatement* asmBlock;
|
||||
const LLType* retty;
|
||||
unsigned retn;
|
||||
bool retemu; // emulate abi ret with a temporary
|
||||
|
||||
IRAsmBlock(AsmBlockStatement* b) : asmBlock(b), retty(NULL), retn(0) {}
|
||||
IRAsmBlock(AsmBlockStatement* b) : asmBlock(b), retty(NULL), retn(0), retemu(false) {}
|
||||
};
|
||||
|
||||
// llvm::CallInst and llvm::InvokeInst don't share a common base
|
||||
|
||||
@@ -207,6 +207,29 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
|
||||
{
|
||||
as->out_c = "={ax},={dx},";
|
||||
asmblock->retn = 2;
|
||||
#if 0
|
||||
// this is to show how to allocate a temporary for the return value
|
||||
// in case the appropriate multi register constraint isn't supported.
|
||||
// this way abi return from inline asm can still be emulated.
|
||||
|
||||
// generate asm
|
||||
as->out_c = "=*m,=*m,";
|
||||
LLValue* tmp = DtoAlloca(llretTy, ".tmp_asm_ret");
|
||||
as->out.push_back( tmp );
|
||||
as->out.push_back( DtoGEPi(tmp, 0,1) );
|
||||
as->code = "movd %eax, $<<out0>>" "\n\t" "mov %edx, $<<out1>>";
|
||||
|
||||
// fix asmblock
|
||||
asmblock->retn = 0;
|
||||
asmblock->retemu = true;
|
||||
asmblock->asmBlock->abiret = tmp;
|
||||
|
||||
// add "ret" stmt
|
||||
asmblock->s.push_back(as);
|
||||
|
||||
// done, we don't want anything pushed in the front of the block
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user