Issue #3049 - Add loongarch64 wasm backend build support

This commit is contained in:
Basilisk-Dev 2026-04-24 15:58:49 -04:00 • committed by wuggy
commit 683173c33b
9 changed files with 113 additions and 53 deletions

View file

@ -1839,9 +1839,21 @@ class Assembler : public AssemblerLOONGARCH64 {
static void Bind(uint8_t* rawCode, CodeLabel label); static void Bind(uint8_t* rawCode, CodeLabel label);
void bind(RepatchLabel* label); void bind(RepatchLabel* label);
void bindLater(Label* label, wasm::TrapDesc target) { void bindLater(Label* label, wasm::TrapDesc target) {
(void)label; if (label->used()) {
(void)target; int32_t next;
MOZ_CRASH("wasm trap patching is not supported on loongarch64 yet");
BufferOffset b(label);
do {
Instruction* inst = editSrc(b);
append(wasm::TrapSite(target, b.getOffset()));
next = inst[1].encode();
inst[1].makeNop();
b = BufferOffset(next);
} while (next != LabelBase::INVALID_OFFSET);
}
label->reset();
} }
void processCodeLabels(uint8_t* rawCode); void processCodeLabels(uint8_t* rawCode);

View file

@ -1436,16 +1436,20 @@ void MacroAssembler::clampIntToUint8(Register reg) {
template <class L> template <class L>
void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label) { void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label) {
(void)cond; BufferOffset bo = ma_BoundsCheck(ScratchRegister);
(void)index; append(wasm::BoundsCheck(bo.getOffset()));
(void)label; ma_b(index, ScratchRegister, label, cond);
MOZ_CRASH("wasm bounds checks are not supported on loongarch64 yet");
} }
void MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit) { void MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit) {
(void)patchAt; InstImm* i0 = reinterpret_cast<InstImm*>(patchAt);
(void)limit; InstImm* i1 = reinterpret_cast<InstImm*>(i0->next());
MOZ_CRASH("wasm bounds checks are not supported on loongarch64 yet");
*i0 = InstImm(op_lu12i_w, int32_t((limit >> 12) & 0xfffff),
Register::FromCode(i0->extractRD()), false);
*i1 = InstImm(op_ori, int32_t(limit & 0xfff),
Register::FromCode(i1->extractRJ()),
Register::FromCode(i1->extractRD()), 12);
} }
void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) { void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) {

View file

@ -2469,18 +2469,19 @@ void MacroAssembler::repatchFarJump(uint8_t* code, uint32_t farJumpOffset,
} }
CodeOffset MacroAssembler::nopPatchableToNearJump() { CodeOffset MacroAssembler::nopPatchableToNearJump() {
MOZ_CRASH("wasm patchable jumps are not supported on loongarch64"); CodeOffset offset(currentOffset());
as_nop();
return offset;
} }
void MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target) { void MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target) {
(void)jump; MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>());
(void)target; new (jump) InstJump(op_b, JOffImm26(target - jump));
MOZ_CRASH("wasm patchable jumps are not supported on loongarch64");
} }
void MacroAssembler::patchNearJumpToNop(uint8_t* jump) { void MacroAssembler::patchNearJumpToNop(uint8_t* jump) {
(void)jump; MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstJump>());
MOZ_CRASH("wasm patchable jumps are not supported on loongarch64"); new (jump) InstNOP();
} }
void MacroAssembler::call(wasm::SymbolicAddress target) { void MacroAssembler::call(wasm::SymbolicAddress target) {

View file

@ -116,6 +116,27 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
Label* overflow); Label* overflow);
void ma_add32TestOverflow(Register rd, Register rj, Imm32 imm, void ma_add32TestOverflow(Register rd, Register rj, Imm32 imm,
Label* overflow); Label* overflow);
template <typename L>
void ma_add32TestOverflow(Register rd, Register rj, Register rk,
L overflow) {
ScratchRegisterScope scratch(asMasm());
as_add_d(scratch, rj, rk);
as_add_w(rd, rj, rk);
ma_b(rd, Register(scratch), overflow, Assembler::NotEqual);
}
template <typename L>
void ma_add32TestOverflow(Register rd, Register rj, Imm32 imm, L overflow) {
if (is_intN(imm.value, 12)) {
ScratchRegisterScope scratch(asMasm());
as_addi_d(scratch, rj, imm.value);
as_addi_w(rd, rj, imm.value);
ma_b(rd, scratch, overflow, Assembler::NotEqual);
} else {
SecondScratchRegisterScope scratch2(asMasm());
ma_li(scratch2, imm);
ma_add32TestOverflow(rd, rj, scratch2, overflow);
}
}
void ma_addPtrTestOverflow(Register rd, Register rj, Register rk, void ma_addPtrTestOverflow(Register rd, Register rj, Register rk,
Label* overflow); Label* overflow);
void ma_addPtrTestOverflow(Register rd, Register rj, Imm32 imm, void ma_addPtrTestOverflow(Register rd, Register rj, Imm32 imm,
@ -257,6 +278,25 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
Label* overflow); Label* overflow);
void ma_add32TestCarry(Condition cond, Register rd, Register rj, Imm32 imm, void ma_add32TestCarry(Condition cond, Register rd, Register rj, Imm32 imm,
Label* overflow); Label* overflow);
template <typename L>
void ma_add32TestCarry(Condition cond, Register rd, Register rj, Register rk,
L overflow) {
MOZ_ASSERT(cond == Assembler::CarrySet || cond == Assembler::CarryClear);
MOZ_ASSERT_IF(rd == rj, rk != rd);
ScratchRegisterScope scratch(asMasm());
as_add_w(rd, rj, rk);
as_sltu(scratch, rd, rd == rj ? rk : rj);
ma_b(Register(scratch), Register(scratch), overflow,
cond == Assembler::CarrySet ? Assembler::NonZero : Assembler::Zero);
}
template <typename L>
void ma_add32TestCarry(Condition cond, Register rd, Register rj, Imm32 imm,
L overflow) {
SecondScratchRegisterScope scratch2(asMasm());
MOZ_ASSERT(rj != scratch2);
ma_li(scratch2, imm);
ma_add32TestCarry(cond, rd, rj, scratch2, overflow);
}
// subtract // subtract
void ma_sub_w(Register rd, Register rj, Imm32 imm); void ma_sub_w(Register rd, Register rj, Imm32 imm);
@ -376,18 +416,15 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
template <typename T> template <typename T>
void ma_b(Register lhs, const T& rhs, wasm::TrapDesc target, void ma_b(Register lhs, const T& rhs, wasm::TrapDesc target,
Condition c, JumpKind jumpKind = LongJump) { Condition c, JumpKind jumpKind = LongJump) {
(void)lhs; Label label;
(void)rhs; ma_b(lhs, rhs, &label, c, jumpKind);
(void)target; bindLater(&label, target);
(void)c;
(void)jumpKind;
MOZ_CRASH("wasm trap branches are not supported on loongarch64 yet");
} }
void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump) { void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump) {
(void)target; Label label;
(void)jumpKind; ma_b(&label, jumpKind);
MOZ_CRASH("wasm trap jumps are not supported on loongarch64 yet"); bindLater(&label, target);
} }
void ma_b(Label* l, JumpKind jumpKind = LongJump); void ma_b(Label* l, JumpKind jumpKind = LongJump);
@ -1306,12 +1343,13 @@ class MacroAssemblerLOONGARCH64Compat : public MacroAssemblerLOONGARCH64 {
static void calculateAlignedStackPointer(void** stackPointer); static void calculateAlignedStackPointer(void** stackPointer);
void loadWasmGlobalPtr(uint32_t globalDataOffset, Register dest) { void loadWasmGlobalPtr(uint32_t globalDataOffset, Register dest) {
(void)globalDataOffset; loadPtr(Address(GlobalReg, globalDataOffset - WasmGlobalRegBias), dest);
(void)dest;
MOZ_CRASH("wasm globals are not supported on loongarch64 yet");
} }
void loadWasmPinnedRegsFromTls() { void loadWasmPinnedRegsFromTls() {
MOZ_CRASH("wasm pinned registers are not supported on loongarch64 yet"); loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, memoryBase)), HeapReg);
loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, globalData)),
GlobalReg);
ma_add_d(GlobalReg, GlobalReg, Imm32(WasmGlobalRegBias));
} }
void cmpPtrSet(Assembler::Condition cond, Address lhs, ImmPtr rhs, void cmpPtrSet(Assembler::Condition cond, Address lhs, ImmPtr rhs,

View file

@ -375,6 +375,11 @@ if not CONFIG['JS_CODEGEN_LOONGARCH64']:
'wasm/WasmBaselineCompile.cpp', 'wasm/WasmBaselineCompile.cpp',
'wasm/WasmIonCompile.cpp', 'wasm/WasmIonCompile.cpp',
] ]
else:
SOURCES += [
'wasm/WasmBaselineCompile.cpp',
'wasm/WasmIonCompile.cpp',
]
# jsarray.cpp and jsatom.cpp cannot be built in unified mode because # jsarray.cpp and jsatom.cpp cannot be built in unified mode because
# xpcshell is broken during packaging when compiled with gcc-4.8.2 # xpcshell is broken during packaging when compiled with gcc-4.8.2

