From 56dd1fcc4355e5dd885f0709377a8ecead060cb2 Mon Sep 17 00:00:00 2001 From: Jonghyun Park Date: Fri, 31 Mar 2017 06:20:01 +0900 Subject: [PATCH] [x86/Linux] Use CDECL instead of STDCALL (dotnet/coreclr#10410) [x86/Linux] Use CDECL instead of STDCALL Use STDCALL/THISCALL/FASTCALL if callconv is explicitly specified Merge two adjustment (argument/alignment) into one Commit migrated from https://github.com/dotnet/coreclr/commit/5e03cb09e3754e4a3430ba424a1352b9c01ff098 --- src/coreclr/src/inc/corinfo.h | 11 ++++++ src/coreclr/src/jit/codegencommon.cpp | 24 ++++++++---- src/coreclr/src/jit/codegenlinear.h | 2 +- src/coreclr/src/jit/codegenxarch.cpp | 61 +++++++++++++++++++++++-------- src/coreclr/src/jit/importer.cpp | 8 ++++ src/coreclr/src/vm/comdelegate.cpp | 9 ++++- src/coreclr/src/vm/fcall.h | 2 +- src/coreclr/src/vm/i386/jithelp.S | 6 +-- src/coreclr/src/vm/i386/stublinkerx86.cpp | 12 +++++- 9 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/coreclr/src/inc/corinfo.h b/src/coreclr/src/inc/corinfo.h index f7560b2..00c42ce 100644 --- a/src/coreclr/src/inc/corinfo.h +++ b/src/coreclr/src/inc/corinfo.h @@ -747,6 +747,17 @@ enum CorInfoCallConv CORINFO_CALLCONV_PARAMTYPE = 0x80, // Passed last. Same as CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG }; +#ifdef UNIX_X86_ABI +inline bool IsCallerPop(CorInfoCallConv callConv) +{ + unsigned int umask = CORINFO_CALLCONV_STDCALL + | CORINFO_CALLCONV_THISCALL + | CORINFO_CALLCONV_FASTCALL; + + return !(callConv & umask); +} +#endif // UNIX_X86_ABI + enum CorInfoUnmanagedCallConv { // These correspond to CorUnmanagedCallingConvention diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 5e65397..e9546f8 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -1639,7 +1639,7 @@ void CodeGen::genDefineTempLabel(BasicBlock* label) void CodeGen::genAdjustSP(ssize_t delta) { -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(UNIX_X86_ABI) if (delta == sizeof(int)) inst_RV(INS_pop, REG_ECX, TYP_INT); else @@ -9720,17 +9720,25 @@ void CodeGen::genFnEpilog(BasicBlock* block) unsigned stkArgSize = 0; // Zero on all platforms except x86 #if defined(_TARGET_X86_) - - noway_assert(compiler->compArgSize >= intRegState.rsCalleeRegArgCount * sizeof(void*)); - stkArgSize = compiler->compArgSize - intRegState.rsCalleeRegArgCount * sizeof(void*); - - noway_assert(compiler->compArgSize < 0x10000); // "ret" only has 2 byte operand + bool fCalleePop = true; // varargs has caller pop if (compiler->info.compIsVarArgs) - stkArgSize = 0; + fCalleePop = false; + +#ifdef UNIX_X86_ABI + if (IsCallerPop(compiler->info.compMethodInfo->args.callConv)) + fCalleePop = false; +#endif // UNIX_X86_ABI -#endif // defined(_TARGET_X86_) + if (fCalleePop) + { + noway_assert(compiler->compArgSize >= intRegState.rsCalleeRegArgCount * sizeof(void*)); + stkArgSize = compiler->compArgSize - intRegState.rsCalleeRegArgCount * sizeof(void*); + + noway_assert(compiler->compArgSize < 0x10000); // "ret" only has 2 byte operand + } +#endif // _TARGET_X86_ /* Return, popping our arguments (if any) */ instGen_Return(stkArgSize); diff --git a/src/coreclr/src/jit/codegenlinear.h b/src/coreclr/src/jit/codegenlinear.h index 9fa5bdb..b038858 100644 --- a/src/coreclr/src/jit/codegenlinear.h +++ b/src/coreclr/src/jit/codegenlinear.h @@ -176,7 +176,7 @@ void genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode); void genAlignStackBeforeCall(GenTreePutArgStk* putArgStk); void genAlignStackBeforeCall(GenTreeCall* call); -void genRemoveAlignmentAfterCall(GenTreeCall* call); +void genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias = 0); #if defined(UNIX_X86_ABI) diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp index 5d26612..9833b09 100644 --- a/src/coreclr/src/jit/codegenxarch.cpp +++ b/src/coreclr/src/jit/codegenxarch.cpp @@ -5005,16 +5005,30 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } #if defined(_TARGET_X86_) + bool fCallerPop = (call->gtFlags & GTF_CALL_POP_ARGS) != 0; + +#ifdef UNIX_X86_ABI + { + CorInfoCallConv callConv = CORINFO_CALLCONV_DEFAULT; + + if ((callType != CT_HELPER) && call->callSig) + { + callConv = call->callSig->callConv; + } + + fCallerPop |= IsCallerPop(callConv); + } +#endif // UNIX_X86_ABI + // If the callee pops the arguments, we pass a positive value as the argSize, and the emitter will // adjust its stack level accordingly. // If the caller needs to explicitly pop its arguments, we must pass a negative value, and then do the // pop when we're done. ssize_t argSizeForEmitter = stackArgBytes; - if ((call->gtFlags & GTF_CALL_POP_ARGS) != 0) + if (fCallerPop) { argSizeForEmitter = -stackArgBytes; } - #endif // defined(_TARGET_X86_) #ifdef FEATURE_AVX_SUPPORT @@ -5187,8 +5201,6 @@ void CodeGen::genCallInstruction(GenTreeCall* call) // clang-format on } - genRemoveAlignmentAfterCall(call); - // if it was a pinvoke we may have needed to get the address of a label if (genPendingCallLabel) { @@ -5197,11 +5209,6 @@ void CodeGen::genCallInstruction(GenTreeCall* call) genPendingCallLabel = nullptr; } -#if defined(_TARGET_X86_) - // The call will pop its arguments. - SubtractStackLevel(stackArgBytes); -#endif // defined(_TARGET_X86_) - // Update GC info: // All Callee arg registers are trashed and no longer contain any GC pointers. // TODO-XArch-Bug?: As a matter of fact shouldn't we be killing all of callee trashed regs here? @@ -5302,6 +5309,8 @@ void CodeGen::genCallInstruction(GenTreeCall* call) gcInfo.gcMarkRegSetNpt(RBM_INTRET); } + unsigned stackAdjustBias = 0; + #if defined(_TARGET_X86_) //------------------------------------------------------------------------- // Create a label for tracking of region protected by the monitor in synchronized methods. @@ -5332,11 +5341,15 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } // Is the caller supposed to pop the arguments? - if (((call->gtFlags & GTF_CALL_POP_ARGS) != 0) && (stackArgBytes != 0)) + if (fCallerPop && (stackArgBytes != 0)) { - genAdjustSP(stackArgBytes); + stackAdjustBias = stackArgBytes; } + + SubtractStackLevel(stackArgBytes); #endif // _TARGET_X86_ + + genRemoveAlignmentAfterCall(call, stackAdjustBias); } // Produce code for a GT_JMP node. @@ -7566,19 +7579,35 @@ void CodeGen::genAlignStackBeforeCall(GenTreeCall* call) // // Arguments: // call - the call node. +// bias - additional stack adjustment // -void CodeGen::genRemoveAlignmentAfterCall(GenTreeCall* call) +// Note: +// When bias > 0, caller should adjust stack level appropriately as +// bias is not considered when adjusting stack level. +// +void CodeGen::genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias) { +#if defined(_TARGET_X86_) #if defined(UNIX_X86_ABI) // Put back the stack pointer if there was any padding for stack alignment - unsigned padStkAlign = call->fgArgInfo->GetStkAlign(); - if (padStkAlign != 0) + unsigned padStkAlign = call->fgArgInfo->GetStkAlign(); + unsigned padStkAdjust = padStkAlign + bias; + + if (padStkAdjust != 0) { - inst_RV_IV(INS_add, REG_SPBASE, padStkAlign, EA_PTRSIZE); + inst_RV_IV(INS_add, REG_SPBASE, padStkAdjust, EA_PTRSIZE); SubtractStackLevel(padStkAlign); SubtractNestedAlignment(padStkAlign); } -#endif // UNIX_X86_ABI +#else // UNIX_X86_ABI + if (bias != 0) + { + genAdjustSP(bias); + } +#endif // !UNIX_X86_ABI_ +#else // _TARGET_X86_ + assert(bias == 0); +#endif // !_TARGET_X86 } #ifdef _TARGET_X86_ diff --git a/src/coreclr/src/jit/importer.cpp b/src/coreclr/src/jit/importer.cpp index 599abf9..eaf647a 100644 --- a/src/coreclr/src/jit/importer.cpp +++ b/src/coreclr/src/jit/importer.cpp @@ -6967,6 +6967,14 @@ var_types Compiler::impImportCall(OPCODE opcode, } #endif // !FEATURE_VARARG +#ifdef UNIX_X86_ABI + if (call->gtCall.callSig == nullptr) + { + call->gtCall.callSig = new (this, CMK_CorSig) CORINFO_SIG_INFO; + *call->gtCall.callSig = *sig; + } +#endif // UNIX_X86_ABI + if ((sig->callConv & CORINFO_CALLCONV_MASK) == CORINFO_CALLCONV_VARARG || (sig->callConv & CORINFO_CALLCONV_MASK) == CORINFO_CALLCONV_NATIVEVARARG) { diff --git a/src/coreclr/src/vm/comdelegate.cpp b/src/coreclr/src/vm/comdelegate.cpp index 20ae695..2682c2d 100644 --- a/src/coreclr/src/vm/comdelegate.cpp +++ b/src/coreclr/src/vm/comdelegate.cpp @@ -277,7 +277,14 @@ VOID GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArraystacksizedelta == 0); +#endif + if (pWalk->stacksizedelta) X86EmitAddEsp(pWalk->stacksizedelta); @@ -5717,8 +5721,12 @@ COPY_VALUE_CLASS: X86EmitPopReg(kFactorReg); X86EmitPopReg(kTotalReg); +#ifndef UNIX_X86_ABI // ret N X86EmitReturn(pArrayOpScript->m_cbretpop); +#else + X86EmitReturn(0); +#endif #endif // !_TARGET_AMD64_ // Exception points must clean up the stack for all those extra args. -- 2.7.4