Skip to content

Commit c28f3ad

Browse files
Armel support in crossgen2 (#43706)
This change adds support for armel target compilation in crossgen2 To use the feature compile an application using the --targetos Linux and --targetarch armel flags. Summary of changes - To avoid bloating the compilation matrix, the #ifdefs used in the JIT that were conditional on ARM_SOFTFP behavior have been changed in to variable checks. To avoid perf penalties, this dynamic behavior is only enabled for the jit intended for compiling using crossgen2. - Armel abi processing was integrated into the various parts of the managed crossgen2 codebase that correspond to components with special handling in the coreclr codebase - HFA support is disabled for Armel targets - Floating point registers are not used when passing arguments With this change it becomes possible to run crossgen2 on a Windows or Linux machine and target a Linux Armel target.
1 parent 65e45f1 commit c28f3ad

25 files changed

+506
-349
lines changed

src/coreclr/inc/corjitflags.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ class CORJIT_FLAGS
9797

9898
CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method
9999

100+
#if defined(TARGET_ARM)
101+
CORJIT_FLAG_SOFTFP_ABI = 43, // JIT should generate PC-relative address computations instead of EE relocation records
102+
#else // !defined(TARGET_ARM)
100103
CORJIT_FLAG_UNUSED16 = 43,
104+
#endif // !defined(TARGET_ARM)
105+
101106
CORJIT_FLAG_UNUSED17 = 44,
102107
CORJIT_FLAG_UNUSED18 = 45,
103108
CORJIT_FLAG_UNUSED19 = 46,

src/coreclr/inc/switches.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
// do not work reliably with conservative GC.
151151
#define FEATURE_CONSERVATIVE_GC 1
152152

153-
#if (defined(TARGET_ARM) && !defined(ARM_SOFTFP)) || defined(TARGET_ARM64)
153+
#if (defined(TARGET_ARM) && (!defined(ARM_SOFTFP) || defined(CONFIGURABLE_ARM_ABI))) || defined(TARGET_ARM64)
154154
#define FEATURE_HFA
155155
#endif
156156

src/coreclr/jit/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ if (CLR_CMAKE_BUILD_SUBSET_ALLJITS AND NOT CLR_CROSS_COMPONENTS_BUILD)
490490

491491
create_standalone_jit(TARGET clrjit_unix_armel_${ARCH_HOST_NAME} OS unix ARCH armel)
492492
create_standalone_jit(TARGET clrjit_unix_arm_${ARCH_HOST_NAME} OS unix ARCH arm)
493+
target_compile_definitions(clrjit_unix_arm_${ARCH_HOST_NAME} PRIVATE ARM_SOFTFP CONFIGURABLE_ARM_ABI)
493494
create_standalone_jit(TARGET clrjit_win_arm_${ARCH_HOST_NAME} OS win ARCH arm)
494495
create_standalone_jit(TARGET clrjit_win_x86_${ARCH_HOST_NAME} OS win ARCH x86)
495496
else()

src/coreclr/jit/codegencommon.cpp

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4004,40 +4004,38 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
40044004

40054005
if (doingFloat)
40064006
{
4007-
#if defined(FEATURE_HFA) || defined(UNIX_AMD64_ABI)
4008-
insCopy = ins_Copy(TYP_DOUBLE);
4009-
// Compute xtraReg here when we have a float argument
4010-
assert(xtraReg == REG_NA);
4007+
#ifndef UNIX_AMD64_ABI
4008+
if (GlobalJitOptions::compFeatureHfa)
4009+
#endif // !UNIX_AMD64_ABI
4010+
{
4011+
insCopy = ins_Copy(TYP_DOUBLE);
4012+
// Compute xtraReg here when we have a float argument
4013+
assert(xtraReg == REG_NA);
40114014

4012-
regMaskTP fpAvailMask;
4015+
regMaskTP fpAvailMask;
40134016

4014-
fpAvailMask = RBM_FLT_CALLEE_TRASH & ~regArgMaskLive;
4015-
#if defined(FEATURE_HFA)
4016-
fpAvailMask &= RBM_ALLDOUBLE;
4017-
#else
4018-
#if !defined(UNIX_AMD64_ABI)
4019-
#error Error. Wrong architecture.
4020-
#endif // !defined(UNIX_AMD64_ABI)
4021-
#endif // defined(FEATURE_HFA)
4017+
fpAvailMask = RBM_FLT_CALLEE_TRASH & ~regArgMaskLive;
4018+
if (GlobalJitOptions::compFeatureHfa)
4019+
{
4020+
fpAvailMask &= RBM_ALLDOUBLE;
4021+
}
40224022

4023-
if (fpAvailMask == RBM_NONE)
4024-
{
4025-
fpAvailMask = RBM_ALLFLOAT & ~regArgMaskLive;
4026-
#if defined(FEATURE_HFA)
4027-
fpAvailMask &= RBM_ALLDOUBLE;
4028-
#else
4029-
#if !defined(UNIX_AMD64_ABI)
4030-
#error Error. Wrong architecture.
4031-
#endif // !defined(UNIX_AMD64_ABI)
4032-
#endif // defined(FEATURE_HFA)
4033-
}
4023+
if (fpAvailMask == RBM_NONE)
4024+
{
4025+
fpAvailMask = RBM_ALLFLOAT & ~regArgMaskLive;
4026+
if (GlobalJitOptions::compFeatureHfa)
4027+
{
4028+
fpAvailMask &= RBM_ALLDOUBLE;
4029+
}
4030+
}
40344031

4035-
assert(fpAvailMask != RBM_NONE);
4032+
assert(fpAvailMask != RBM_NONE);
40364033

4037-
// We pick the lowest avail register number
4038-
regMaskTP tempMask = genFindLowestBit(fpAvailMask);
4039-
xtraReg = genRegNumFromMask(tempMask);
4040-
#elif defined(TARGET_X86)
4034+
// We pick the lowest avail register number
4035+
regMaskTP tempMask = genFindLowestBit(fpAvailMask);
4036+
xtraReg = genRegNumFromMask(tempMask);
4037+
}
4038+
#if defined(TARGET_X86)
40414039
// This case shouldn't occur on x86 since NYI gets converted to an assert
40424040
NYI("Homing circular FP registers via xtraReg");
40434041
#endif
@@ -9562,20 +9560,26 @@ bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass)
95629560

95639561
bool Compiler::IsHfa(GenTree* tree)
95649562
{
9565-
#ifdef FEATURE_HFA
9566-
return IsHfa(gtGetStructHandleIfPresent(tree));
9567-
#else
9568-
return false;
9569-
#endif
9563+
if (GlobalJitOptions::compFeatureHfa)
9564+
{
9565+
return IsHfa(gtGetStructHandleIfPresent(tree));
9566+
}
9567+
else
9568+
{
9569+
return false;
9570+
}
95709571
}
95719572

95729573
var_types Compiler::GetHfaType(GenTree* tree)
95739574
{
9574-
#ifdef FEATURE_HFA
9575-
return GetHfaType(gtGetStructHandleIfPresent(tree));
9576-
#else
9577-
return TYP_UNDEF;
9578-
#endif
9575+
if (GlobalJitOptions::compFeatureHfa)
9576+
{
9577+
return GetHfaType(gtGetStructHandleIfPresent(tree));
9578+
}
9579+
else
9580+
{
9581+
return TYP_UNDEF;
9582+
}
95799583
}
95809584

95819585
unsigned Compiler::GetHfaCount(GenTree* tree)
@@ -9585,18 +9589,19 @@ unsigned Compiler::GetHfaCount(GenTree* tree)
95859589

95869590
var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass)
95879591
{
9588-
#ifdef FEATURE_HFA
9589-
if (hClass != NO_CLASS_HANDLE)
9592+
if (GlobalJitOptions::compFeatureHfa)
95909593
{
9591-
CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass);
9592-
if (elemKind != CORINFO_HFA_ELEM_NONE)
9594+
if (hClass != NO_CLASS_HANDLE)
95939595
{
9594-
// This type may not appear elsewhere, but it will occupy a floating point register.
9595-
compFloatingPointUsed = true;
9596+
CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass);
9597+
if (elemKind != CORINFO_HFA_ELEM_NONE)
9598+
{
9599+
// This type may not appear elsewhere, but it will occupy a floating point register.
9600+
compFloatingPointUsed = true;
9601+
}
9602+
return HfaTypeFromElemKind(elemKind);
95969603
}
9597-
return HfaTypeFromElemKind(elemKind);
95989604
}
9599-
#endif // FEATURE_HFA
96009605
return TYP_UNDEF;
96019606
}
96029607

