Skip to content

Commit 289aa17

Browse files
am11sunlijun-610tomeksowisirntarjkotas
authored
Add linux-riscv64 nativeaot runtime build (dotnet#110688)
* Fix registers/offsets in riscv-nativeaot. * Fix *.S files in riscv-nativeaot. * Fix riscv64 nativeaot native build * Managed build fixes * Apply suggestions from code review Co-authored-by: Tymoteusz Wenerski <[email protected]> * Apply suggestions from code review Co-authored-by: Tomasz Sowiński <[email protected]> * Update other macros in AsmOffsetsVerify * Update src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs Co-authored-by: Adeel Mujahid <[email protected]> --------- Co-authored-by: sunlijun <[email protected]> Co-authored-by: Tomek Sowiński <[email protected]> Co-authored-by: Tymoteusz Wenerski <[email protected]> Co-authored-by: Jan Kotas <[email protected]>
1 parent eb0490e commit 289aa17

Some content is hidden

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

47 files changed

+3882
-39
lines changed

src/coreclr/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ add_subdirectory(tools/aot/jitinterface)
151151

152152
if(NOT CLR_CROSS_COMPONENTS_BUILD)
153153
# NativeAOT only buildable for a subset of CoreCLR-supported configurations
154-
if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64 OR CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_LOONGARCH64 OR (CLR_CMAKE_HOST_ARCH_I386 AND CLR_CMAKE_HOST_WIN32))
154+
if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64 OR CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_LOONGARCH64 OR CLR_CMAKE_HOST_ARCH_RISCV64 OR (CLR_CMAKE_HOST_ARCH_I386 AND CLR_CMAKE_HOST_WIN32))
155155
add_subdirectory(nativeaot)
156156
endif()
157157
endif(NOT CLR_CROSS_COMPONENTS_BUILD)

src/coreclr/nativeaot/Common/src/Internal/Runtime/TransitionBlock.cs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE
3636
#define ENREGISTERED_PARAMTYPE_MAXSIZE
3737
#elif TARGET_WASM
38-
#elif TARGET_LOONGARCH64
38+
#elif TARGET_LOONGARCH64 || TARGET_RISCV64
3939
#define CALLDESCR_ARGREGS // CallDescrWorker has ArgumentRegister parameter
4040
#define CALLDESCR_FPARGREGS // CallDescrWorker has FloatArgumentRegisters parameter
4141
#define ENREGISTERED_RETURNTYPE_MAXSIZE
@@ -360,6 +360,60 @@ internal struct ArchitectureConstants
360360
public const int STACK_ELEM_SIZE = 8;
361361
public static int StackElemSize(int size) { return (((size) + STACK_ELEM_SIZE - 1) & ~(STACK_ELEM_SIZE - 1)); }
362362
}
363+
#elif TARGET_RISCV64
364+
[StructLayout(LayoutKind.Sequential)]
365+
internal struct ReturnBlock
366+
{
367+
private IntPtr returnValue;
368+
private IntPtr returnValue2;
369+
private IntPtr returnValue3;
370+
private IntPtr returnValue4;
371+
}
372+
373+
[StructLayout(LayoutKind.Sequential)]
374+
internal struct ArgumentRegisters
375+
{
376+
private IntPtr a0;
377+
private IntPtr a1;
378+
private IntPtr a2;
379+
private IntPtr a3;
380+
private IntPtr a4;
381+
private IntPtr a5;
382+
private IntPtr a6;
383+
private IntPtr a7;
384+
public static unsafe int GetOffsetOfa7()
385+
{
386+
return sizeof(IntPtr) * 7;
387+
}
388+
}
389+
390+
[StructLayout(LayoutKind.Sequential)]
391+
internal struct FloatArgumentRegisters
392+
{
393+
private double fa0;
394+
private double fa1;
395+
private double fa2;
396+
private double fa3;
397+
private double fa4;
398+
private double fa5;
399+
private double fa6;
400+
private double fa7;
401+
}
402+
403+
internal struct ArchitectureConstants
404+
{
405+
// To avoid corner case bugs, limit maximum size of the arguments with sufficient margin
406+
public const int MAX_ARG_SIZE = 0xFFFFFF;
407+
408+
public const int NUM_ARGUMENT_REGISTERS = 8;
409+
public const int ARGUMENTREGISTERS_SIZE = NUM_ARGUMENT_REGISTERS * 8;
410+
public const int ENREGISTERED_RETURNTYPE_MAXSIZE = 32; // bytes (four FP registers: fa0, fa1, fa2, and fa3)
411+
public const int ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE = 16; // bytes (two int registers: a0 and a1)
412+
public const int ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE_PRIMITIVE = 8;
413+
public const int ENREGISTERED_PARAMTYPE_MAXSIZE = 16; // bytes (max value type size that can be passed by value)
414+
public const int STACK_ELEM_SIZE = 8;
415+
public static int StackElemSize(int size) { return (((size) + STACK_ELEM_SIZE - 1) & ~(STACK_ELEM_SIZE - 1)); }
416+
}
363417
#endif
364418

