{
argSize = genTypeSize(argType);
}
- const unsigned argAlignment = eeGetArgAlignment(argType, (hfaType == TYP_FLOAT));
- const unsigned argSizeWithPadding = roundUp(argSize, argAlignment);
- return argSizeWithPadding;
+
+ const unsigned argSizeAlignment = eeGetArgSizeAlignment(argType, (hfaType == TYP_FLOAT));
+ const unsigned alignedArgSize = roundUp(argSize, argSizeAlignment);
+ return alignedArgSize;
#endif
}
//------------------------------------------------------------------------
-// eeGetArgAlignment: Return arg passing alignment for the given type.
+// eeGetArgSizeAlignment: Return alignment for an argument size.
//
// Arguments:
// type - the argument type
// isFloatHfa - is it an HFA<float> type
//
// Return value:
-// the required alignment in bytes.
+// the required argument size alignment in bytes.
//
// Notes:
-// It currently doesn't return smaller than required alignment for arm32 (4 bytes for double and int64)
-// but it does not lead to issues because its alignment requirements are satisfied in other code parts.
-// TODO: fix this function and delete the other code that is handling this.
+// Usually values passed on the stack are aligned to stack slot (i.e. pointer size), except for
+// on macOS ARM ABI that allows packing multiple args into a single stack slot.
+//
+// The arg size alignment can be different from the normal alignment. One
+// example is on arm32 where a struct containing a double and float can
+// explicitly have size 12 but with alignment 8, in which case the size is
+// aligned to 4 (the stack slot size) while frame layout must still handle
+// aligning the argument to 8.
//
// static
-unsigned Compiler::eeGetArgAlignment(var_types type, bool isFloatHfa)
+unsigned Compiler::eeGetArgSizeAlignment(var_types type, bool isFloatHfa)
{
if (compMacOsArm64Abi())
{
{
varDsc->SetOtherArgReg(genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_INT));
}
+
+#if FEATURE_FASTTAILCALL
+ // Check if arg was split between registers and stack.
+ if (!varTypeUsesFloatReg(argType))
+ {
+ unsigned firstRegArgNum = genMapIntRegNumToRegArgNum(varDsc->GetArgReg());
+ unsigned lastRegArgNum = firstRegArgNum + cSlots - 1;
+ if (lastRegArgNum >= varDscInfo->maxIntRegArgNum)
+ {
+ assert(varDscInfo->stackArgSize == 0);
+ unsigned numEnregistered = varDscInfo->maxIntRegArgNum - firstRegArgNum;
+ varDsc->SetStackOffset(-(int)numEnregistered * REGSIZE_BYTES);
+ varDscInfo->stackArgSize += (cSlots - numEnregistered) * REGSIZE_BYTES;
+ JITDUMP("set user arg V%02u offset to %d\n", varDscInfo->varNum, varDsc->GetStackOffset());
+ }
+ }
+#endif
#endif // TARGET_ARM
#ifdef DEBUG
#endif // TARGET_XXX
#if FEATURE_FASTTAILCALL
- const unsigned argAlignment = eeGetArgAlignment(origArgType, (hfaType == TYP_FLOAT));
- if (compMacOsArm64Abi())
- {
- varDscInfo->stackArgSize = roundUp(varDscInfo->stackArgSize, argAlignment);
- }
-
- assert((argSize % argAlignment) == 0);
- assert((varDscInfo->stackArgSize % argAlignment) == 0);
+#ifdef TARGET_ARM
+ unsigned argAlignment = cAlign * TARGET_POINTER_SIZE;
+#else
+ unsigned argAlignment = eeGetArgSizeAlignment(origArgType, (hfaType == TYP_FLOAT));
+ // We expect the following rounding operation to be a noop on all
+ // ABIs except ARM (where we have 8-byte aligned args) and macOS
+ // ARM64 (that allows to pack multiple smaller parameters in a
+ // single stack slot).
+ assert(compMacOsArm64Abi() || ((varDscInfo->stackArgSize % argAlignment) == 0));
+#endif
+ varDscInfo->stackArgSize = roundUp(varDscInfo->stackArgSize, argAlignment);
JITDUMP("set user arg V%02u offset to %u\n", varDscInfo->varNum, varDscInfo->stackArgSize);
varDsc->SetStackOffset(varDscInfo->stackArgSize);
if (lvIsParam)
{
assert(varTypeIsStruct(lvType));
- const bool isFloatHfa = (lvIsHfa() && (GetHfaType() == TYP_FLOAT));
- const unsigned argAlignment = Compiler::eeGetArgAlignment(lvType, isFloatHfa);
- return roundUp(lvExactSize, argAlignment);
+ const bool isFloatHfa = (lvIsHfa() && (GetHfaType() == TYP_FLOAT));
+ const unsigned argSizeAlignment = Compiler::eeGetArgSizeAlignment(lvType, isFloatHfa);
+ return roundUp(lvExactSize, argSizeAlignment);
}
#if defined(FEATURE_SIMD) && !defined(TARGET_64BIT)
}
#endif // TARGET_ARM
const bool isFloatHfa = (varDsc->lvIsHfa() && (varDsc->GetHfaType() == TYP_FLOAT));
- const unsigned argAlignment = eeGetArgAlignment(varDsc->lvType, isFloatHfa);
+ const unsigned argAlignment = eeGetArgSizeAlignment(varDsc->lvType, isFloatHfa);
if (compMacOsArm64Abi())
{
argOffs = roundUp(argOffs, argAlignment);