Skip to content

[CI run only] Enable FEATURE_INSTANTIATINGSTUB_AS_IL on win-x86 #116331

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

Closed
Closed
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
4 changes: 1 addition & 3 deletions src/coreclr/clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ if(NOT CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-DFEATURE_PORTABLE_SHUFFLE_THUNKS)
endif()

if(CLR_CMAKE_TARGET_UNIX OR NOT CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-DFEATURE_INSTANTIATINGSTUB_AS_IL)
endif()
add_definitions(-DFEATURE_INSTANTIATINGSTUB_AS_IL)

add_compile_definitions(FEATURE_CODE_VERSIONING)
add_definitions(-DFEATURE_COLLECTIBLE_TYPES)
Expand Down
12 changes: 4 additions & 8 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1172,14 +1172,12 @@ class CodeGen final : public CodeGenInterface

#endif

#ifndef TARGET_X86
void genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArgVarNum);
#endif // !TARGET_X86

#ifdef TARGET_X86
bool genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk);
void genPushReg(var_types type, regNumber srcReg);
void genPutArgStkFieldList(GenTreePutArgStk* putArgStk);
void genPutArgStkPushFieldList(GenTreePutArgStk* putArgStk);
#endif // TARGET_X86

void genPutStructArgStk(GenTreePutArgStk* treeNode);
Expand All @@ -1194,9 +1192,8 @@ class CodeGen final : public CodeGenInterface
void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode);
#ifdef TARGET_X86
void genStructPutArgPush(GenTreePutArgStk* putArgStkNode);
#else
void genStructPutArgPartialRepMovs(GenTreePutArgStk* putArgStkNode);
#endif
void genStructPutArgPartialRepMovs(GenTreePutArgStk* putArgStkNode);

void genCodeForStoreBlk(GenTreeBlk* storeBlkNode);
void genCodeForInitBlkLoop(GenTreeBlk* initBlkNode);
Expand Down Expand Up @@ -1294,10 +1291,9 @@ class CodeGen final : public CodeGenInterface

#ifdef TARGET_X86
bool m_pushStkArg;
#else // !TARGET_X86
unsigned m_stkArgVarNum;
unsigned m_stkArgOffset;
#endif // !TARGET_X86
unsigned m_stkArgVarNum = BAD_VAR_NUM;
unsigned m_stkArgOffset;

#if defined(DEBUG) && defined(TARGET_XARCH)
void genStackPointerCheck(bool doStackPointerCheck,
Expand Down
22 changes: 16 additions & 6 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,7 @@ void CodeGenInterface::CopyRegisterInfo()
CodeGen::CodeGen(Compiler* theCompiler)
: CodeGenInterface(theCompiler)
{
#if !defined(TARGET_X86)
m_stkArgVarNum = BAD_VAR_NUM;
#endif

#if defined(UNIX_X86_ABI)
curNestedAlignment = 0;
Expand Down Expand Up @@ -4456,7 +4454,7 @@ void CodeGen::genFinalizeFrame()

#if defined(TARGET_X86)

if (compiler->compTailCallUsed)
if (compiler->compTailCallViaJitHelperUsed)
{
// If we are generating a helper-based tailcall, we've set the tailcall helper "flags"
// argument to "1", indicating to the tailcall helper that we've saved the callee-saved
Expand Down Expand Up @@ -5895,10 +5893,22 @@ unsigned CodeGen::getFirstArgWithStackSlot()
return BAD_VAR_NUM;
#elif defined(TARGET_AMD64)
return 0;
#else // TARGET_X86
// Not implemented for x86.
NYI_X86("getFirstArgWithStackSlot not yet implemented for x86.");
#elif defined(TARGET_X86)
// On x86 args are passed on the stack in reverse, so the base is the last stack argument.
for (unsigned i = compiler->info.compArgsCount; i != 0; i--)
{
const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(i - 1);
assert(abiInfo.NumSegments == 1);
if (abiInfo.Segment(0).IsPassedOnStack())
{
return i - 1;
}
}

assert(!"Expected to find stack parameter");
return BAD_VAR_NUM;
#else
#error Not implemented
#endif // TARGET_X86
}

Expand Down
15 changes: 10 additions & 5 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,14 @@ void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode,

#ifdef TARGET_X86
assert(dstReg != REG_SPBASE);
inst_Mov(TYP_I_IMPL, dstReg, REG_SPBASE, /* canSkip */ false);
if (m_stkArgVarNum == BAD_VAR_NUM)
{
inst_Mov(TYP_I_IMPL, dstReg, REG_SPBASE, /* canSkip */ false);
}
else
{
GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, dstReg, m_stkArgVarNum, putArgNode->getArgOffset());
}
#else // !TARGET_X86
GenTree* dstAddr = putArgNode;
if (dstAddr->GetRegNum() != dstReg)
Expand Down Expand Up @@ -1834,10 +1841,9 @@ void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode,
// outArgVarNum - The lclVar num for the argument
//
// Notes:
// The x86 version of this is in codegenxarch.cpp, and doesn't take an
// outArgVarNum, as it pushes its args onto the stack.
// The primary x86 version of this is genPutArgStkPushFieldList in
// codegenxarch.cpp. This version is only used for fast tailcalls on x86.
//
#ifndef TARGET_X86
void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArgVarNum)
{
assert(putArgStk->gtOp1->OperIs(GT_FIELD_LIST));
Expand Down Expand Up @@ -1884,7 +1890,6 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArg
#endif
}
}
#endif // !TARGET_X86

