Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix x86 linux tests #57244

Merged
merged 1 commit into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8521,6 +8521,14 @@ void CodeGen::genFnEpilog(BasicBlock* block)

noway_assert(compiler->compArgSize < 0x10000); // "ret" only has 2 byte operand
}

#ifdef UNIX_X86_ABI
// The called function must remove hidden address argument from the stack before returning
// in case of struct returning according to cdecl calling convention on linux.
// Details: http://www.sco.com/developers/devspecs/abi386-4.pdf pages 40-43
if (compiler->info.compCallConv == CorInfoCallConvExtension::C && compiler->info.compRetBuffArg != BAD_VAR_NUM)
stkArgSize += TARGET_POINTER_SIZE;
#endif // UNIX_X86_ABI
#endif // TARGET_X86

/* Return, popping our arguments (if any) */
Expand Down
34 changes: 33 additions & 1 deletion src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6413,7 +6413,8 @@ GenTreeCall* Compiler::gtNewCallNode(

node->gtFlags |= (GTF_CALL | GTF_GLOB_REF);
#ifdef UNIX_X86_ABI
node->gtFlags |= GTF_CALL_POP_ARGS;
if (callType == CT_INDIRECT || callType == CT_HELPER)
node->gtFlags |= GTF_CALL_POP_ARGS;
#endif // UNIX_X86_ABI
for (GenTreeCall::Use& use : GenTreeCall::UseList(args))
{
Expand Down Expand Up @@ -10000,6 +10001,33 @@ void GenTree::SetIndirExceptionFlags(Compiler* comp)
return charsDisplayed;
}

#ifdef TARGET_X86
inline const char* GetCallConvName(CorInfoCallConvExtension callConv)
{
switch (callConv)
{
case CorInfoCallConvExtension::Managed:
return "Managed";
case CorInfoCallConvExtension::C:
return "C";
case CorInfoCallConvExtension::Stdcall:
return "Stdcall";
case CorInfoCallConvExtension::Thiscall:
return "Thiscall";
case CorInfoCallConvExtension::Fastcall:
return "Fastcall";
case CorInfoCallConvExtension::CMemberFunction:
return "CMemberFunction";
case CorInfoCallConvExtension::StdcallMemberFunction:
return "StdcallMemberFunction";
case CorInfoCallConvExtension::FastcallMemberFunction:
return "FastcallMemberFunction";
default:
return "UnknownCallConv";
}
}
#endif // TARGET_X86

/*****************************************************************************/

void Compiler::gtDispNodeName(GenTree* tree)
Expand Down Expand Up @@ -10085,6 +10113,10 @@ void Compiler::gtDispNodeName(GenTree* tree)
{
gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " thiscall");
}
#ifdef TARGET_X86
gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " %s",
GetCallConvName(tree->AsCall()->GetUnmanagedCallConv()));
#endif // TARGET_X86
gtfType = gtfTypeBuf;
}

Expand Down
7 changes: 5 additions & 2 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
// Case of call returning a struct via hidden retbuf arg
CLANG_FORMAT_COMMENT_ANCHOR;

