@@ -639,7 +639,7 @@ bool Compiler::isNativePrimitiveStructType(CORINFO_CLASS_HANDLE clsHnd)
639
639
// For vector calling conventions, a vector is considered a "primitive"
640
640
// type, as it is passed in a single register.
641
641
//
642
- var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd, bool isVarArg )
642
+ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd)
643
643
{
644
644
assert(structSize != 0);
645
645
@@ -648,37 +648,32 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS
648
648
// Start by determining if we have an HFA/HVA with a single element.
649
649
if (GlobalJitOptions::compFeatureHfa)
650
650
{
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)
654
652
{
655
- switch (structSize)
656
- {
657
- case 4:
658
- case 8:
653
+ case 4:
654
+ case 8:
659
655
#ifdef TARGET_ARM64
660
- case 16:
656
+ case 16:
661
657
#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))
662
662
{
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)
666
664
{
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;
675
670
}
676
671
}
677
672
}
678
- if (useType != TYP_UNKNOWN)
679
- {
680
- return useType;
681
- }
673
+ }
674
+ if (useType != TYP_UNKNOWN)
675
+ {
676
+ return useType;
682
677
}
683
678
}
684
679
@@ -733,230 +728,6 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS
733
728
return useType;
734
729
}
735
730
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
-
960
731
//-----------------------------------------------------------------------------
961
732
// getReturnTypeForStruct:
962
733
// 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,
1136
907
//
1137
908
// The ABI for struct returns in varArg methods, is same as the normal case,
1138
909
// so pass false for isVararg
1139
- useType = getPrimitiveTypeForStruct(structSize, clsHnd, /*isVararg=*/false );
910
+ useType = getPrimitiveTypeForStruct(structSize, clsHnd);
1140
911
1141
912
if (useType != TYP_UNKNOWN)
1142
913
{
@@ -4082,8 +3853,8 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
4082
3853
JITDUMP("\n"
4083
3854
"compRsvdRegCheck\n"
4084
3855
" frame size = %6d\n"
4085
- " compArgSize = %6d\n",
4086
- frameSize, compArgSize );
3856
+ " lvaParameterStackSize = %6d\n",
3857
+ frameSize, lvaParameterStackSize );
4087
3858
4088
3859
if (opts.MinOpts())
4089
3860
{
@@ -4153,7 +3924,7 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
4153
3924
JITDUMP(" maxR11NegativeEncodingOffset = %6d\n", maxR11NegativeEncodingOffset);
4154
3925
4155
3926
// -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;
4157
3928
JITDUMP(" maxR11PositiveOffset = %6d\n", maxR11PositiveOffset);
4158
3929
4159
3930
// The value is positive, but represents a negative offset from R11.
@@ -4184,8 +3955,8 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
4184
3955
JITDUMP(" maxSPPositiveEncodingOffset = %6d\n", maxSPPositiveEncodingOffset);
4185
3956
4186
3957
// -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;
4189
3960
4190
3961
if (codeGen->isFramePointerUsed())
4191
3962
{
0 commit comments