//------------------------------------------------------------------------
// genSetBlockSize: Ensure that the block size is in the given register
Expand Down
78 changes: 59 additions & 19 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4126,7 +4126,6 @@ void CodeGen::genStructPutArgPush(GenTreePutArgStk* putArgNode)
}
#endif // TARGET_X86

#ifndef TARGET_X86
//------------------------------------------------------------------------
// genStructPutArgPartialRepMovs: Generates code for passing a struct arg by value on stack using
// a mix of pointer-sized stores, "movsq" and "rep movsd".
Expand Down Expand Up @@ -4217,7 +4216,6 @@ void CodeGen::genStructPutArgPartialRepMovs(GenTreePutArgStk* putArgNode)

assert(numGCSlotsCopied == layout->GetGCPtrCount());
}
#endif // !TARGET_X86

//------------------------------------------------------------------------
// If any Vector3 args are on stack and they are not pass-by-ref, the upper 32bits
Expand Down Expand Up @@ -8107,15 +8105,15 @@ bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk)
}

//---------------------------------------------------------------------
// genPutArgStkFieldList - generate code for passing a GT_FIELD_LIST arg on the stack.
// genPutArgStkPushFieldList - generate code for passing a GT_FIELD_LIST arg on the stack.
//
// Arguments
// treeNode - the GT_PUTARG_STK node whose op1 is a GT_FIELD_LIST
//
// Return value:
// None
//
void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk)
void CodeGen::genPutArgStkPushFieldList(GenTreePutArgStk* putArgStk)
{
GenTreeFieldList* const fieldList = putArgStk->gtOp1->AsFieldList();
assert(fieldList != nullptr);
Expand Down Expand Up @@ -8332,28 +8330,63 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* putArgStk)

if (data->OperIs(GT_FIELD_LIST))
{
genPutArgStkFieldList(putArgStk);
if (putArgStk->putInIncomingArgArea())
{
genPutArgStkFieldList(putArgStk, getBaseVarForPutArgStk(putArgStk));
}
else
{
genPutArgStkPushFieldList(putArgStk);
}
return;
}

if (varTypeIsStruct(targetType))
{
genAdjustStackForPutArgStk(putArgStk);
genPutStructArgStk(putArgStk);
if (putArgStk->putInIncomingArgArea())
{
m_pushStkArg = false;
m_stkArgVarNum = getBaseVarForPutArgStk(putArgStk);
m_stkArgOffset = putArgStk->getArgOffset();
genPutStructArgStk(putArgStk);
m_stkArgVarNum = BAD_VAR_NUM;
}
else
{
genAdjustStackForPutArgStk(putArgStk);
genPutStructArgStk(putArgStk);
}
return;
}

genConsumeRegs(data);

if (data->isUsedFromReg())
if (putArgStk->putInIncomingArgArea())
{
genPushReg(targetType, data->GetRegNum());
unsigned baseVarNum = getBaseVarForPutArgStk(putArgStk);
if (data->isContainedIntOrIImmed())
{
GetEmitter()->emitIns_S_I(ins_Store(targetType), emitTypeSize(targetType), baseVarNum,
putArgStk->getArgOffset(), (int)data->AsIntConCommon()->IconValue());
}
else
{
GetEmitter()->emitIns_S_R(ins_Store(targetType), emitTypeSize(targetType), data->GetRegNum(), baseVarNum,
putArgStk->getArgOffset());
}
}
else
{
assert(genTypeSize(data) == TARGET_POINTER_SIZE);
inst_TT(INS_push, emitTypeSize(data), data);
AddStackLevel(TARGET_POINTER_SIZE);
if (data->isUsedFromReg())
{
genPushReg(targetType, data->GetRegNum());
}
else
{
assert(genTypeSize(data) == TARGET_POINTER_SIZE);
inst_TT(INS_push, emitTypeSize(data), data);
AddStackLevel(TARGET_POINTER_SIZE);
}
}
#else // !TARGET_X86
{
Expand Down Expand Up @@ -8543,7 +8576,14 @@ void CodeGen::genStoreRegToStackArg(var_types type, regNumber srcReg, int offset
}
else
{
GetEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, offset);
if (m_stkArgVarNum != BAD_VAR_NUM)
{
GetEmitter()->emitIns_S_R(ins, attr, srcReg, m_stkArgVarNum, m_stkArgOffset + offset);
}
else
{
GetEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, offset);
}
}
#else // !TARGET_X86
assert(m_stkArgVarNum != BAD_VAR_NUM);
Expand Down Expand Up @@ -8571,7 +8611,7 @@ void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk)
var_types targetType = source->TypeGet();

