Skip to content

Commit 58209bb

Browse files
authored
JIT: Delete old parameter ABI classification (#112884)
1 parent 38b7d03 commit 58209bb

17 files changed

+270
-2037
lines changed

src/coreclr/jit/CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ set( JIT_SOURCES
163163
rationalize.cpp
164164
redundantbranchopts.cpp
165165
regalloc.cpp
166-
registerargconvention.cpp
167166
regMaskTPOps.cpp
168167
regset.cpp
169168
scev.cpp
@@ -360,7 +359,6 @@ set( JIT_HEADERS
360359
rangecheckcloning.h
361360
rationalize.h
362361
regalloc.h
363-
registerargconvention.h
364362
register.h
365363
regset.h
366364
scev.h

src/coreclr/jit/abi.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,9 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp,
679679
const CORINFO_SWIFT_LOWERING* lowering = comp->GetSwiftLowering(structLayout->GetClassHandle());
680680
if (lowering->byReference)
681681
{
682-
return m_classifier.Classify(comp, TYP_I_IMPL, nullptr, WellKnownArg::None);
682+
ABIPassingInformation abiInfo = m_classifier.Classify(comp, TYP_I_IMPL, nullptr, WellKnownArg::None);
683+
assert(abiInfo.NumSegments == 1);
684+
return ABIPassingInformation::FromSegment(comp, /* passedByRef */ true, abiInfo.Segment(0));
683685
}
684686

685687
ArrayStack<ABIPassingSegment> segments(comp->getAllocator(CMK_ABI));

src/coreclr/jit/codegencommon.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -4496,7 +4496,6 @@ void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegS
44964496
const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum);
44974497
if (abiInfo.IsSplitAcrossRegistersAndStack())
44984498
{
4499-
assert(var->lvIsSplit);
45004499
JITDUMP("Homing stack part of split parameter V%02u\n", lclNum);
45014500

45024501
assert(abiInfo.NumSegments == 2);

src/coreclr/jit/codegenloongarch64.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4713,7 +4713,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
47134713
if (treeNode->putInIncomingArgArea())
47144714
{
47154715
varNumOut = getFirstArgWithStackSlot();
4716-
argOffsetMax = compiler->compArgSize;
4716+
argOffsetMax = compiler->lvaParameterStackSize;
47174717
#if FEATURE_FASTTAILCALL
47184718
// This must be a fast tail call.
47194719
assert(treeNode->gtCall->IsFastTailCall());

src/coreclr/jit/codegenriscv64.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4801,7 +4801,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
48014801
if (treeNode->putInIncomingArgArea())
48024802
{
48034803
varNumOut = getFirstArgWithStackSlot();
4804-
argOffsetMax = compiler->compArgSize;
4804+
argOffsetMax = compiler->lvaParameterStackSize;
48054805
#if FEATURE_FASTTAILCALL
48064806
// This must be a fast tail call.
48074807
assert(treeNode->gtCall->IsFastTailCall());

src/coreclr/jit/compiler.cpp

+25-254
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ bool Compiler::isNativePrimitiveStructType(CORINFO_CLASS_HANDLE clsHnd)
639639
// For vector calling conventions, a vector is considered a "primitive"
640640
// type, as it is passed in a single register.
641641
//
642-
var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd, bool isVarArg)
642+
var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd)
643643
{
644644
assert(structSize != 0);
645645

@@ -648,37 +648,32 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS
648648
// Start by determining if we have an HFA/HVA with a single element.
649649
if (GlobalJitOptions::compFeatureHfa)
650650
{
651-
// Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated
652-
// as if they are not HFA types.
653-
if (!(TargetArchitecture::IsArm64 && TargetOS::IsWindows && isVarArg))
651+
switch (structSize)
654652
{
655-
switch (structSize)
656-
{
657-
case 4:
658-
case 8:
653+
case 4:
654+
case 8:
659655
#ifdef TARGET_ARM64
660-
case 16:
656+
case 16:
661657
#endif // TARGET_ARM64
658+
{
659+
var_types hfaType = GetHfaType(clsHnd);
660+
// We're only interested in the case where the struct size is equal to the size of the hfaType.
661+
if (varTypeIsValidHfaType(hfaType))
662662
{
663-
var_types hfaType = GetHfaType(clsHnd);
664-
// We're only interested in the case where the struct size is equal to the size of the hfaType.
665-
if (varTypeIsValidHfaType(hfaType))
663+
if (genTypeSize(hfaType) == structSize)
666664
{
667-
if (genTypeSize(hfaType) == structSize)
668-
{
669-
useType = hfaType;
670-
}
671-
else
672-
{
673-
return TYP_UNKNOWN;
674-
}
665+
useType = hfaType;
666+
}
667+
else
668+
{
669+
return TYP_UNKNOWN;
675670
}
676671
}
677672
}
678-
if (useType != TYP_UNKNOWN)
679-
{
680-
return useType;
681-
}
673+
}
674+
if (useType != TYP_UNKNOWN)
675+
{
676+
return useType;
682677
}
683678
}
684679

@@ -733,230 +728,6 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS
733728
return useType;
734729
}
735730

736-
//-----------------------------------------------------------------------------
737-
// getArgTypeForStruct:
738-
// Get the type that is used to pass values of the given struct type.
739-
// If you have already retrieved the struct size then it should be
740-
// passed as the optional fourth argument, as this allows us to avoid
741-
// an extra call to getClassSize(clsHnd)
742-
//
743-
// Arguments:
744-
// clsHnd - the handle for the struct type
745-
// wbPassStruct - An "out" argument with information about how
746-
// the struct is to be passed
747-
// isVarArg - is vararg, used to ignore HFA types for Arm64 windows varargs
748-
// structSize - the size of the struct type,
749-
// or zero if we should call getClassSize(clsHnd)
750-
//
751-
// Return Value:
752-
// For wbPassStruct you can pass a 'nullptr' and nothing will be written
753-
// or returned for that out parameter.
754-
// When *wbPassStruct is SPK_PrimitiveType this method's return value
755-
// is the primitive type used to pass the struct.
756-
// When *wbPassStruct is SPK_ByReference this method's return value
757-
// is always TYP_UNKNOWN and the struct type is passed by reference to a copy
758-
// When *wbPassStruct is SPK_ByValue or SPK_ByValueAsHfa this method's return value
759-
// is always TYP_STRUCT and the struct type is passed by value either
760-
// using multiple registers or on the stack.
761-
//
762-
// Assumptions:
763-
// The size must be the size of the given type.
764-
// The given class handle must be for a value type (struct).
765-
//
766-
// Notes:
767-
// About HFA types:
768-
// When the clsHnd is a one element HFA type we return the appropriate
769-
// floating point primitive type and *wbPassStruct is SPK_PrimitiveType
770-
// If there are two or more elements in the HFA type then the this method's
771-
// return value is TYP_STRUCT and *wbPassStruct is SPK_ByValueAsHfa
772-
//
773-
var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
774-
structPassingKind* wbPassStruct,
775-
bool isVarArg,
776-
unsigned structSize)
777-
{
778-
var_types useType = TYP_UNKNOWN;
779-
structPassingKind howToPassStruct = SPK_Unknown; // We must change this before we return
780-
781-
assert(structSize != 0);
782-
783-
// Determine if we can pass the struct as a primitive type.
784-
// Note that on x86 we only pass specific pointer-sized structs that satisfy isTrivialPointerSizedStruct checks.
785-
#ifndef TARGET_X86
786-
#ifdef UNIX_AMD64_ABI
787-
788-
// An 8-byte struct may need to be passed in a floating point register
789-
// So we always consult the struct "Classifier" routine
790-
//
791-
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
792-
eeGetSystemVAmd64PassStructInRegisterDescriptor(clsHnd, &structDesc);
793-
794-
if (structDesc.passedInRegisters && (structDesc.eightByteCount != 1))
795-
{
796-
// We can't pass this as a primitive type.
797-
}
798-
else if (structDesc.eightByteClassifications[0] == SystemVClassificationTypeSSE)
799-
{
800-
// If this is passed as a floating type, use that.
801-
// Otherwise, we'll use the general case - we don't want to use the "EightByteType"
802-
// directly, because it returns `TYP_INT` for any integral type <= 4 bytes, and
803-
// we need to preserve small types.
804-
useType = GetEightByteType(structDesc, 0);
805-
}
806-
else
807-
#endif // UNIX_AMD64_ABI
808-
809-
// The largest arg passed in a single register is MAX_PASS_SINGLEREG_BYTES,
810-
// so we can skip calling getPrimitiveTypeForStruct when we
811-
// have a struct that is larger than that.
812-
//
813-
if (structSize <= MAX_PASS_SINGLEREG_BYTES)
814-
{
815-
// We set the "primitive" useType based upon the structSize
816-
// and also examine the clsHnd to see if it is an HFA of count one
817-
useType = getPrimitiveTypeForStruct(structSize, clsHnd, isVarArg);
818-
}
819-
#else
820-
if (isTrivialPointerSizedStruct(clsHnd))
821-
{
822-
useType = TYP_I_IMPL;
823-
}
824-
#endif // !TARGET_X86
825-
826-
// Did we change this struct type into a simple "primitive" type?
827-
//
828-
if (useType != TYP_UNKNOWN)
829-
{
830-
// Yes, we should use the "primitive" type in 'useType'
831-
howToPassStruct = SPK_PrimitiveType;
832-
}
833-
else // We can't replace the struct with a "primitive" type
834-
{
835-
// See if we can pass this struct by value, possibly in multiple registers
836-
// or if we should pass it by reference to a copy
837-
//
838-
if (structSize <= MAX_PASS_MULTIREG_BYTES)
839-
{
840-
// Structs that are HFA/HVA's are passed by value in multiple registers.
841-
// Arm64 Windows VarArg methods arguments will not classify HFA/HVA types, they will need to be treated
842-
// as if they are not HFA/HVA types.
843-
var_types hfaType;
844-
if (TargetArchitecture::IsArm64 && TargetOS::IsWindows && isVarArg)
845-
{
846-
hfaType = TYP_UNDEF;
847-
}
848-
else
849-
{
850-
hfaType = GetHfaType(clsHnd);
851-
}
852-
if (varTypeIsValidHfaType(hfaType))
853-
{
854-
// HFA's of count one should have been handled by getPrimitiveTypeForStruct
855-
assert(GetHfaCount(clsHnd) >= 2);
856-
857-
// setup wbPassType and useType indicate that this is passed by value as an HFA
858-
// using multiple registers
859-
// (when all of the parameters registers are used, then the stack will be used)
860-
howToPassStruct = SPK_ByValueAsHfa;
861-
useType = TYP_STRUCT;
862-
}
863-
else // Not an HFA struct type
864-
{
865-
866-
#ifdef UNIX_AMD64_ABI
867-
// The case of (structDesc.eightByteCount == 1) should have already been handled
868-
if ((structDesc.eightByteCount > 1) || !structDesc.passedInRegisters)
869-
{
870-
// setup wbPassType and useType indicate that this is passed by value in multiple registers
871-
// (when all of the parameters registers are used, then the stack will be used)
872-
howToPassStruct = SPK_ByValue;
873-
useType = TYP_STRUCT;
874-
}
875-
else
876-
{
877-
assert(structDesc.eightByteCount == 0);
878-
// Otherwise we pass this struct by reference to a copy
879-
// setup wbPassType and useType indicate that this is passed using one register
880-
// (by reference to a copy)
881-
howToPassStruct = SPK_ByReference;
882-
useType = TYP_UNKNOWN;
883-
}
884-
885-
#elif defined(TARGET_ARM64)
886-
887-
// Structs that are pointer sized or smaller should have been handled by getPrimitiveTypeForStruct
888-
assert(structSize > TARGET_POINTER_SIZE);
889-
890-
// On ARM64 structs that are 9-16 bytes are passed by value in multiple registers
891-
//
892-
if (structSize <= (TARGET_POINTER_SIZE * 2))
893-
{
894-
// setup wbPassType and useType indicate that this is passed by value in multiple registers
895-
// (when all of the parameters registers are used, then the stack will be used)
896-
howToPassStruct = SPK_ByValue;
897-
useType = TYP_STRUCT;
898-
}
899-
else // a structSize that is 17-32 bytes in size
900-
{
901-
// Otherwise we pass this struct by reference to a copy
902-
// setup wbPassType and useType indicate that this is passed using one register
903-
// (by reference to a copy)
904-
howToPassStruct = SPK_ByReference;
905-
useType = TYP_UNKNOWN;
906-
}
907-
908-
#elif defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
909-
910-
// Otherwise we pass this struct by value on the stack
911-
// setup wbPassType and useType indicate that this is passed by value according to the X86/ARM32 ABI
912-
// On LOONGARCH64 and RISCV64 struct that is 1-16 bytes is passed by value in one/two register(s)
913-
howToPassStruct = SPK_ByValue;
914-
useType = TYP_STRUCT;
915-
916-
#else // TARGET_XXX
917-
918-
noway_assert(!"Unhandled TARGET in getArgTypeForStruct (with FEATURE_MULTIREG_ARGS=1)");
919-
920-
#endif // TARGET_XXX
921-
}
922-
}
923-
else // (structSize > MAX_PASS_MULTIREG_BYTES)
924-
{
925-
// We have a (large) struct that can't be replaced with a "primitive" type
926-
// and can't be passed in multiple registers
927-
928-
#if defined(TARGET_X86) || defined(TARGET_ARM) || defined(UNIX_AMD64_ABI)
929-
930-
// Otherwise we pass this struct by value on the stack
931-
// setup wbPassType and useType indicate that this is passed by value according to the X86/ARM32 ABI
932-
howToPassStruct = SPK_ByValue;
933-
useType = TYP_STRUCT;
934-
935-
#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
936-
937-
// Otherwise we pass this struct by reference to a copy
938-
// setup wbPassType and useType indicate that this is passed using one register (by reference to a copy)
939-
howToPassStruct = SPK_ByReference;
940-
useType = TYP_UNKNOWN;
941-
942-
#else // TARGET_XXX
943-
944-
noway_assert(!"Unhandled TARGET in getArgTypeForStruct");
945-
946-
#endif // TARGET_XXX
947-
}
948-
}
949-
950-
// 'howToPassStruct' must be set to one of the valid values before we return
951-
assert(howToPassStruct != SPK_Unknown);
952-
if (wbPassStruct != nullptr)
953-
{
954-
*wbPassStruct = howToPassStruct;
955-
}
956-
957-
return useType;
958-
}
959-
960731
//-----------------------------------------------------------------------------
961732
// getReturnTypeForStruct:
962733
// Get the type that is used to return values of the given struct type.
@@ -1136,7 +907,7 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
1136907
//
1137908
// The ABI for struct returns in varArg methods, is same as the normal case,
1138909
// so pass false for isVararg
1139-
useType = getPrimitiveTypeForStruct(structSize, clsHnd, /*isVararg=*/false);
910+
useType = getPrimitiveTypeForStruct(structSize, clsHnd);
1140911

1141912
if (useType != TYP_UNKNOWN)
1142913
{
@@ -4082,8 +3853,8 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
40823853
JITDUMP("\n"
40833854
"compRsvdRegCheck\n"
40843855
" frame size = %6d\n"
4085-
" compArgSize = %6d\n",
4086-
frameSize, compArgSize);
3856+
" lvaParameterStackSize = %6d\n",
3857+
frameSize, lvaParameterStackSize);
40873858

40883859
if (opts.MinOpts())
40893860
{
@@ -4153,7 +3924,7 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
41533924
JITDUMP(" maxR11NegativeEncodingOffset = %6d\n", maxR11NegativeEncodingOffset);
41543925

41553926
// -1 because otherwise we are computing the address just beyond the last argument, which we don't need to do.
4156-
unsigned maxR11PositiveOffset = compArgSize + (2 * REGSIZE_BYTES) - 1;
3927+
unsigned maxR11PositiveOffset = lvaParameterStackSize + (2 * REGSIZE_BYTES) - 1;
41573928
JITDUMP(" maxR11PositiveOffset = %6d\n", maxR11PositiveOffset);
41583929

41593930
// The value is positive, but represents a negative offset from R11.
@@ -4184,8 +3955,8 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
41843955
JITDUMP(" maxSPPositiveEncodingOffset = %6d\n", maxSPPositiveEncodingOffset);
41853956

41863957
// -1 because otherwise we are computing the address just beyond the last argument, which we don't need to do.
4187-
assert(compArgSize + frameSize > 0);
4188-
unsigned maxSPPositiveOffset = compArgSize + frameSize - 1;
3958+
assert(lvaParameterStackSize + frameSize > 0);
3959+
unsigned maxSPPositiveOffset = lvaParameterStackSize + frameSize - 1;
41893960

41903961
if (codeGen->isFramePointerUsed())
41913962
{

0 commit comments

Comments
 (0)