# HG changeset patch # User Tomas Lindquist Olsen # Date 1234621548 -3600 # Node ID e048e36bc1559c6e293c5e8273dba7d079940a2a # Parent 5fa3e0ea06e962a6d25f3f3e20bda6c7ccdb854a 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. diff -r 5fa3e0ea06e9 -r e048e36bc155 gen/asmstmt.cpp --- 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; } diff -r 5fa3e0ea06e9 -r e048e36bc155 gen/irstate.h --- 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 diff -r 5fa3e0ea06e9 -r e048e36bc155 gen/naked.cpp --- 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, $<>" "\n\t" "mov %edx, $<>"; + + // 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 {