365419
//
@@ -465,6 +519,20 @@ public static unsafe int GetOffsetOfArgumentRegisters()
465519
return sizeof(ReturnBlock);
466520
}
467521

522+
public IntPtr m_alignmentPad;
523+
#elif TARGET_RISCV64
524+
public ReturnBlock m_returnBlock;
525+
public static unsafe int GetOffsetOfReturnValuesBlock()
526+
{
527+
return 0;
528+
}
529+
530+
public ArgumentRegisters m_argumentRegisters;
531+
public static unsafe int GetOffsetOfArgumentRegisters()
532+
{
533+
return sizeof(ReturnBlock);
534+
}
535+
468536
public IntPtr m_alignmentPad;
469537
#else
470538
#error Portability problem

src/coreclr/nativeaot/Directory.Build.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@
8989
<PropertyGroup Condition="'$(Platform)' == 'loongarch64'">
9090
<DefineConstants>TARGET_64BIT;TARGET_LOONGARCH64;$(DefineConstants)</DefineConstants>
9191
</PropertyGroup>
92+
<PropertyGroup Condition="'$(Platform)' == 'riscv64'">
93+
<DefineConstants>TARGET_64BIT;TARGET_RISCV64;$(DefineConstants)</DefineConstants>
94+
</PropertyGroup>
9295

9396
<PropertyGroup>
9497
<DefineConstants Condition="'$(TargetsWindows)'=='true'">TARGET_WINDOWS;$(DefineConstants)</DefineConstants>

src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,18 @@ class AsmOffsets
2828
static_assert(offsetof(Array, m_Length) == offsetof(String, m_Length), "The length field of String and Array have different offsets");
2929
static_assert(sizeof(((Array*)0)->m_Length) == sizeof(((String*)0)->m_Length), "The length field of String and Array have different sizes");
3030

