Skip to content

Commit 52024d2

Browse files
Create a WASM-targeting RyuJit
Notable build system changes: 1) Not included in clr.alljits yet. Build with clr.wasmjit. Notable factoring choices: 1) Introduce some new target defines for features which WASM won't need, like fixed size register mask support and GCInfo based on code metadata. 2) For this initial commit, the amount of changes has been intentionally minimized. In the future, more things will be moved around and ifdefed out.
1 parent a42a703 commit 52024d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1670
-383
lines changed

eng/Subsets.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
<SubsetName Include="Clr.PalTestList" OnDemand="true" Description="Generate the list of the CoreCLR PAL tests. When using the command line, use Clr.PalTests instead." />
220220
<SubsetName Include="Clr.Hosts" Description="The CoreCLR corerun test host." />
221221
<SubsetName Include="Clr.Jit" Description="The JIT for the CoreCLR .NET runtime." />
222+
<SubsetName Include="Clr.WasmJit" Description="The cross-targeting WebAssembly JIT compiler for the CoreCLR .NET runtime." />
222223
<SubsetName Include="Clr.AllJits" Description="All of the cross-targeting JIT compilers for the CoreCLR .NET runtime." />
223224
<SubsetName Include="Clr.AllJitsCommunity" Description="All of the cross-targeting JIT compilers for the CoreCLR .NET runtime, including community targets." />
224225
<SubsetName Include="Clr.Spmi" Description="SuperPMI, a tool for CoreCLR JIT testing." />
@@ -322,6 +323,10 @@
322323
<ClrRuntimeBuildSubsets>$(ClrRuntimeBuildSubsets);ClrJitSubset=true</ClrRuntimeBuildSubsets>
323324
</PropertyGroup>
324325

326+
<PropertyGroup Condition="$(_subset.Contains('+clr.wasmjit+'))">
327+
<ClrRuntimeBuildSubsets>$(ClrRuntimeBuildSubsets);ClrWasmJitSubset=true</ClrRuntimeBuildSubsets>
328+
</PropertyGroup>
329+
325330
<PropertyGroup Condition="$(_subset.Contains('+clr.paltests+'))">
326331
<ClrRuntimeBuildSubsets>$(ClrRuntimeBuildSubsets);ClrPalTestsSubset=true</ClrRuntimeBuildSubsets>
327332
</PropertyGroup>

src/coreclr/build-runtime.cmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do (
329329
if not "!string:-jit-=!"=="!string!" (
330330
set __CMakeTarget=!__CMakeTarget! jit
331331
)
332+
if not "!string:-wasmjit-=!"=="!string!" (
333+
set __CMakeTarget=!__CMakeTarget! wasmjit
334+
)
332335
if not "!string:-alljits-=!"=="!string!" (
333336
set __CMakeTarget=!__CMakeTarget! alljits
334337
)

src/coreclr/clrdefinitions.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ function(set_target_definitions_to_custom_os_and_arch)
283283
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_64BIT)
284284
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_RISCV64)
285285
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE FEATURE_MULTIREG_RETURN)
286+
elseif(TARGETDETAILS_ARCH STREQUAL "wasm")
287+
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WASM32)
288+
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WASM)
286289
endif()
287290

288291
if (TARGETDETAILS_ARCH STREQUAL "armel")

src/coreclr/components.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Define all the individually buildable components of the CoreCLR build and their respective targets
22
add_component(jit)
3+
add_component(wasmjit)
34
add_component(alljits)
45
add_component(hosts)
56
add_component(runtime)

src/coreclr/inc/cordebuginfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class ICorDebugInfo
213213
REGNUM_T5,
214214
REGNUM_T6,
215215
REGNUM_PC,
216-
#elif TARGET_WASM
216+
#elif defined(TARGET_WASM)
217217
REGNUM_PC, // wasm doesn't have registers
218218
#else
219219
PORTABILITY_WARNING("Register numbers not defined on this platform")