#if defined(TARGET_WINDOWS) && !defined(TARGET_ARM)
#if (defined(TARGET_WINDOWS) && !defined(TARGET_ARM)) || defined(UNIX_X86_ABI)
// Unmanaged instance methods on Windows need the retbuf arg after the first (this) parameter
if (srcCall->IsUnmanaged())
{
Expand Down Expand Up @@ -1366,7 +1366,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
}
}
else
#endif
#endif // (defined(TARGET_WINDOWS) && !defined(TARGET_ARM)) || defined(UNIX_X86_ABI)
{
// insert the return value buffer into the argument list as first byref parameter
srcCall->gtCallArgs = gtPrependNewCallArg(destAddr, srcCall->gtCallArgs);
Expand Down Expand Up @@ -7412,6 +7412,9 @@ GenTreeCall* Compiler::impImportIndirectCall(CORINFO_SIG_INFO* sig, IL_OFFSETX i
GenTreeCall* call = gtNewIndCallNode(fptr, callRetTyp, nullptr, ilOffset);

call->gtFlags |= GTF_EXCEPT | (fptr->gtFlags & GTF_GLOB_EFFECT);
#ifdef UNIX_X86_ABI
call->gtFlags &= ~GTF_CALL_POP_ARGS;
#endif

return call;
}
Expand Down
19 changes: 6 additions & 13 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2805,17 +2805,8 @@ void Compiler::fgInitArgInfo(GenTreeCall* call)
noway_assert(arg != nullptr);
call->gtCallCookie = nullptr;

#if defined(TARGET_X86)
// x86 passes the cookie on the stack as the final argument to the call.
GenTreeCall::Use** insertionPoint = &call->gtCallArgs;
for (; *insertionPoint != nullptr; insertionPoint = &((*insertionPoint)->NextRef()))
{
}
*insertionPoint = gtNewCallArgs(arg);
#else // !defined(TARGET_X86)
// All other architectures pass the cookie in a register.
// All architectures pass the cookie in a register.
call->gtCallArgs = gtPrependNewCallArg(arg, call->gtCallArgs);
#endif // defined(TARGET_X86)
jakobbotsch marked this conversation as resolved.
Show resolved Hide resolved

nonStandardArgs.Add(arg, REG_PINVOKE_COOKIE_PARAM);
numArgs++;
Expand Down Expand Up @@ -2931,7 +2922,9 @@ void Compiler::fgInitArgInfo(GenTreeCall* call)
}
#ifdef UNIX_X86_ABI
// Add in the ret buff arg
if (callHasRetBuffArg)
if (callHasRetBuffArg &&
call->unmgdCallConv != CorInfoCallConvExtension::C && // C and Stdcall calling conventions do not
call->unmgdCallConv != CorInfoCallConvExtension::Stdcall) // use registers to pass arguments.
maxRegArgs++;
#endif
}
Expand Down Expand Up @@ -18178,8 +18171,8 @@ bool Compiler::fgCheckStmtAfterTailCall()
//
bool Compiler::fgCanTailCallViaJitHelper()
{
#ifndef TARGET_X86
// On anything except X86 we have no faster mechanism available.
#if !defined(TARGET_X86) || defined(UNIX_X86_ABI)
// On anything except windows X86 we have no faster mechanism available.
return false;
#else
// The JIT helper does not properly handle the case where localloc was used.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/reglist.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

// The "regList" type is a small set of registerse
#ifdef TARGET_X86
typedef TinyArray<unsigned short, regNumber, REGNUM_BITS> regList;
typedef TinyArray<unsigned int, regNumber, REGNUM_BITS> regList;
t-mustafin marked this conversation as resolved.
Show resolved Hide resolved
#else
// The regList is unused for all other targets.
#endif // TARGET*
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/targetx86.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
#define RBM_PINVOKE_TARGET_PARAM RBM_EAX

// GenericPInvokeCalliHelper cookie parameter
#define REG_PINVOKE_COOKIE_PARAM REG_STK
#define REG_PINVOKE_COOKIE_PARAM REG_EBX

// IL stub's secret parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
#define REG_SECRET_STUB_PARAM REG_EAX
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/tinyarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class TinyArray

TinyArrayRef operator[](unsigned int n)
{
assert((n + 1) * bits_per_element <= sizeof(itemType) * 8);
assert((n + 1) * bits_per_element <= sizeof(storageType) * 8);
return TinyArrayRef(&data, n);
}
// only use this for clearing it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public TargetRegisterMap(TargetOS os)
switch (os)
{
case TargetOS.Windows:
case TargetOS.Linux:
Arg0 = Register.ECX;
Arg1 = Register.EDX;
Result = Register.EAX;
Expand Down
68 changes: 12 additions & 56 deletions src/coreclr/vm/i386/asmhelpers.S
Original file line number Diff line number Diff line change
Expand Up @@ -620,69 +620,20 @@ NESTED_END VarargPInvokeStub, _TEXT
// Invoked for marshaling-required unmanaged CALLI calls as a stub.
// EAX - the unmanaged target
// ECX, EDX - arguments
// [ESP + 4] - the VASigCookie
// EBX - the VASigCookie
//
LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT
// save the target
push eax

// EAX <- VASigCookie
mov eax, [esp + 8] // skip target and retaddr

mov eax, [eax + VASigCookie__StubOffset]
test eax, eax

cmp dword ptr [ebx + VASigCookie__StubOffset], 0
jz LOCAL_LABEL(GoCallCalliWorker)
// ---------------------------------------

push eax

// stack layout at this point:
//
// | ... |
// | stack arguments | ESP + 16
// +----------------------+
// | VASigCookie* | ESP + 12
// +----------------------+
// | return address | ESP + 8
// +----------------------+
// | CALLI target address | ESP + 4
// +----------------------+
// | stub entry point | ESP + 0
// ------------------------

// remove VASigCookie from the stack
mov eax, [esp + 8]
mov [esp + 12], eax

// move stub entry point below the RA
mov eax, [esp]
mov [esp + 8], eax

// load EAX with the target address
pop eax
pop eax

// stack layout at this point:
//
// | ... |
// | stack arguments | ESP + 8
// +----------------------+
// | return address | ESP + 4
// +----------------------+
// | stub entry point | ESP + 0
// ------------------------

// CALLI target address is in EAX
ret
// Stub is already prepared, just jump to it
jmp dword ptr [ebx + VASigCookie__StubOffset]

LOCAL_LABEL(GoCallCalliWorker):
// the target is on the stack and will become m_Datum of PInvokeCalliFrame
// call the stub generating worker
pop eax

//
// target ptr in EAX, VASigCookie ptr in EDX
// call the stub generating worker
// target ptr in EAX, VASigCookie ptr in EBX
//

STUB_PROLOG
Expand All @@ -692,11 +643,16 @@ LOCAL_LABEL(GoCallCalliWorker):
// save target
push eax

#define STACK_ALIGN_PADDING 4
sub esp, STACK_ALIGN_PADDING // pass stack aligned to 0x10
push eax // unmanaged target
push dword ptr [esi + 4*7] // pVaSigCookie (first stack argument)
push ebx // pVaSigCookie (first stack argument)
push esi // pTransitionBlock

CHECK_STACK_ALIGNMENT
call C_FUNC(GenericPInvokeCalliStubWorker)
add esp, STACK_ALIGN_PADDING // restore alignment, callee pop args
#undef STACK_ALIGN_PADDING

// restore target
pop eax
Expand Down
63 changes: 7 additions & 56 deletions src/coreclr/vm/i386/asmhelpers.asm
Original file line number Diff line number Diff line change
Expand Up @@ -1142,69 +1142,20 @@ _VarargPInvokeStub@0 endp
; Invoked for marshaling-required unmanaged CALLI calls as a stub.
; EAX - the unmanaged target
; ECX, EDX - arguments
; [ESP + 4] - the VASigCookie
; EBX - the VASigCookie
;
_GenericPInvokeCalliHelper@0 proc public
; save the target
push eax

; EAX <- VASigCookie
mov eax, [esp + 8] ; skip target and retaddr

mov eax, [eax + VASigCookie__StubOffset]
test eax, eax

cmp dword ptr [ebx + VASigCookie__StubOffset], 0
jz GoCallCalliWorker
; ---------------------------------------

push eax

; stack layout at this point:
;
; | ... |
; | stack arguments | ESP + 16
; +----------------------+
; | VASigCookie* | ESP + 12
; +----------------------+
; | return address | ESP + 8
; +----------------------+
; | CALLI target address | ESP + 4
; +----------------------+
; | stub entry point | ESP + 0
; ------------------------

; remove VASigCookie from the stack
mov eax, [esp + 8]
mov [esp + 12], eax

; move stub entry point below the RA
mov eax, [esp]
mov [esp + 8], eax

; load EAX with the target address
pop eax
pop eax

; stack layout at this point:
;
; | ... |
; | stack arguments | ESP + 8
; +----------------------+
; | return address | ESP + 4
; +----------------------+
; | stub entry point | ESP + 0
; ------------------------

; CALLI target address is in EAX
ret
; Stub is already prepared, just jump to it
jmp dword ptr [ebx + VASigCookie__StubOffset]

GoCallCalliWorker:
; the target is on the stack and will become m_Datum of PInvokeCalliFrame
; call the stub generating worker
pop eax

;
; target ptr in EAX, VASigCookie ptr in EDX
; call the stub generating worker
; target ptr in EAX, VASigCookie ptr in EBX
;

STUB_PROLOG
Expand All @@ -1215,7 +1166,7 @@ GoCallCalliWorker:
push eax

push eax ; unmanaged target
push dword ptr [esi + 4*7] ; pVaSigCookie (first stack argument)
push ebx ; pVaSigCookie (first stack argument)
push esi ; pTransitionBlock

call _GenericPInvokeCalliStubWorker@12
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/i386/jithelp.S
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ LEAF_ENTRY JIT_WriteBarrierGroup, _TEXT
ret
LEAF_END JIT_WriteBarrierGroup, _TEXT

// Pointer to JIT_WriteBarrierEAX
.data
.align 4
.global C_FUNC(JIT_WriteBarrierEAX_Loc)
Expand All @@ -396,6 +397,7 @@ LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT
addl $_GLOBAL_OFFSET_TABLE_+(2b-1b), %eax
.intel_syntax noprefix
mov eax, dword ptr [eax + C_FUNC(JIT_WriteBarrierEAX_Loc)@GOT]
mov eax, [eax]
xchg eax, dword ptr [esp]
ret
LEAF_END JIT_WriteBarrier_Callable, _TEXT
Expand Down
Loading