31+
#define TO_STRING(x) #x
32+
#define OFFSET_STRING(cls, member) TO_STRING(offsetof(cls, member))
33+
34+
// Macro definition
3135
#define PLAT_ASM_OFFSET(offset, cls, member) \
32-
static_assert((offsetof(cls, member) == 0x##offset) || (offsetof(cls, member) > 0x##offset), "Bad asm offset for '" #cls "." #member "', the actual offset is smaller than 0x" #offset "."); \
33-
static_assert((offsetof(cls, member) == 0x##offset) || (offsetof(cls, member) < 0x##offset), "Bad asm offset for '" #cls "." #member "', the actual offset is larger than 0x" #offset ".");
36+
static_assert(offsetof(cls, member) == 0x##offset, "Bad asm offset for '" #cls "." #member "'. Actual offset: " OFFSET_STRING(cls, member));
3437

35-
#define PLAT_ASM_SIZEOF(size, cls ) \
36-
static_assert((sizeof(cls) == 0x##size) || (sizeof(cls) > 0x##size), "Bad asm size for '" #cls "', the actual size is smaller than 0x" #size "."); \
37-
static_assert((sizeof(cls) == 0x##size) || (sizeof(cls) < 0x##size), "Bad asm size for '" #cls "', the actual size is larger than 0x" #size ".");
38+
#define PLAT_ASM_SIZEOF(size, cls) \
39+
static_assert(sizeof(cls) == 0x##size, "Bad asm size for '" #cls "'. Actual size: " OFFSET_STRING(cls, 0x##size));
3840

3941
#define PLAT_ASM_CONST(constant, expr) \
40-
static_assert(((expr) == 0x##constant) || ((expr) > 0x##constant), "Bad asm constant for '" #expr "', the actual value is smaller than 0x" #constant "."); \
41-
static_assert(((expr) == 0x##constant) || ((expr) < 0x##constant), "Bad asm constant for '" #expr "', the actual value is larger than 0x" #constant ".");
42+
static_assert((expr) == 0x##constant, "Bad asm constant for '" #expr "'. Actual value: " OFFSET_STRING(expr, 0x##constant));
4243

4344
#include "AsmOffsets.h"
4445

src/coreclr/nativeaot/Runtime/CommonMacros.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment);
119119
#define LOG2_PTRSIZE 2
120120
#define POINTER_SIZE 4
121121

122-
#elif defined(HOST_LOONGARCH64)
122+
#elif defined(HOST_LOONGARCH64) || defined (HOST_RISCV64)
123123

124124
#define LOG2_PTRSIZE 3
125125
#define POINTER_SIZE 8

src/coreclr/nativeaot/Runtime/EHHelpers.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,24 @@ FCIMPL3(void, RhpCopyContextFromExInfo, void * pOSContext, int32_t cbOSContext,
203203
pContext->Sp = pPalContext->SP;
204204
pContext->Ra = pPalContext->RA;
205205
pContext->Pc = pPalContext->IP;
206+
#elif defined(HOST_RISCV64)
207+
pContext->A0 = pPalContext->A0;
208+
pContext->A1 = pPalContext->A1;
209+
pContext->S1 = pPalContext->S1;
210+
pContext->S2 = pPalContext->S2;
211+
pContext->S3 = pPalContext->S3;
212+
pContext->S4 = pPalContext->S4;
213+
pContext->S5 = pPalContext->S5;
214+
pContext->S6 = pPalContext->S6;
215+
pContext->S7 = pPalContext->S7;
216+
pContext->S8 = pPalContext->S8;
217+
pContext->S9 = pPalContext->S9;
218+
pContext->S10 = pPalContext->S10;
219+
pContext->S11 = pPalContext->S11;
220+
pContext->Fp = pPalContext->FP;
221+
pContext->Sp = pPalContext->SP;
222+
pContext->Ra = pPalContext->RA;
223+
pContext->Pc = pPalContext->IP;
206224
#elif defined(HOST_WASM)
207225
// No registers, no work to do yet
208226
#else
@@ -295,7 +313,7 @@ EXTERN_C CODE_LOCATION RhpCheckedAssignRefEBPAVLocation;
295313
#endif
296314
EXTERN_C CODE_LOCATION RhpByRefAssignRefAVLocation1;
297315

298-
#if !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64)
316+
#if !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64) && !defined(HOST_RISCV64)
299317
EXTERN_C CODE_LOCATION RhpByRefAssignRefAVLocation2;
300318
#endif
301319

@@ -328,7 +346,7 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP)
328346
(uintptr_t)&RhpCheckedAssignRefEBPAVLocation,
329347
#endif
330348
(uintptr_t)&RhpByRefAssignRefAVLocation1,
331-
#if !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64)
349+
#if !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64) && !defined(HOST_RISCV64)
332350
(uintptr_t)&RhpByRefAssignRefAVLocation2,
333351
#endif
334352
};
@@ -410,7 +428,7 @@ static uintptr_t UnwindSimpleHelperToCaller(
410428
pContext->SetSp(sp+sizeof(uintptr_t)); // pop the stack
411429
#elif defined(HOST_ARM) || defined(HOST_ARM64)
412430
uintptr_t adjustedFaultingIP = pContext->GetLr();
413-
#elif defined(HOST_LOONGARCH64)
431+
#elif defined(HOST_LOONGARCH64) || defined(HOST_RISCV64)
414432
uintptr_t adjustedFaultingIP = pContext->GetRa();
415433
#else
416434
uintptr_t adjustedFaultingIP = 0; // initializing to make the compiler happy

src/coreclr/nativeaot/Runtime/MiscHelpers.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ FCIMPL1(uint8_t *, RhGetCodeTarget, uint8_t * pCodeOrg)
335335
int64_t distToTarget = ((int64_t)pCode[0] << 38) >> 36;
336336
return (uint8_t *)pCode + distToTarget;
337337
}
338+
338339
#elif TARGET_LOONGARCH64
339340
uint32_t * pCode = (uint32_t *)pCodeOrg;
340341
// is this "addi.d $a0, $a0, 8"?
@@ -370,6 +371,45 @@ FCIMPL1(uint8_t *, RhGetCodeTarget, uint8_t * pCodeOrg)
370371
distToTarget += ((((int64_t)pCode[1] & ~0x3ff) << 38) >> 46);
371372
return (uint8_t *)((int64_t)pCode + distToTarget);
372373
}
374+
375+
#elif TARGET_RISCV64
376+
uint32_t * pCode = (uint32_t *)pCodeOrg;
377+
if (pCode[0] == 0x00850513) // Encoding for `addi a0, a0, 8` in 32-bit instruction format
378+
{
379+
// unboxing sequence
380+
unboxingStub = true;
381+
pCode++;
382+
}
383+
// is this an indirect jump?
384+
// lui t0, imm; jalr t0, t0, imm12
385+
if ((pCode[0] & 0x7f) == 0x17 && // auipc
386+
(pCode[1] & 0x707f) == 0x3003 && // ld with funct3=011
387+
(pCode[2] & 0x707f) == 0x0067) // jr (jalr with x0 as rd and funct3=000)
388+
{
389+
// Compute the distance to the IAT cell
390+
int64_t distToIatCell = (((int32_t)pCode[0]) >> 12) << 12; // Extract imm20 from auipc
391+
distToIatCell += ((int32_t)pCode[1]) >> 20; // Add imm12 from ld
392+
393+
uint8_t ** pIatCell = (uint8_t **)(((int64_t)pCode & ~0xfff) + distToIatCell);
394+
return *pIatCell;
395+
}
396+
397+
// Is this an unboxing stub followed by a relative jump?
398+
// auipc t0, imm20; jalr ra, imm12(t0)
399+
else if (unboxingStub &&
400+
(pCode[0] & 0x7f) == 0x17 && // auipc opcode
401+
(pCode[1] & 0x707f) == 0x0067) // jalr opcode with funct3=000
402+
{
403+
// Extract imm20 from auipc
404+
int64_t distToTarget = (((int32_t)pCode[0]) >> 12) << 12; // Extract imm20 (bits 31:12)
405+
406+
// Extract imm12 from jalr
407+
distToTarget += ((int32_t)pCode[1]) >> 20; // Extract imm12 (bits 31:20)
408+
409+
// Calculate the final target address relative to PC
410+
return (uint8_t *)((int64_t)pCode + distToTarget);
411+
}
412+
373413
#else
374414
UNREFERENCED_PARAMETER(unboxingStub);
375415
PORTABILITY_ASSERT("RhGetCodeTarget");

src/coreclr/nativeaot/Runtime/PalRedhawk.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,83 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
531531
}
532532
} CONTEXT, *PCONTEXT;
533533

534+
#elif defined(TARGET_RISCV64)
535+
536+
#define CONTEXT_RISCV64 0x01000000L
537+
538+
#define CONTEXT_CONTROL (CONTEXT_RISCV64 | 0x1L)
539+
#define CONTEXT_INTEGER (CONTEXT_RISCV64 | 0x2L)
540+
541+
#define RISCV64_MAX_BREAKPOINTS 8
542+
#define RISCV64_MAX_WATCHPOINTS 2
543+
544+
typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
545+
//
546+
// Control flags.
547+
//
548+
uint32_t ContextFlags;
549+
550+
//
551+
// Integer registers
552+
//
553+
uint64_t X0;
554+
uint64_t Ra;
555+
uint64_t Sp;
556+
uint64_t Gp;
557+
uint64_t Tp;
558+
uint64_t T0;
559+
uint64_t T1;
560+
uint64_t T2;
561+
uint64_t Fp;
562+
uint64_t S1;
563+
uint64_t A0;
564+
uint64_t A1;
565+
uint64_t A2;
566+
uint64_t A3;
567+
uint64_t A4;
568+
uint64_t A5;
569+
uint64_t A6;
570+
uint64_t A7;
571+
uint64_t S2;
572+
uint64_t S3;
573+
uint64_t S4;
574+
uint64_t S5;
575+
uint64_t S6;
576+
uint64_t S7;
577+
uint64_t S8;
578+
uint64_t S9;
579+
uint64_t S10;
580+
uint64_t S11;
581+
uint64_t T3;
582+
uint64_t T4;
583+
uint64_t T5;
584+
uint64_t T6;
585+
uint64_t Pc;
586+
587+
//
588+
// Floating Point Registers
589+
//
590+
uint64_t F[32];
591+
uint32_t Fcsr;
592+
593+
void SetIp(uintptr_t ip) { Pc = ip; }
594+
void SetArg0Reg(uintptr_t val) { A0 = val; }
595+
void SetArg1Reg(uintptr_t val) { A1 = val; }
596+
uintptr_t GetIp() { return Pc; }
597+
uintptr_t GetRa() { return Ra; }
598+
uintptr_t GetSp() { return Sp; }
599+
600+
template <typename F>
601+
void ForEachPossibleObjectRef(F lambda)
602+
{
603+
for (uint64_t* pReg = &X0; pReg <= &T6; pReg++)
604+
lambda((size_t*)pReg);
605+
606+
// RA can be used as a scratch register
607+
lambda((size_t*)&Ra);
608+
}
609+
} CONTEXT, *PCONTEXT;
610+
534611
#elif defined(HOST_WASM)
535612

536613
typedef struct DECLSPEC_ALIGN(8) _CONTEXT {

src/coreclr/nativeaot/Runtime/PalRedhawkCommon.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct PAL_LIMITED_CONTEXT
6161
uintptr_t GetLr() const { return LR; }
6262
void SetIp(uintptr_t ip) { IP = ip; }
6363
void SetSp(uintptr_t sp) { SP = sp; }
64+
6465
#elif defined(TARGET_ARM64)
6566
uintptr_t FP;
6667
uintptr_t LR;
@@ -91,6 +92,7 @@ struct PAL_LIMITED_CONTEXT
9192
uintptr_t GetLr() const { return LR; }
9293
void SetIp(uintptr_t ip) { IP = ip; }
9394
void SetSp(uintptr_t sp) { SP = sp; }
95+
9496
#elif defined(TARGET_LOONGARCH64)
9597
uintptr_t FP;
9698
uintptr_t RA;
@@ -121,6 +123,37 @@ struct PAL_LIMITED_CONTEXT
121123
void SetIp(uintptr_t ip) { IP = ip; }
122124
void SetSp(uintptr_t sp) { SP = sp; }
123125

126+
#elif defined(TARGET_RISCV64)
127+
128+
uintptr_t FP;
129+
uintptr_t RA;
130+
131+
uintptr_t A0;
132+
uintptr_t A1;
133+
uintptr_t S1;
134+
uintptr_t S2;
135+
uintptr_t S3;
136+
uintptr_t S4;
137+
uintptr_t S5;
138+
uintptr_t S6;
139+
uintptr_t S7;
140+
uintptr_t S8;
141+
uintptr_t S9;
142+
uintptr_t S10;
143+
uintptr_t S11;
144+
145+
uintptr_t SP;
146+
uintptr_t IP;
147+
148+
uint64_t F[12];
149+
150+
uintptr_t GetIp() const { return IP; }
151+
uintptr_t GetSp() const { return SP; }
152+
uintptr_t GetFp() const { return FP; }
153+
uintptr_t GetRa() const { return RA; }
154+
void SetIp(uintptr_t ip) { IP = ip; }
155+
void SetSp(uintptr_t sp) { SP = sp; }
156+
124157
#elif defined(UNIX_AMD64_ABI)
125158
// Param regs: rdi, rsi, rdx, rcx, r8, r9, scratch: rax, rdx (both return val), preserved: rbp, rbx, r12-r15
126159
uintptr_t IP;

0 commit comments

Comments
 (0)