src/coreclr/jit/CMakeLists.txt

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function(create_standalone_jit)
2222

2323
if(TARGETDETAILS_OS STREQUAL "unix_osx" OR TARGETDETAILS_OS STREQUAL "unix_anyos")
2424
set(JIT_ARCH_LINK_LIBRARIES gcinfo_unix_${TARGETDETAILS_ARCH})
25-
else()
25+
elseif(NOT ${TARGETDETAILS_ARCH} MATCHES "wasm")
2626
set(JIT_ARCH_LINK_LIBRARIES gcinfo_${TARGETDETAILS_OS}_${TARGETDETAILS_ARCH})
2727
endif()
2828

@@ -53,6 +53,9 @@ function(create_standalone_jit)
5353
elseif(TARGETDETAILS_ARCH STREQUAL "riscv64")
5454
set(JIT_ARCH_SOURCES ${JIT_RISCV64_SOURCES})
5555
set(JIT_ARCH_HEADERS ${JIT_RISCV64_HEADERS})
56+
elseif(TARGETDETAILS_ARCH STREQUAL "wasm")
57+
set(JIT_ARCH_SOURCES ${JIT_WASM_SOURCES})
58+
set(JIT_ARCH_HEADERS ${JIT_WASM_HEADERS})
5659
else()
5760
clr_unknown_arch()
5861
endif()
@@ -94,7 +97,6 @@ set( JIT_SOURCES
9497
block.cpp
9598
buildstring.cpp
9699
codegencommon.cpp
97-
codegenlinear.cpp
98100
compiler.cpp
99101
copyprop.cpp
100102
debuginfo.cpp
@@ -115,8 +117,6 @@ set( JIT_SOURCES
115117
fgstmt.cpp
116118
flowgraph.cpp
117119
forwardsub.cpp
118-
gcdecode.cpp
119-
gcencode.cpp
120120
gcinfo.cpp
121121
gentree.cpp
122122
gschecks.cpp
@@ -145,8 +145,6 @@ set( JIT_SOURCES
145145
liveness.cpp
146146
loopcloning.cpp
147147
lower.cpp
148-
lsra.cpp
149-
lsrabuild.cpp
150148
morph.cpp
151149
morphblock.cpp
152150
objectalloc.cpp
@@ -163,8 +161,6 @@ set( JIT_SOURCES
163161
rangecheckcloning.cpp
164162
rationalize.cpp
165163
redundantbranchopts.cpp
166-
regalloc.cpp
167-
regMaskTPOps.cpp
168164
regset.cpp
169165
scev.cpp
170166
scopeinfo.cpp
@@ -178,11 +174,21 @@ set( JIT_SOURCES
178174
stacklevelsetter.cpp
179175
switchrecognition.cpp
180176
treelifeupdater.cpp
181-
unwind.cpp
182177
utils.cpp
183178
valuenum.cpp
184179
)
185180

181+
set ( JIT_PHYSICAL_TARGET_SOURCES
182+
lsra.cpp
183+
lsrabuild.cpp
184+
regalloc.cpp
185+
regMaskTPOps.cpp
186+
codegenlinear.cpp
187+
gcdecode.cpp
188+
gcencode.cpp
189+
unwind.cpp
190+
)
191+
186192
if (CLR_CMAKE_TARGET_WIN32)
187193
# Append clrjit.natvis file
188194
list (APPEND JIT_SOURCES
@@ -192,6 +198,7 @@ endif(CLR_CMAKE_TARGET_WIN32)
192198
# Define all the architecture-specific source files
193199

194200
set( JIT_AMD64_SOURCES
201+
${JIT_PHYSICAL_TARGET_SOURCES}
195202
codegenxarch.cpp
196203
emitxarch.cpp
197204
lowerxarch.cpp
@@ -205,6 +212,7 @@ set( JIT_AMD64_SOURCES
205212
)
206213

207214
set( JIT_ARM_SOURCES
215+
${JIT_PHYSICAL_TARGET_SOURCES}
208216
codegenarmarch.cpp
209217
codegenarm.cpp
210218
decomposelongs.cpp
@@ -217,6 +225,7 @@ set( JIT_ARM_SOURCES
217225
)
218226

219227
set( JIT_I386_SOURCES
228+
${JIT_PHYSICAL_TARGET_SOURCES}
220229
codegenxarch.cpp
221230
decomposelongs.cpp
222231
emitxarch.cpp
@@ -231,6 +240,7 @@ set( JIT_I386_SOURCES
231240
)
232241

233242
set( JIT_ARM64_SOURCES
243+
${JIT_PHYSICAL_TARGET_SOURCES}
234244
codegenarmarch.cpp
235245
codegenarm64.cpp
236246
codegenarm64test.cpp
@@ -260,6 +270,7 @@ set( JIT_POWERPC64_SOURCES
260270
)
261271

262272
set( JIT_LOONGARCH64_SOURCES
273+
${JIT_PHYSICAL_TARGET_SOURCES}
263274
codegenloongarch64.cpp
264275
emitloongarch64.cpp
265276
lowerloongarch64.cpp
@@ -269,6 +280,7 @@ set( JIT_LOONGARCH64_SOURCES
269280
)
270281

271282
set( JIT_RISCV64_SOURCES
283+
${JIT_PHYSICAL_TARGET_SOURCES}
272284
codegenriscv64.cpp
273285
emitriscv64.cpp
274286
lowerriscv64.cpp
@@ -277,6 +289,14 @@ set( JIT_RISCV64_SOURCES
277289
unwindriscv64.cpp
278290
)
279291

292+
set( JIT_WASM_SOURCES
293+
codegenwasm.cpp
294+
emitwasm.cpp
295+
lowerwasm.cpp
296+
regallocwasm.cpp
297+
targetwasm.cpp
298+
)
299+
280300
# We include the headers here for better experience in IDEs.
281301
set( JIT_HEADERS
282302
../inc/corinfo.h
@@ -448,6 +468,15 @@ set( JIT_RISCV64_HEADERS
448468
registerriscv64.h
449469
)
450470

471+
set( JIT_WASM_HEADERS
472+
regallocwasm.h
473+
targetwasm.h
474+
emitwasm.h
475+
emitfmtswasm.h
476+
instrswasm.h
477+
registerwasm.h
478+
)
479+
451480
convert_to_absolute_path(JIT_SOURCES ${JIT_SOURCES})
452481
convert_to_absolute_path(JIT_HEADERS ${JIT_HEADERS})
453482
convert_to_absolute_path(JIT_RESOURCES ${JIT_RESOURCES})
@@ -470,6 +499,8 @@ convert_to_absolute_path(JIT_LOONGARCH64_SOURCES ${JIT_LOONGARCH64_SOURCES})
470499
convert_to_absolute_path(JIT_LOONGARCH64_HEADERS ${JIT_LOONGARCH64_HEADERS})
471500
convert_to_absolute_path(JIT_RISCV64_SOURCES ${JIT_RISCV64_SOURCES})
472501
convert_to_absolute_path(JIT_RISCV64_HEADERS ${JIT_RISCV64_HEADERS})
502+
convert_to_absolute_path(JIT_WASM_SOURCES ${JIT_WASM_SOURCES})
503+
convert_to_absolute_path(JIT_WASM_HEADERS ${JIT_WASM_HEADERS})
473504

474505
if(CLR_CMAKE_TARGET_ARCH_AMD64)
475506
set(JIT_ARCH_SOURCES ${JIT_AMD64_SOURCES})
@@ -499,13 +530,12 @@ elseif(CLR_CMAKE_TARGET_ARCH_RISCV64)
499530
set(JIT_ARCH_SOURCES ${JIT_RISCV64_SOURCES})
500531
set(JIT_ARCH_HEADERS ${JIT_RISCV64_HEADERS})
501532
elseif(CLR_CMAKE_TARGET_ARCH_WASM)
502-
set(JIT_ARCH_SOURCES ${JIT_WASM32_SOURCES})
503-
set(JIT_ARCH_HEADERS ${JIT_WASM32_HEADERS})
533+
set(JIT_ARCH_SOURCES ${JIT_WASM_SOURCES})
534+
set(JIT_ARCH_HEADERS ${JIT_WASM_HEADERS})
504535
else()
505536
clr_unknown_arch()
506537
endif()
507538

508-
509539
set(JIT_DLL_MAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/dllmain.cpp)
510540

511541
if(CLR_CMAKE_HOST_WIN32)
@@ -623,7 +653,12 @@ function(add_jit jitName)
623653
target_compile_definitions(${jitName} PRIVATE JIT_STANDALONE_BUILD)
624654

625655
# add the install targets
626-
install_clr(TARGETS ${jitName} DESTINATIONS . COMPONENT alljits)
656+
if (${jitName} MATCHES "clrjit_universal_wasm")
657+
# TODO-WASM: add the WASM Jit to alljits once that becomes necessary.
658+
install_clr(TARGETS ${jitName} DESTINATIONS . COMPONENT wasmjit)
659+
else()
660+
install_clr(TARGETS ${jitName} DESTINATIONS . COMPONENT alljits)
661+
endif()
627662
endfunction()
628663

629664
set(JIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
@@ -653,6 +688,7 @@ add_pgo(clrjit)
653688

654689
if (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64)
655690
create_standalone_jit(TARGET clrjit_universal_arm64_${ARCH_HOST_NAME} OS universal ARCH arm64)
691+
create_standalone_jit(TARGET clrjit_universal_wasm_${ARCH_HOST_NAME} OS universal ARCH wasm)
656692
create_standalone_jit(TARGET clrjit_unix_x64_${ARCH_HOST_NAME} OS unix_anyos ARCH x64)
657693
create_standalone_jit(TARGET clrjit_win_x64_${ARCH_HOST_NAME} OS win ARCH x64)
658694
if (CLR_CMAKE_BUILD_COMMUNITY_ALTJITS EQUAL 1)
@@ -678,7 +714,7 @@ if (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)
678714
endif (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)
679715

680716
if (CLR_CMAKE_TARGET_UNIX)
681-
if (NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6 AND NOT ARCH_TARGET_NAME STREQUAL ppc64le AND NOT ARCH_TARGET_NAME STREQUAL riscv64)
717+
if (NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6 AND NOT ARCH_TARGET_NAME STREQUAL ppc64le AND NOT ARCH_TARGET_NAME STREQUAL riscv64 AND NOT ARCH_TARGET_NAME STREQUAL wasm)
682718
if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)
683719
install_clr(TARGETS clrjit_universal_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME} DESTINATIONS . COMPONENT jit)
684720
else()

src/coreclr/jit/abi.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ regNumber ABIPassingSegment::GetRegister() const
4141
return static_cast<regNumber>(m_register);
4242
}
4343

44+
#if HAS_FIXED_REGISTER_SET
4445
//-----------------------------------------------------------------------------
4546
// GetRegisterMask:
4647
// Get the mask of registers that this segment is passed in.
@@ -62,6 +63,7 @@ regMaskTP ABIPassingSegment::GetRegisterMask() const
6263

6364
return mask;
6465
}
66+
#endif // HAS_FIXED_REGISTER_SET
6567

6668
//-----------------------------------------------------------------------------
6769
// GetStackOffset:
@@ -739,3 +741,103 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp,
739741
return m_classifier.Classify(comp, type, structLayout, wellKnownParam);
740742
}
741743
#endif
744+
745+
//-----------------------------------------------------------------------------------
746+
// IsMultiRegReturnedType: Returns true if the type is returned in multiple registers
747+
//
748+
// Arguments:
749+
// hClass - type handle
750+
//
751+
// Return Value:
752+
// true if type is returned in multiple registers, false otherwise.
753+
//
754+
bool Compiler::IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass, CorInfoCallConvExtension callConv)
755+
{
756+
if (hClass == NO_CLASS_HANDLE)
757+
{
758+
return false;
759+
}
760+
761+
structPassingKind howToReturnStruct;
762+
var_types returnType = getReturnTypeForStruct(hClass, callConv, &howToReturnStruct);
763+
764+
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
765+
return (varTypeIsStruct(returnType) && (howToReturnStruct != SPK_PrimitiveType));
766+
#else
767+
return (varTypeIsStruct(returnType));
768+
#endif
769+
}
770+
771+
//------------------------------------------------------------------------
772+
// IsHfa: Is this an HFA type?
773+
//
774+
// HFAs are an ARM/ARM64 ABI concept, where structs like { float, float }
775+
// (up to 4 same-type (including vector) FP fiels) can be passed in multiple
776+
// registers.
777+
//
778+
// Arguments:
779+
// hClass - The type in question
780+
//
781+
// Return Value:
782+
// Whether "hClass" represents an HFA.
783+
//
784+
bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass)
785+
{
786+
return varTypeIsValidHfaType(GetHfaType(hClass));
787+
}
788+
789+
//------------------------------------------------------------------------
790+
// GetHfaType: Get the field type for an HFA struct.
791+
//
792+
// Arguments:
793+
// hClass - The type in question
794+
//
795+
// Return Value:
796+
// If "hClass" represents an HFA, return the field type, otherwise TYP_UNDEF.
797+
//
798+
var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass)
799+
{
800+
if (GlobalJitOptions::compFeatureHfa)
801+
{
802+
if (hClass != NO_CLASS_HANDLE)
803+
{
804+
CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass);
805+
if (elemKind != CORINFO_HFA_ELEM_NONE)
806+
{
807+
// This type may not appear elsewhere, but it will occupy a floating point register.
808+
compFloatingPointUsed = true;
809+
}
810+
return HfaTypeFromElemKind(elemKind);
811+
}
812+
}
813+
return TYP_UNDEF;
814+
}
815+
816+
//------------------------------------------------------------------------
817+
// GetHfaCount: Given a class handle for an HFA struct
818+
// return the number of registers needed to hold the HFA
819+
//
820+
// Note that on ARM32 the single precision registers overlap with
821+
// the double precision registers and for that reason each
822+
// double register is considered to be two single registers.
823+
// Thus for ARM32 an HFA of 4 doubles this function will return 8.
824+
// On ARM64 given an HFA of 4 singles or 4 doubles this function will
825+
// will return 4 for both.
826+
// Arguments:
827+
// hClass: the class handle of a HFA struct
828+
//
829+
unsigned Compiler::GetHfaCount(CORINFO_CLASS_HANDLE hClass)
830+
{
831+
assert(IsHfa(hClass));
832+
#ifdef TARGET_ARM
833+
// A HFA of doubles is twice as large as an HFA of singles for ARM32
834+
// (i.e. uses twice the number of single precision registers)
835+
return info.compCompHnd->getClassSize(hClass) / REGSIZE_BYTES;
836+
#else // TARGET_ARM64
837+
var_types hfaType = GetHfaType(hClass);
838+
unsigned classSize = info.compCompHnd->getClassSize(hClass);
839+
// Note that the retail build issues a warning about a potential division by zero without the Max function
840+
unsigned elemSize = Max((unsigned)1, EA_SIZE_IN_BYTES(emitActualTypeSize(hfaType)));
841+
return classSize / elemSize;
842+
#endif // TARGET_ARM64
843+
}

0 commit comments

Comments
 (0)