#if defined(TARGET_X86) && defined(FEATURE_SIMD)
if (putArgStk->isSIMD12())
if (putArgStk->isSIMD12() && !putArgStk->putInIncomingArgArea())
{
genPutArgStkSimd12(putArgStk);
return;
Expand All @@ -8593,11 +8633,10 @@ void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk)
case GenTreePutArgStk::Kind::RepInstr:
genStructPutArgRepMovs(putArgStk);
break;
#ifndef TARGET_X86

case GenTreePutArgStk::Kind::PartialRepInstr:
genStructPutArgPartialRepMovs(putArgStk);
break;
#endif // !TARGET_X86

case GenTreePutArgStk::Kind::Unroll:
genStructPutArgUnroll(putArgStk);
Expand Down Expand Up @@ -10567,7 +10606,8 @@ void CodeGen::genFnEpilog(BasicBlock* block)
// Add 'compiler->compLclFrameSize' to ESP. Use "pop ECX" for that, except in cases
// where ECX may contain some state.

if ((frameSize == TARGET_POINTER_SIZE) && !compiler->compJmpOpUsed && !compiler->compIsAsync())
if ((frameSize == TARGET_POINTER_SIZE) && !compiler->compJmpOpUsed && !compiler->compIsAsync() &&
!compiler->compFastTailCallUsed)
{
inst_RV(INS_pop, REG_ECX, TYP_I_IMPL);
regSet.verifyRegUsed(REG_ECX);
Expand Down Expand Up @@ -10655,7 +10695,7 @@ void CodeGen::genFnEpilog(BasicBlock* block)
}
#ifdef TARGET_X86
else if ((compiler->compLclFrameSize == REGSIZE_BYTES) && !compiler->compJmpOpUsed &&
!compiler->compIsAsync())
!compiler->compIsAsync() && !compiler->compFastTailCallUsed)
{
// "pop ecx" will make ESP point to the callee-saved registers
inst_RV(INS_pop, REG_ECX, TYP_I_IMPL);
Expand Down Expand Up @@ -10809,7 +10849,7 @@ void CodeGen::genFnEpilog(BasicBlock* block)
#if FEATURE_FASTTAILCALL
else
{
genCallInstruction(jmpNode->AsCall());
genCallInstruction(jmpNode->AsCall() X86_ARG(0));
}
#endif // FEATURE_FASTTAILCALL
}
Expand Down
14 changes: 9 additions & 5 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9877,11 +9877,15 @@ class Compiler

InlineResult* compInlineResult; // The result of importing the inlinee method.

bool compDoAggressiveInlining = false; // If true, mark every method as CORINFO_FLG_FORCEINLINE
bool compJmpOpUsed = false; // Does the method do a JMP
bool compLongUsed = false; // Does the method use TYP_LONG
bool compFloatingPointUsed = false; // Does the method use TYP_FLOAT or TYP_DOUBLE
bool compTailCallUsed = false; // Does the method do a tailcall
bool compDoAggressiveInlining = false; // If true, mark every method as CORINFO_FLG_FORCEINLINE
bool compJmpOpUsed = false; // Does the method do a JMP
bool compLongUsed = false; // Does the method use TYP_LONG
bool compFloatingPointUsed = false; // Does the method use TYP_FLOAT or TYP_DOUBLE
bool compTailCallUsed = false; // Does the method do a tailcall
#ifdef TARGET_X86
bool compTailCallViaJitHelperUsed = false;
bool compFastTailCallUsed = false;
#endif
bool compTailPrefixSeen = false; // Does the method IL have tail. prefix
bool compLocallocSeen = false; // Does the method IL have localloc opcode
bool compLocallocUsed = false; // Does the method use localloc.
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11266,12 +11266,14 @@ void emitter::emitIns_Call(const EmitCallParams& params)
id->idAddr()->iiaAddrMode.amScale = params.xmul ? emitEncodeScale(params.xmul) : emitter::OPSZ1;

code_t code = insCodeMR(ins);
#ifndef TARGET_X86
if (ins == INS_tail_i_jmp)
{
// Tailcall with addressing mode/register needs to be rex.w
// prefixed to be recognized as part of epilog by unwinder.
code = AddRexWPrefix(id, code);
}
#endif

sz = emitInsSizeAM(id, code);

Expand Down Expand Up @@ -14386,12 +14388,14 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
if ((ins == INS_call) || (ins == INS_tail_i_jmp))
{
code = AddX86PrefixIfNeeded(id, code, size);
#ifndef TARGET_X86
if (ins == INS_tail_i_jmp)
{
// tail call with addressing mode (or through register) needs rex.w
// prefix to be recognized by unwinder as part of epilog.
code = AddRexWPrefix(id, code);
}
#endif

// Special case: call via a register
if (id->idIsCallRegPtr())
Expand Down
Loading
Loading