Mercurial > projects > ldc
changeset 954:e048e36bc155
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.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 14 Feb 2009 15:25:48 +0100 |
parents | 5fa3e0ea06e9 |
children | 8a70b4381369 |
files | gen/asmstmt.cpp gen/irstate.h gen/naked.cpp |
diffstat | 3 files changed, 31 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/asmstmt.cpp Fri Feb 13 22:20:30 2009 +0100 +++ b/gen/asmstmt.cpp Sat Feb 14 15:25:48 2009 +0100 @@ -629,7 +629,7 @@ } 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 @@ 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; }
--- a/gen/irstate.h Fri Feb 13 22:20:30 2009 +0100 +++ b/gen/irstate.h Sat Feb 14 15:25:48 2009 +0100 @@ -88,8 +88,9 @@ 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
--- a/gen/naked.cpp Fri Feb 13 22:20:30 2009 +0100 +++ b/gen/naked.cpp Sat Feb 14 15:25:48 2009 +0100 @@ -207,6 +207,29 @@ { 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 {