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);
void bind(RepatchLabel* label);
void bindLater(Label* label, wasm::TrapDesc target) {
(void)label;
(void)target;
MOZ_CRASH("wasm trap patching is not supported on loongarch64 yet");
if (label->used()) {
int32_t next;
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);

View file

@ -1436,16 +1436,20 @@ void MacroAssembler::clampIntToUint8(Register reg) {
template <class L>
void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label) {
(void)cond;
(void)index;
(void)label;
MOZ_CRASH("wasm bounds checks are not supported on loongarch64 yet");
BufferOffset bo = ma_BoundsCheck(ScratchRegister);
append(wasm::BoundsCheck(bo.getOffset()));
ma_b(index, ScratchRegister, label, cond);
}
void MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit) {
(void)patchAt;
(void)limit;
MOZ_CRASH("wasm bounds checks are not supported on loongarch64 yet");
InstImm* i0 = reinterpret_cast<InstImm*>(patchAt);
InstImm* i1 = reinterpret_cast<InstImm*>(i0->next());
*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) {

View file

@ -2469,18 +2469,19 @@ void MacroAssembler::repatchFarJump(uint8_t* code, uint32_t farJumpOffset,
}
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)jump;
(void)target;
MOZ_CRASH("wasm patchable jumps are not supported on loongarch64");
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>());
new (jump) InstJump(op_b, JOffImm26(target - jump));
}
void MacroAssembler::patchNearJumpToNop(uint8_t* jump) {
(void)jump;
MOZ_CRASH("wasm patchable jumps are not supported on loongarch64");
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstJump>());
new (jump) InstNOP();
}
void MacroAssembler::call(wasm::SymbolicAddress target) {

View file

@ -116,6 +116,27 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
Label* overflow);
void ma_add32TestOverflow(Register rd, Register rj, Imm32 imm,
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,
Label* overflow);
void ma_addPtrTestOverflow(Register rd, Register rj, Imm32 imm,
@ -257,6 +278,25 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
Label* overflow);
void ma_add32TestCarry(Condition cond, Register rd, Register rj, Imm32 imm,
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
void ma_sub_w(Register rd, Register rj, Imm32 imm);
@ -376,18 +416,15 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
template <typename T>
void ma_b(Register lhs, const T& rhs, wasm::TrapDesc target,
Condition c, JumpKind jumpKind = LongJump) {
(void)lhs;
(void)rhs;
(void)target;
(void)c;
(void)jumpKind;
MOZ_CRASH("wasm trap branches are not supported on loongarch64 yet");
Label label;
ma_b(lhs, rhs, &label, c, jumpKind);
bindLater(&label, target);
}
void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump) {
(void)target;
(void)jumpKind;
MOZ_CRASH("wasm trap jumps are not supported on loongarch64 yet");
Label label;
ma_b(&label, jumpKind);
bindLater(&label, target);
}
void ma_b(Label* l, JumpKind jumpKind = LongJump);
@ -1306,12 +1343,13 @@ class MacroAssemblerLOONGARCH64Compat : public MacroAssemblerLOONGARCH64 {
static void calculateAlignedStackPointer(void** stackPointer);
void loadWasmGlobalPtr(uint32_t globalDataOffset, Register dest) {
(void)globalDataOffset;
(void)dest;
MOZ_CRASH("wasm globals are not supported on loongarch64 yet");
loadPtr(Address(GlobalReg, globalDataOffset - WasmGlobalRegBias), dest);
}
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,

View file

@ -375,6 +375,11 @@ if not CONFIG['JS_CODEGEN_LOONGARCH64']:
'wasm/WasmBaselineCompile.cpp',
'wasm/WasmIonCompile.cpp',
]
else:
SOURCES += [
'wasm/WasmBaselineCompile.cpp',
'wasm/WasmIonCompile.cpp',
]
# jsarray.cpp and jsatom.cpp cannot be built in unified mode because
# 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 StoredFP = 36;
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)
static const unsigned PushedRetAddr = 0;
static const unsigned PostStorePrePopFP = 0;
@ -258,7 +265,8 @@ PushRetAddr(MacroAssembler& masm)
{
#if defined(JS_CODEGEN_ARM)
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);
#else
// 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 RFP_sig(p) ((p)->uc_mcontext.gregs[30])
# 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__)
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
# define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
@ -399,7 +404,7 @@ struct macos_aarch64_context {
static uint8_t**
ContextToPC(CONTEXT* context)
{
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64)
#if defined(JS_CODEGEN_NONE)
MOZ_CRASH();
#else
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) +
NonVolatileRegs.fpus().getPushSizeInBytes() +
sizeof(double);
#elif defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_LOONGARCH64)
#elif defined(JS_CODEGEN_NONE)
static const unsigned FramePushedAfterSave = 0;
#else
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.
#if defined(JS_CODEGEN_ARM)
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);
#endif
@ -1099,21 +1100,3 @@ wasm::GenerateThrowStub(MacroAssembler& masm, Label* throwLabel)
offsets.end = masm.currentOffset();
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,
MIPS = 0x4,
MIPS64 = 0x5,
LOONGARCH64 = 0x6,
ARCH_BITS = 3
};
@ -399,7 +400,10 @@ GetCPUID()
#elif defined(JS_CODEGEN_MIPS64)
MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> 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;
#else
# error "unknown architecture"