src/coreclr/jit/compiler.cpp

Lines changed: 53 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ bool Compiler::s_pJitFunctionFileInitialized = false;
5454
MethodSet* Compiler::s_pJitMethodSet = nullptr;
5555
#endif // DEBUG
5656

57+
#ifdef CONFIGURABLE_ARM_ABI
58+
// static
59+
bool GlobalJitOptions::compFeatureHfa = false;
60+
LONG GlobalJitOptions::compUseSoftFPConfigured = 0;
61+
#endif // CONFIGURABLE_ARM_ABI
62+
5763
/*****************************************************************************
5864
*
5965
* Little helpers to grab the current cycle counter value; this is done
@@ -468,49 +474,6 @@ var_types Compiler::getJitGCType(BYTE gcType)
468474
return result;
469475
}
470476

471-
#ifdef ARM_SOFTFP
472-
//---------------------------------------------------------------------------
473-
// IsSingleFloat32Struct:
474-
// Check if the given struct type contains only one float32 value type
475-
//
476-
// Arguments:
477-
// clsHnd - the handle for the struct type
478-
//
479-
// Return Value:
480-
// true if the given struct type contains only one float32 value type,
481-
// false otherwise.
482-
//
483-
484-
bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd)
485-
{
486-
for (;;)
487-
{
488-
// all of class chain must be of value type and must have only one field
489-
if (!info.compCompHnd->isValueClass(clsHnd) || info.compCompHnd->getClassNumInstanceFields(clsHnd) != 1)
490-
{
491-
return false;
492-
}
493-
494-
CORINFO_CLASS_HANDLE* pClsHnd = &clsHnd;
495-
CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
496-
CorInfoType fieldType = info.compCompHnd->getFieldType(fldHnd, pClsHnd);
497-
498-
switch (fieldType)
499-
{
500-
case CORINFO_TYPE_VALUECLASS:
501-
clsHnd = *pClsHnd;
502-
break;
503-
504-
case CORINFO_TYPE_FLOAT:
505-
return true;
506-
507-
default:
508-
return false;
509-
}
510-
}
511-
}
512-
#endif // ARM_SOFTFP
513-
514477
#ifdef TARGET_X86
515478
//---------------------------------------------------------------------------
516479
// isTrivialPointerSizedStruct:
@@ -623,53 +586,44 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS
623586

624587
var_types useType = TYP_UNKNOWN;
625588

626-
// Start by determining if we have an HFA/HVA with a single element.
627-
#ifdef FEATURE_HFA
589+
// Start by determining if we have an HFA/HVA with a single element.
590+
if (GlobalJitOptions::compFeatureHfa)
591+
{
628592
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
629-
// Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated
630-
// as if they are not HFA types.
631-
if (!isVarArg)
593+
// Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated
594+
// as if they are not HFA types.
595+
if (!isVarArg)
632596
#endif // defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
633-
{
634-
switch (structSize)
635597
{
636-
case 4:
637-
case 8:
598+
switch (structSize)
599+
{
600+
case 4:
601+
case 8:
638602
#ifdef TARGET_ARM64
639-
case 16:
603+
case 16:
640604
#endif // TARGET_ARM64
641-
{
642-
var_types hfaType;
643-
#ifdef ARM_SOFTFP
644-
// For ARM_SOFTFP, HFA is unsupported so we need to check in another way.
645-
// This matters only for size-4 struct because bigger structs would be processed with RetBuf.
646-
if (isSingleFloat32Struct(clsHnd))
647-
{
648-
hfaType = TYP_FLOAT;
649-
}
650-
#else // !ARM_SOFTFP
651-
hfaType = GetHfaType(clsHnd);
652-
#endif // ARM_SOFTFP
653-
// We're only interested in the case where the struct size is equal to the size of the hfaType.
654-
if (varTypeIsValidHfaType(hfaType))
655605
{
656-
if (genTypeSize(hfaType) == structSize)
606+
var_types hfaType = GetHfaType(clsHnd);
607+
// We're only interested in the case where the struct size is equal to the size of the hfaType.
608+
if (varTypeIsValidHfaType(hfaType))
657609
{
658-
useType = hfaType;
659-
}
660-
else
661-
{
662-
return TYP_UNKNOWN;
610+
if (genTypeSize(hfaType) == structSize)
611+
{
612+
useType = hfaType;
613+
}
614+
else
615+
{
616+
return TYP_UNKNOWN;
617+
}
663618
}
664619
}
665620
}
666-
}
667-
if (useType != TYP_UNKNOWN)
668-
{
669-
return useType;
621+
if (useType != TYP_UNKNOWN)
622+
{
623+
return useType;
624+
}
670625
}
671626
}
672-
#endif // FEATURE_HFA
673627

674628
// Now deal with non-HFA/HVA structs.
675629
switch (structSize)
@@ -3273,6 +3227,27 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
32733227
}
32743228
#endif // FEATURE_FASTTAILCALL
32753229

3230+
#ifdef CONFIGURABLE_ARM_ABI
3231+
opts.compUseSoftFP = jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI);
3232+
unsigned int softFPConfig = opts.compUseSoftFP ? 2 : 1;
3233+
unsigned int oldSoftFPConfig =
3234+
InterlockedCompareExchange(&GlobalJitOptions::compUseSoftFPConfigured, softFPConfig, 0);
3235+
if (oldSoftFPConfig != softFPConfig && oldSoftFPConfig != 0)
3236+
{
3237+
// There are no current scenarios where the abi can change during the lifetime of a process
3238+
// that uses the JIT. If such a change occurs, either compFeatureHfa will need to change to a TLS static
3239+
// or we will need to have some means to reset the flag safely.
3240+
NO_WAY("SoftFP ABI setting changed during lifetime of process");
3241+
}
3242+
3243+
GlobalJitOptions::compFeatureHfa = !opts.compUseSoftFP;
3244+
#elif defined(ARM_SOFTFP)
3245+
// Armel is unconditionally enabled in the JIT. Verify that the VM side agrees.
3246+
assert(jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI));
3247+
#elif TARGET_ARM
3248+
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI));
3249+
#endif // CONFIGURABLE_ARM_ABI
3250+
32763251
opts.compScopeInfo = opts.compDbgInfo;
32773252

32783253
#ifdef LATE_DISASM

0 commit comments

Comments
 (0)