docs/design/coreclr/jit/porting-ryujit.md
First, understand the JIT architecture by reading RyuJIT overview.
One advantage of the CLR is that the VM (mostly) hides the (non-ABI) OS differences.
The following components need to be updated, or target-specific versions created, for a new platform.
There are several steps to follow to port the JIT (some of which can be be done in parallel), described below.
DOTNET_JITMinOpts=1.FEATURE_EH -- if 0, all exception handling blocks are removed. Of course, tests with exception handling
that depend on exceptions being thrown and caught won't run correctly.FEATURE_STRUCTPROMOTEFEATURE_FASTTAILCALLFEATURE_TAILCALL_OPTFEATURE_SIMDDOTNET_AltJit variable. For example, setting DOTNET_AltJit=Add and running
a test will use the "base" JIT (say, the Windows x64 targeting JIT) to compile all functions except
Add, which will be first compiled by the new altjit, and if it fails, fall back to the "base" JIT. In this
way, only very limited JIT functionality need to work, as the "base" JIT takes care of most functions.CodeGen::genArm64EmitterUnitTests().XXX.cs, there is a single interesting function named XXX to compile
(that is, the name of the source file is the same as the name of the interesting function. This was done to make
the scripts to invoke these tests very simple.). Set DOTNET_AltJit=XXX so the new JIT only attempts to
compile that one function.BuildAsStandalone set to true.DOTNET_JitDisasm to see the generated code for functions, even if the code isn't run.JIT directory of testsDOTNET_JITMinOpts=1.DOTNET_TieredCompilation=0 (or disable it for the platform entirely) until much later.JitStress and JitStressRegs stress modes.GCStress on-line. This also requires VM work.DOTNET_GCStress=4 quality. When crossgen/ngen is brought on-line, test with DOTNET_GCStress=8
and DOTNET_GCStress=C as well.Vector<T>) and hardware intrinsics support.fgMorphArgs(), fgFixupStructReturn(), fgMorphCall(), fgPromoteStructs() and the various struct assignment morphing methodsSin only for x86, Round everywhere BUT amd64)_TARGET_64_BIT_ (32 bit target is just ! _TARGET_64BIT_)
_TARGET_XARCH_, _TARGET_ARMARCH_
_TARGET_AMD64_, _TARGET_X86_, _TARGET_ARM64_, _TARGET_ARM_
insGroup and instrDesc data structures are used for encoding
instrDesc is initialized with the opcode bits, and has fields for immediates and register numbers.instrDescs are collected into insGroup groupsinstrDescs), during CodeGeninstrDescs after CodeGen is completeinstrDesc represents the instruction to be emittedemitter::emitInsMov(instruction ins, emitAttr attr, GenTree* node)
emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val)
emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2) (currently Arm64 only)
LinearScan::startBlockSequence() and LinearScan::moveToNextBlock()lvaSortByRefCount(), and determined by lvIsRegCandidate()genCreateAddrMode(), in CodeGenCommon.cpp traverses the tree looking for an addressing mode, then captures its constituent elements (base, index, scale & offset) in "out parameters"
gtSetEvalOrder, and by LoweringgenCodeForBBList()
genCodeForTreeNode(), which needs to handle all nodes that are not "contained"