diff --git a/gen/functions.cpp b/gen/functions.cpp index ab1893be..b94bda9a 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -592,6 +592,16 @@ void DtoDefineFunc(FuncDeclaration* fd) fd->vresult->ir.irLocal = new IrLocal(fd->vresult); fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), "function_vresult"); } + + // this hack makes sure the frame pointer elimination optimization is disabled. + // this this eliminates a bunch of inline asm related issues. + // naked must always eliminate the framepointer however... + if (fd->inlineAsm && !fd->naked) + { + // emit a call to llvm_eh_unwind_init + LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init); + gIR->ir->CreateCall(hack, ""); + } // give the 'this' argument storage and debug info if (f->usesThis) diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 11ad4025..9fdee7bf 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -37,7 +37,12 @@ unsigned DtoCallingConv(LINK l) if (l == LINKc || l == LINKcpp) return llvm::CallingConv::C; else if (l == LINKd || l == LINKdefault) - return llvm::CallingConv::Fast; + { + if (global.params.cpu == ARCHx86) + return llvm::CallingConv::X86_StdCall; + else + return llvm::CallingConv::Fast; + } else if (l == LINKwindows) return llvm::CallingConv::X86_StdCall; else diff --git a/tests/mini/callingconv1.d b/tests/mini/callingconv1.d new file mode 100644 index 00000000..48d1a99d --- /dev/null +++ b/tests/mini/callingconv1.d @@ -0,0 +1,31 @@ +module mini.callingconv1; + +extern(C) int printf(char*, ...); + +float foo(float a, float b) +{ + return a + b; +} + +void main() +{ + float a = 1.5; + float b = 2.5; + float c; + + asm + { + mov EAX, [a]; + push EAX; + mov EAX, [b]; + push EAX; + call foo; + fstp c; + } + + printf("%f\n", c); + + assert(c == 4.0); + + printf("passed\n", c); +}