View file

@ -242,7 +242,14 @@ static const unsigned PushedRetAddr = 8;
static const unsigned PushedFP = 32; static const unsigned PushedFP = 32;
static const unsigned StoredFP = 36; static const unsigned StoredFP = 36;
static const unsigned PostStorePrePopFP = 4; static const unsigned PostStorePrePopFP = 4;
#elif defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64) #elif defined(JS_CODEGEN_LOONGARCH64)
static const unsigned PushedRetAddr = 8;
static const unsigned PushedFP = 36;
static const unsigned StoredFP = 40;
# if defined(DEBUG)
static const unsigned PostStorePrePopFP = 0;
# endif
#elif defined(JS_CODEGEN_NONE)
# if defined(DEBUG) # if defined(DEBUG)
static const unsigned PushedRetAddr = 0; static const unsigned PushedRetAddr = 0;
static const unsigned PostStorePrePopFP = 0; static const unsigned PostStorePrePopFP = 0;
@ -258,7 +265,8 @@ PushRetAddr(MacroAssembler& masm)
{ {
#if defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_ARM)
masm.push(lr); masm.push(lr);
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
defined(JS_CODEGEN_LOONGARCH64)
masm.push(ra); masm.push(ra);
#else #else
// The x86/x64 call instruction pushes the return address. // The x86/x64 call instruction pushes the return address.

View file

@ -172,6 +172,11 @@ class AutoSetHandlingSegFault
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29]) # define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30]) # define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
# endif # endif
# if defined(__linux__) && defined(__loongarch__)
# define EPC_sig(p) ((p)->uc_mcontext.__pc)
# define RSP_sig(p) ((p)->uc_mcontext.__gregs[3])
# define RFP_sig(p) ((p)->uc_mcontext.__gregs[22])
# endif
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i]) # define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
# define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP]) # define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
@ -399,7 +404,7 @@ struct macos_aarch64_context {
static uint8_t** static uint8_t**
ContextToPC(CONTEXT* context) ContextToPC(CONTEXT* context)
{ {
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64) #if defined(JS_CODEGEN_NONE)
MOZ_CRASH(); MOZ_CRASH();
#else #else
return reinterpret_cast<uint8_t**>(&PC_sig(context)); return reinterpret_cast<uint8_t**>(&PC_sig(context));

View file

@ -84,7 +84,7 @@ static const LiveRegisterSet NonVolatileRegs =
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) + static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
NonVolatileRegs.fpus().getPushSizeInBytes() + NonVolatileRegs.fpus().getPushSizeInBytes() +
sizeof(double); sizeof(double);
#elif defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64) #elif defined(JS_CODEGEN_NONE)
static const unsigned FramePushedAfterSave = 0; static const unsigned FramePushedAfterSave = 0;
#else #else
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t)
@ -107,7 +107,8 @@ wasm::GenerateEntry(MacroAssembler& masm, const FuncExport& fe)
// Save the return address if it wasn't already saved by the call insn. // Save the return address if it wasn't already saved by the call insn.
#if defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_ARM)
masm.push(lr); masm.push(lr);
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
defined(JS_CODEGEN_LOONGARCH64)
masm.push(ra); masm.push(ra);
#endif #endif
@ -1099,21 +1100,3 @@ wasm::GenerateThrowStub(MacroAssembler& masm, Label* throwLabel)
offsets.end = masm.currentOffset(); offsets.end = masm.currentOffset();
return offsets; return offsets;
} }
#if defined(JS_CODEGEN_LOONGARCH64)
bool
js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
{
(void)fg;
return false;
}
bool
js::wasm::CompileFunction(IonCompileTask* task)
{
(void)task;
return false;
}
#endif

View file

@ -379,6 +379,7 @@ GetCPUID()
ARM = 0x3, ARM = 0x3,
MIPS = 0x4, MIPS = 0x4,
MIPS64 = 0x5, MIPS64 = 0x5,
LOONGARCH64 = 0x6,
ARCH_BITS = 3 ARCH_BITS = 3
}; };
@ -399,7 +400,10 @@ GetCPUID()
#elif defined(JS_CODEGEN_MIPS64) #elif defined(JS_CODEGEN_MIPS64)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS)); MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
return MIPS64 | (jit::GetMIPSFlags() << ARCH_BITS); return MIPS64 | (jit::GetMIPSFlags() << ARCH_BITS);
#elif defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64) #elif defined(JS_CODEGEN_LOONGARCH64)
MOZ_ASSERT(jit::GetLOONGARCH64Flags() <= (UINT32_MAX >> ARCH_BITS));
return LOONGARCH64 | (jit::GetLOONGARCH64Flags() << ARCH_BITS);
#elif defined(JS_CODEGEN_NONE)
return 0; return 0;
#else #else
# error "unknown architecture" # error "unknown architecture"