-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Support frozen struct returns for Swift calls #99704
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
Changes from all commits
9b4357f
9cbc75e
c8d12ed
e28e51d
1a4034c
0153efd
ca4bd39
d3163ec
35a106a
8005056
f456f6f
6d9c0b8
6580269
5e19124
7bed897
93b81fe
1842c04
daff872
5119a6b
ec9620c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1817,6 +1817,15 @@ regNumber CallArgs::GetCustomRegister(Compiler* comp, CorInfoCallConvExtension c | |
} | ||
} | ||
|
||
#if defined(TARGET_AMD64) && defined(SWIFT_SUPPORT) | ||
// TODO-Cleanup: Unify this with hasFixedRetBuffReg. That will | ||
// likely be necessary for the reverse pinvoke support regardless. | ||
if (cc == CorInfoCallConvExtension::Swift) | ||
{ | ||
return REG_SWIFT_ARG_RET_BUFF; | ||
} | ||
#endif | ||
|
||
break; | ||
|
||
case WellKnownArg::VirtualStubCell: | ||
|
@@ -26841,6 +26850,14 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, | |
{ | ||
assert(varTypeIsStruct(returnType)); | ||
|
||
#ifdef SWIFT_SUPPORT | ||
if (callConv == CorInfoCallConvExtension::Swift) | ||
{ | ||
InitializeSwiftReturnRegs(comp, retClsHnd); | ||
break; | ||
} | ||
#endif | ||
|
||
#ifdef UNIX_AMD64_ABI | ||
|
||
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; | ||
|
@@ -26944,6 +26961,31 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, | |
#endif | ||
} | ||
|
||
#ifdef SWIFT_SUPPORT | ||
//--------------------------------------------------------------------------------------- | ||
// InitializeSwiftReturnRegs: | ||
// Initialize the Return Type Descriptor for a method that returns with the | ||
// Swift calling convention. | ||
// | ||
// Parameters: | ||
// comp - Compiler instance | ||
// clsHnd - Struct type being returned | ||
// | ||
void ReturnTypeDesc::InitializeSwiftReturnRegs(Compiler* comp, CORINFO_CLASS_HANDLE clsHnd) | ||
{ | ||
const CORINFO_SWIFT_LOWERING* lowering = comp->GetSwiftLowering(clsHnd); | ||
assert(!lowering->byReference); | ||
|
||
static_assert_no_msg(MAX_SWIFT_LOWERED_ELEMENTS <= MAX_RET_REG_COUNT); | ||
assert(lowering->numLoweredElements <= MAX_RET_REG_COUNT); | ||
|
||
for (size_t i = 0; i < lowering->numLoweredElements; i++) | ||
{ | ||
m_regType[i] = JITtype2varType(lowering->loweredElements[i]); | ||
} | ||
} | ||
#endif | ||
|
||
//--------------------------------------------------------------------------------------- | ||
// InitializeLongReturnType: | ||
// Initialize the Return Type Descriptor for a method that returns a TYP_LONG | ||
|
@@ -27007,8 +27049,9 @@ void ReturnTypeDesc::InitializeReturnType(Compiler* comp, | |
// GetABIReturnReg: Return i'th return register as per target ABI | ||
// | ||
// Arguments: | ||
// idx - Index of the return register. | ||
// The first return register has an index of 0 and so on. | ||
// idx - Index of the return register. | ||
// The first return register has an index of 0 and so on. | ||
// callConv - Associated calling convention | ||
// | ||
// Return Value: | ||
// Returns i'th return register as per target ABI. | ||
|
@@ -27017,13 +27060,44 @@ void ReturnTypeDesc::InitializeReturnType(Compiler* comp, | |
// x86 and ARM return long in multiple registers. | ||
// ARM and ARM64 return HFA struct in multiple registers. | ||
// | ||
regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) const | ||
regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx, CorInfoCallConvExtension callConv) const | ||
{ | ||
unsigned count = GetReturnRegCount(); | ||
assert(idx < count); | ||
|
||
regNumber resultReg = REG_NA; | ||
|
||
#ifdef SWIFT_SUPPORT | ||
if (callConv == CorInfoCallConvExtension::Swift) | ||
{ | ||
static const regNumber swiftIntReturnRegs[] = {REG_SWIFT_INTRET_ORDER}; | ||
static const regNumber swiftFloatReturnRegs[] = {REG_SWIFT_FLOATRET_ORDER}; | ||
assert((idx < ArrLen(swiftIntReturnRegs)) && (idx < ArrLen(swiftFloatReturnRegs))); | ||
unsigned intRegIdx = 0; | ||
unsigned floatRegIdx = 0; | ||
for (unsigned i = 0; i < idx; i++) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this isn't on a hot path, and we have at most 4 return registers for a Swift call, I'm guessing it's not worth caching the return registers used so we can skip this loop? Though we do call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally we would keep all the registers and also the offsets as part of this type, from a simple code hygiene standpoint, but increasing its size increases the size of I don't think there's anything to be concerned about wrt. throughput here. |
||
{ | ||
if (varTypeUsesIntReg(GetReturnRegType(i))) | ||
{ | ||
intRegIdx++; | ||
} | ||
else | ||
{ | ||
floatRegIdx++; | ||
} | ||
} | ||
|
||
if (varTypeUsesIntReg(GetReturnRegType(idx))) | ||
{ | ||
return swiftIntReturnRegs[intRegIdx]; | ||
} | ||
else | ||
{ | ||
return swiftFloatReturnRegs[floatRegIdx]; | ||
} | ||
} | ||
#endif | ||
|
||
#ifdef UNIX_AMD64_ABI | ||
var_types regType0 = GetReturnRegType(0); | ||
|
||
|
@@ -27171,7 +27245,7 @@ regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) const | |
// GetABIReturnRegs: get the mask of return registers as per target arch ABI. | ||
// | ||
// Arguments: | ||
// None | ||
// callConv - The calling convention | ||
// | ||
// Return Value: | ||
// reg mask of return registers in which the return type is returned. | ||
|
@@ -27181,14 +27255,14 @@ regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) const | |
// of return registers and wants to know the set of return registers. | ||
// | ||
// static | ||
regMaskTP ReturnTypeDesc::GetABIReturnRegs() const | ||
regMaskTP ReturnTypeDesc::GetABIReturnRegs(CorInfoCallConvExtension callConv) const | ||
{ | ||
regMaskTP resultMask = RBM_NONE; | ||
|
||
unsigned count = GetReturnRegCount(); | ||
for (unsigned i = 0; i < count; ++i) | ||
{ | ||
resultMask |= genRegMask(GetABIReturnReg(i)); | ||
resultMask |= genRegMask(GetABIReturnReg(i, callConv)); | ||
} | ||
|
||
return resultMask; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MAX_RET_REG_COUNT
is already 4 on ARM64, but it might be helpful to the reader tostatic_assert
that here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a static assert.