Add PPC64 JIT support for Firefox 153 ESR - #2
Open
runlevel5 wants to merge 8 commits into
Open
Conversation
3 tasks
runlevel5
force-pushed
the
esr153-ppc64
branch
14 times, most recently
from
July 8, 2026 03:19
e9723ce to
fdbcbbf
Compare
runlevel5
force-pushed
the
esr153-ppc64
branch
11 times, most recently
from
July 23, 2026 03:08
c6f34cc to
1bdb171
Compare
runlevel5
force-pushed
the
esr153-ppc64
branch
3 times, most recently
from
July 26, 2026 03:55
a9e7e5c to
6c6f6a9
Compare
runlevel5
force-pushed
the
esr153-ppc64
branch
3 times, most recently
from
August 12, 2026 03:05
ec44ada to
4cd6549
Compare
Adapted from work done by Raptor Engineering for chromium's vendored SKIA. Gated to little-endian: the SSE-derived swizzle and permute helpers assume the ppc64le vector-register byte order, so big-endian falls back to the portable paths. Co-authored-by: Timothy Pearson <tpearson@raptorengineering.com>
Gated to little-endian: the VSX kernels assume the ppc64le vector-register byte order, so big-endian falls back to the portable C paths. Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: James Zern <jzern@google.com>
Based on the work done by Cameron Kaiser and Justin Hibbits https://github.com/chmeeedalf/gecko-dev Co-authored-by: Cameron Kaiser <classilla@floodgap.com> Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com> Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: Timothy Pearson <tpearson@solidsilicon.com> Assisted-by: Dan Horák <dan@danny.cz> Assisted-by: Hiếu Lê <modology@gmail.com> Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Enable the SpiderMonkey JIT and WebAssembly on big-endian PPC64 (ELFv1 and ELFv2). Co-authored-by: Cameron Kaiser <classilla@floodgap.com> Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com> Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: Timothy Pearson <tpearson@solidsilicon.com> Assisted-by: Dan Horák <dan@danny.cz> Assisted-by: Hiếu Lê <modology@gmail.com> Assisted-by: Claude Fable 5 <noreply@anthropic.com> Assisted-by: Alexander Baldeck <alex.bldck@gmail.com>
The build system defines HAVE_PLATFORM_GHASH for both PPC64 endians, but the POWER8 vpmsumd GHASH implementation was compiled out on big-endian, leaving platform_ghash_support, gcm_HashInit_hw, gcm_HashWrite_hw and gcm_HashZeroX_hw unresolved and freebl failing to link. Make ghash-ppc.c endian-correct instead of stubbing it out. GNU C vector element indexing follows memory order, so the doubleword element reads, the pair constructors and the vec_splat index of the most-significant byte must mirror on big-endian, while vec_xl_be, vec_xst_be and the whole-register operations (vpmsumd, vec_sll, vec_rl, xor) already produce identical register values on both endians. The new USE_PPC_CRYPTO_GHASH define drops the little-endian restriction for ghash-ppc.c only; the other USE_PPC_CRYPTO consumers remain little-endian. Also give gcm.c the same -mcrypto/-maltivec cflags as ghash-ppc.c in gcm.gyp. gcmHashContext's vec_u64 x/h fields are gated on __ALTIVEC__/__VSX__, so without this gcm.c and ghash-ppc.c disagree on sizeof(gcmHashContext) and every field after x/h -- including the ghash_mul function pointer -- lands at a different offset in each translation unit, corrupting the hardware GHASH dispatch. This is not endian-specific: it affects ppc64le the same way whenever disable_crypto_vsx doesn't already imply matching flags elsewhere. Found by crashing on a real TLS 1.3 handshake (AES-GCM record decrypt) in a full browser build, not just the isolated GHASH unit tests. Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=2027768
Big-endian used to flip the OS_RGBA surface format synonyms to the
A8R8G8B8 memory layout, which Skia has no color type for, so surface
creation hit MOZ_DIAGNOSTIC_CRASH("A8R8G8B8 unsupported by Skia") as
soon as anything was drawn. Keep the synonyms pinned to the B8G8R8A8
memory layout on both endians so the whole pixel pipeline operates on
one layout, and convert for the display server at the compositor
boundary instead.
Skia's SkPMColor channel shifts describe a little-endian uint32_t
view of that layout, so on big-endian a packed color value and the
in-memory destination pixels disagree on byte order. Introduce
BE_CONVERT (a no-op on little-endian) and apply it at the scalar
blitter load/store boundaries: solid fills, the blit_row_color32
kernel, A8 glyph masks, LCD16 subpixel text, BW masks, the black
blitter, and the direct-blit fill value. Alpha extraction always uses
the unconverted value. The SurfaceFormatBit shifts mirror on
big-endian so channel accessors keep addressing the same bytes, and
kARGBAlphaOffset moves to byte 0 for the RGBX verification.
Software WebRender resolves frames in the B8G8R8A8 memory layout, but
X11 consumes native-endian 32-bit pixel values, so swizzle the dirty
region to the A8R8G8B8 layout when handing the buffer to the widget.
Skia-drawn image surfaces get the inverse reorder in imgFrame before
they enter the surface cache.
Known gap: SkRasterPipeline's load/store stages and the headless
screenshot readback still assume little-endian and are unchanged.
Add a pre-VSX tier to the PPC64 JIT so the engine runs with the JIT enabled on PowerPC 970 (ISA 2.01) hardware, detected at runtime via AT_HWCAP PPC_FEATURE_HAS_VSX and testable on newer silicon with MOZ_PPC64_FORCE_970=1. Scalar fallbacks replace every VSX and post-2.01 instruction the port emits: GPR<->FPR moves round-trip through the ABI red zone (mtvsrd, mfvsrd, mtvsrwz, mtvsrwa, lfiwax); round-to-integral swaps the FPSCR RN field around fctid/fcfid (friz, frip, frim) with a new mtfsfi emitter, quieting signaling NaNs on the pass-through path as the hardware forms do; fcpsgn, isel, popcntd/popcntw and the unsigned int64 conversions (fcfidu, fctiduz) get branch- or SWAR-based equivalents; int64-to- float32 converts with round-to-odd (truncate-mode fcfid, then FPSCR FI sets the mantissa lsb) so the final frsp rounds exactly like fcfids; the unsigned truncations split at 2**63 in the GPR domain and reject negative inputs the signed fctidz would accept; 64-bit byte-reversed wasm memory accesses use ldx/stdx plus a red-zone byte swap that needs no scratch register beyond r0, with store trap sites deferred to the faulting instruction; min/max and zero-constant materialization avoid xsmindp/xsmaxdp/xxlxor. Sub-word atomics (lbarx/lharx/stbcx./sthcx. are ISA 2.06) run the classic masked-word lwarx/stwcx. dance on the containing aligned word; the lowering allocates the value/offset/mask temps the dance needs (the native path never read them, and Ion collapses unused bogus temps onto one register). Wasm SIMD is unavailable on the tier: feature detection reports it absent, register save/restore skips the nonexistent v128 state, and SupportsFastUnalignedFPAccesses() gates the 16-byte tier of the inline wasm memory.copy/init expansion. Debug builds assert HasVSX() in every VSX-form encoder and each gated emitter so an unconverted call site fails fast instead of executing an illegal instruction on real hardware. Raise LIFO_ALLOC_ALIGN to 16: C++17 requires allocation functions to return storage aligned to __STDCPP_DEFAULT_NEW_ALIGNMENT__ (16 on ppc64), and GCC 16 exploits that guarantee when vectorizing member zero-initialization of TempObject-derived classes. At -mcpu=970 it emits VMX stvx, which masks the low 4 address bits, so 8-byte-aligned LifoAlloc storage caused wrong-address stores and uninitialized members. Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: Claude Fable 5 <noreply@anthropic.com> Assisted-by: Alexander Baldeck <alex.bldck@gmail.com>
runlevel5
force-pushed
the
esr153-ppc64
branch
from
August 19, 2026 00:55
4cd6549 to
f84b406
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PPC64 JIT support for Firefox 153 ESR
Brings JIT compilation to PPC64 — both little-endian (ppc64le) and big-endian (ppc64/ppc64be, ELFv1 and ELFv2) — targeting POWER8+ (ISA v2.07+) with POWER9 (ISA v3.0) / POWER10 (ISA 3.1) optimizations, plus a big-endian-only PowerPC 970 (ISA v2.01, pre-VSX / Apple G5) fallback tier. Enables SpiderMonkey's Baseline interpreter, Baseline and Ion JIT compilers, the native regexp JIT, plus full WebAssembly support — tiering, SIMD, huge memory, JSPI, tail calls, and atomics.
This PR revives the JIT port https://github.com/chmeeedalf/gecko-dev by Cameron Kaiser (classilla) and Justin Hibbits (chmeeedalf).
This PR would always track against the esr153 branch. If you are a packager, please find downstream patches in Releases, if the version you are after are not there, please simply leave a comment in this PR and I will prepare the patches for you.
Test results
Real little-endian POWER8 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):
--jitflags=all)jstests(JSPI on)Real POWER9 hardware (SpiderMonkey with debug, GCC 16, Raptor Computing System Blackbird workstation):
MOZ_PPC64_FORCE_POWER8=1--jitflags=all)jstests(JSPI on)Real POWER10 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):
MOZ_PPC64_FORCE_POWER9=1MOZ_PPC64_FORCE_POWER8=1--jitflags=all)jstests(JSPI on)ARM64-host simulator:
FORCE_POWER8=1FORCE_POWER9=1FORCE_POWER10=1jstests(JSPI on)†
shell/os.js("killed process should not have exitStatus") was a parallel-load flake on slower hosts — the test sent SIGINT to asleep 60child and could lose the signal-delivery race under heavy concurrent jstests load, then waitpid blocked until the child exited normally and the assertion failed. Fixed 2026-05-08 by switching to SIGKILL (which is uncatchable, atomic, and works under any load). Patch in this PR.FORCE_POWER10=1impliesFORCE_POWER9=1(matches what real-P10 silicon advertises inhwcap2— bothARCH_3_00andARCH_3_1). Six clean sweeps total — zero hard FAIL, zero TIMEOUT.Real big-endian POWER9 hardware — ELFv1 (Debian ppc64, "bigboy") and ELFv2 (Arch POWER ppc64, "elfv2"), SpiderMonkey debug shell:
--jitflags=all)jstestsMOZ_PPC64_FORCE_POWER8=1MOZ_PPC64_FORCE_POWER8=1‡
bug1782468-ptrdiff-veclen.jsandlarge-arraybuffers/bug2043700.jsare memory-pressure false positives under--jitflags=all's heaviest parallel load on the 7 GB ELFv2 box; both pass cleanly when re-run in isolation.A continuous baseline-vs-Ion differential WebAssembly fuzzer runs on both the ELFv1 and ELFv2 hosts with zero mismatches.
A real big-endian-only JIT bug was found and fixed by this hardware validation. The inline
Map/SetBigInt-key hash (MacroAssembler::prepareHashBigInt) computed a different hash than the C++ reference on big-endian, soMap/Setlookups keyed on aBigIntcould miss under Warp/Ion — a release-build correctness bug. Notably, this branch needed the opposite fix from the Firefox 154+ PR: between ESR 153 and current main, Mozilla refactoredmozilla::HashBytes(from an 8-byte native-value walk that decomposes low-word-then-high-word, to a 4-byte in-memory-order walk). On ESR 153 the JIT's default register-based digit hashing already matches the value-based reference on both endians, so the correct fix here is to use the shared path unchanged — no PPC64 big-endian special case. Root-caused by instrumenting the debug hash assertion and hand-verifying the hash chain bit-for-bit; the tables above are post-fix on both ELFv1 and ELFv2.Big-endian (ppc64be) support
The same backend runs big-endian, on both the ELFv1 and ELFv2 ABIs, across POWER8/9/10:
_CALL_ELF, not byte order — big-endian ELFv2 shares the little-endian call paths (no function descriptors), while ELFv1 uses{entry, TOC, env}descriptors for the JIT / regexp / wasm entry trampolines and symbolic-address calls.mozilla::Resultnarrow storage. jit-test and wasm spec-harness cases that hard-coded little-endian byte order are made endian-neutral.PowerPC 970 (G5) support — pre-VSX fallback tier
The backend also runs on the PowerPC 970 / 970FX / 970MP (Apple Power Mac G5, IBM JS20/JS21) — a big-endian-only, pre-VSX processor at Power ISA v2.01. There is no little-endian 970, so this tier is big-endian exclusively.
The 970 predates VSX (ISA 2.06) and the ISA 2.02–2.07 instructions the POWER8+ backend emits freely (
mtvsrd/mfvsrd,xsmindp/xsmaxdp,xxlxor,isel,popcntd/popcntw,fcfids/fctiduz,lbarx/stbcx.,ldbrx/stdbrx,frim/frip/friz,lfiwax,fcpsgn, …). Rather than disabling the JIT, this tier provides a scalar fallback for every one of them, selected at runtime:getauxval(AT_HWCAP)PPC_FEATURE_HAS_VSX— absent → pre-VSX tier.MOZ_PPC64_FORCE_970=1; the CPU executes both the scalar and the VSX encodings, so the scalar codegen is exercised and verified on modern silicon.MOZ_ASSERT(HasVSX())guards every VSX-form encoder and each gated emitter, so an unconverted call site fails fast at codegen time instead of executing an illegal instruction on a real G5.Fallback highlights: GPR↔FPR moves round-trip through the ABI red zone; round-to-integral swaps the FPSCR
RNfield aroundfctid/fcfid(newmtfsfiemitter), quieting signaling NaNs like the hardware forms; popcount is 64-bit SWAR; select is branch-based;int64→f32uses round-to-odd (truncate-modefcfid+ FPSCRFImantissa-lsb) so the finalfrspsingle-rounds exactly; unsigned 64-bit truncation splits at 2⁶³ in the GPR domain and rejects the negative inputs a signedfctidzwould accept; sub-word atomics run the classic masked-wordlwarx/stwcx.dance, so JSAtomicsand wasm shared memory stay fully JIT-inlined.Feature parity vs the POWER8+ tier
Atomics(incl. sub-word 8/16-bit)Wasm SIMD is reported unavailable rather than emulated: the 970's VMX has no 64-bit integer lanes and no
f64x2, so a faithful v128 tier isn't practical — the same posture SpiderMonkey takes on SSE4.1-less x86. All non-SIMD wasm runs.Test results
Validated with
MOZ_PPC64_FORCE_970=1on real big-endian POWER9 hardware (Arch POWER ppc64, ELFv2, GCC 16.1.1), SpiderMonkey debug shell built with-mcpu=970:--jitflags=all)MOZ_PPC64_FORCE_970=1(ELFv2)The
-mcpu=970shell additionally compiles with zero code changes and runs correctly in interpreter-only mode (--no-jit-backend); the static binary is verifiably VSX-free byobjdump, so even the non-JIT fallback is 970-safe.A one-line correctness fix rides along —
LIFO_ALLOC_ALIGN8 → 16. C++17 requires allocation functions to return storage aligned to__STDCPP_DEFAULT_NEW_ALIGNMENT__(16 on ppc64); GCC 16 exploits that when vectorizing member zero-init ofTempObject-derived classes, and at-mcpu=970it emits VMXstvx, which masks the low 4 address bits — so 8-byte-alignedLifoAllocstorage caused wrong-address stores and uninitialized members (a silent release-build corruption on real hardware, surfaced by the 970 build).Scope
js/src/jit/ppc64/— ~17,500 lines.What's new vs the old chmeeedalf/gecko-dev Firefox-86 port
Inherited:
Architecture-ppc64.hregister/ABI constants, theAssembler-ppc64.h/cppinstruction-encoding skeleton, some basic MacroAssembler patterns.New in this port:
js/moz.configure, dispatch headers,js/src/jit/moz.build).CodeGenerator, Lowering visitors, LIR-ppc64 (old fork predated Warp).CompareExchange/AtomicExchange/AtomicFetchOp.getauxval(AT_HWCAP2), with fallback sequences for every POWER9-only instruction and POWER10 fast paths gated onHasPOWER10().addpcisFP-constant path, POWER10 prefix-instruction fast paths (see below), GCC-stylelis+ori+rldimi64-bit load (~37 % smaller than abcl-based stanza).FlushICache.Key architecture-specific features
Runtime POWER8/POWER9/POWER10 selection
Detection via
getauxval(AT_HWCAP2)—PPC_FEATURE2_ARCH_3_00for POWER9,PPC_FEATURE2_ARCH_3_1for POWER10.cnttzd/w,xxbrd,mtvsrws,mcrxrx,addpcis,modsw/u/d/du,vinsert{b,h}(lane insert from VR + immediate byte position),xxinsertw,mfvsrld,mtvsrdd,xs{min,max}jdp,xxspltib,vcmpne{b,h,w},vneg{w,d},isel,xscvdphp/xscvhpdp(FP16 scalar conversion),xsxexpdp(P9 exponent extract fornearbyIntDouble).replaceLaneInt{8x16,16x8}on POWER9 emits the 2-insnmtvsrd + vinsert{b,h}sequence (down from 5 insns).clampDoubleToUint8is fully branchless on P9 viaxsmaxjdp + isel— the canonical JS clamp shape collapses to a 4-insn straight-line sequence.HasPOWER10()):Addressoperands when displacement exceeds 16 bits):loadPtr→pld,loadDouble→plfd,loadFloat32→plfs,loadUnalignedSimd128→plxv. Replaces the prioraddis + ori + ldx-style two-insn stanzas with one prefixed insn.storePtr→pstd,storeDouble→pstfd,storeFloat32→pstfs,storeUnalignedSimd128→pstxv.loadConstantSimd1283 +xxpermdi→ 1plxv;loadConstantDouble/Float322 → 1plfd/plfs;movePtr(ImmWord)33–34-bit signed 5 → 1paddi.brdcollapsesbyteSwap643 → 1 + drops the GPR↔FPR round-trip;brh/brwcollapsebyteSwap16{Sign,Zero}Extend/byteSwap32from 3-4 → 2;vinsw/vinsdcollapsereplaceLaneInt{32x4,64x2}from 2 → 1 (no scratch VSR);vinsbrx/vinshrxcover the same byte/halfword replaceLane on POWER10;vextract{b,h,w,d}mcollapses bitmask to 1 insn;vmulldcollapsesmulInt64x2from 9-11 insns to 1.setbc/setbcr: 1-insnma_cmp_set, 1-insnallTrueInt*CR6.EQ extract, and 5 → 3 insnanyTrueSimd128. Replaces the oldermfocrf + rlwinm + andi.extraction pattern across the boolean-reduction family.Test with
MOZ_PPC64_FORCE_POWER8=1(downgrade),MOZ_PPC64_FORCE_POWER9=1(force P9 on, useful under sim), orMOZ_PPC64_FORCE_POWER10=1(which impliesFORCE_POWER9=1— matches real-P10 silicon detection). All three configurations PASS the full jit-test + jstests sweeps end-to-end on the simulator.POWER10 prefix-instruction support
Power ISA v3.1 prefixed instructions are 8 bytes (4-byte prefix word with primary opcode 1 + 4-byte suffix word) and must not straddle a 64-byte aligned block at runtime. The assembler emits them via
as_paddi/as_pld/as_plxv/as_plfd/as_plfs, with an automatic leading-nop guard when the prefix would otherwise cross the boundary.The original guard checked
(currentOffset() & 63) == 60— a buffer-relative test that's only correct when the JitCode allocator base is 64-byte aligned. The allocator only guarantees 16-byte alignment, so across the four base-mod-64 classes {0, 16, 32, 48} the unsafe straddle is exactly(currentOffset() & 15) == 12. The same fix shape applies to the inline-emit path (ensurePrefixedAlignment, commit8ae818d0fcab) and the constant-pool patcher (PatchConstantPoolLoad, commitaea233e21209). The simulator's POWER10 model doesn't trap misaligned prefixes, which is why these only surfaced when real-P10 silicon came online.The simulator decodes prefixed instructions, validated against
as -mpower10+objdumpon Fedora 44 / binutils 2.46. Encoding details (MLS Type=2 vs 8LS Type=0 vs 8RR Type=1, R-bit at LE position 20,plxv5-bit suffix opcode + TX bit at suffix bit 26) live inSimulator-ppc64.cppsource comments andPLAN.md's engineering-lessons section.WASM SIMD
Full VMX/VSX implementation using PPC64 AltiVec. All 10 tiers — load/store/splat/lane, bitwise, arithmetic, cmp/shift, float, conversions, shuffle/swizzle, extmul/pairwise/dot, relaxed SIMD (FMA/FNMA). NaN semantics correct (min/max propagation, truncSat NaN→zero, promote NaN-quieting). P8 uses
lxvd2x/stxvd2xwith byte-swap; P9 uses nativelxvx/stxvx; P10 collapses the constant-pool variant to a singleplxv.WASM JSPI
WebAssembly.Suspending/WebAssembly.promisingviajavascript.options.wasm_js_promise_integration. Addppc64to the JSPI whitelists injs/moz.configure(both thedefault_wasm_jspisimulator allowlist and thewasm_jspisimulator-guard die-list — extending the original target.cpu enable to cover sim builds too), and roundContRedZoneSizeup to a page-size multiple so the bottom guard page lands on a page boundary under PPC64LE's 64 KiB pages. No arch-specific stack-switch code required.WASM huge memory
4 GB + 32 MB virtual reservation per wasm memory, bounds-check elimination via SIGSEGV → wasm trap. Signal-handler context indices:
gp_regs[32]=NIA,gp_regs[1]=SP,gp_regs[31]=FP,gp_regs[36]=LR.Simulator (ARM64-host)
A full PPC64 simulator is included so CI can run the JIT on non-PPC64 hosts. Both jit-test and jstests sweeps pass under
FORCE_POWER8=1,FORCE_POWER9=1, andFORCE_POWER10=1configurations (zero hard FAIL, zero TIMEOUT). The sim received many ISA-correctness fixes during development (VMX/VSX decoding, LE lane ordering, FP NaN-payload preservation across f32↔f64, ELFv1 FP-arg shadow slots, single-step profiling for tail calls and non-leaf epilogues), and now decodes:addpcis,mods*/modu*,mtvsrws,xxspltib,xxinsertw,xscvdpsp(n)HW-conformance fix,xs{max,min}jdp,xscvdphp/xscvhpdp(FP16),xsxexpdp. Closes the historical "~40 wasm/simd tests fail under FORCE_POWER9 on the sim" coverage gap.paddi/pld/plxv/plfd/plfs), plus the new instruction-count-reduction ops (brd,brh,brw,vinsw,vinsd,vinsbrx,vinshrx,vextract*m,setbc/setbcr,vmulld).setXEROV()fix that mirrors OV→OV32 — the JIT'sbranchMulPtrOverflow path uses POWER9'smcrxrx+bcwhich reads OV32, and the original sim only set OV. Surfaced as silent BigInt fast-path-mul wrap-around inwasm/regress/bug1836708.js.Build
Complete from-scratch walkthrough — little-endian (Debian / Ubuntu / Fedora, ppc64le)
Mozilla's
./mach bootstrapcannot download prebuilt toolchains for ppc64, soeverything comes from your distro plus rustup. These steps take a fresh
ppc64le machine to a running browser. Big-endian Debian has its own section
right after this one.
1. Install build dependencies.
Debian / Ubuntu — let apt resolve the whole Firefox dependency tree, then add
the handful of pieces it misses:
Fedora:
2. Install Rust and cbindgen via rustup. Distro packages are almost
always too old — this tree requires Rust >= 1.90 and cbindgen >= 0.29.4
(node only needs >= 12, any current distro package is fine):
Make sure
~/.cargo/binstays onPATHfor every build shell.3. Clone this repository and branch.
git clone --branch ppc64 https://github.com/runlevel5/firefox-ppc64.git cd firefox-ppc64(For ESR 153 use
--branch esr153-ppc64, see PR #2. Packagers who preferpatch files over a git checkout: apply the numbered patches from
Releases on top of the
matching Mozilla release tarball instead.)
4. Write a
mozconfig. Create a file namedmozconfigin the tree rootwith one of the configurations below (JS shell, full Firefox GCC, or full
Firefox Clang+LTO). Two lines matter on ppc64 no matter which you pick:
5. Build and run.
Hardware/RAM notes: linking
libxul.sowithlldpeaks around 8 GB;16 GB RAM is a comfortable minimum for the full browser (the JS shell builds
on much less). On bigger machines cap parallelism (
mk_add_options MOZ_PARALLEL_BUILD=20) rather than letting mach use every core — widelldlinks can OOM the box.
Troubleshooting:
machfails creating its virtualenv →sudo apt install python3-venv.rustc --version(>= 1.90) and
cbindgen --version(>= 0.29.4); the rustup/cargo copies in~/.cargo/binmust precede any distro copies onPATH.libclang→ installlibclang-dev(Debian) /clang-devel(Fedora) and point--with-libclang-pathat the directorycontaining
libclang.so(llvm-config --libdir).MOZ_PARALLEL_BUILD, ensure the linkeris
lld(--enable-linker=lld), add swap/zram.Complete walkthrough — big-endian Debian (ppc64, ELFv1)
Big-endian Debian is an unofficial port living in
debian-ports(sid only),and the ELFv1 ABI changes the toolchain rules:
lldcannot link ELFv1 atall, and Debian's clang forces
lld— so the build must use GCC with GNUld(bfd) for both target and host. Steps 2, 3 and 5 from thelittle-endian walkthrough apply unchanged (rustup supports big-endian
powerpc64-unknown-linux-gnu); the differences:1. Dependencies. On a debian-ports sid system:
sudo apt update sudo apt build-dep firefox-esr # if firefox-esr is unavailable in ports, use: sudo apt install build-essential git curl ccache python3-venv python3-pip \ pkg-config nasm m4 unzip zip \ libgtk-3-dev libdbus-glib-1-dev libpulse-dev libasound2-dev \ libxt-dev libx11-xcb-dev libpixman-1-dev \ nodejs npm libclang-dev4. mozconfig for big-endian ELFv1:
Big-endian caveats:
bfdneeds substantially more RAM thanlldto linklibxul.so(community reports ~20 GB resident); on smaller machines build the JS shell
(
--enable-application=js), which links fine everywhere.nodejscurrently segfaults on it — see the dedicated Node.jsbootstrap section below for the two workarounds (DevTools-server-only
build, or forwarding
nodeto a little-endian helper host).cargo install cbindgen— the ports archiveversion is too old.
ELFv1 constraint origin — but clang's forced
lldstill applies on Debianderivatives, so GCC +
bfdremains the safe choice on any big-endiansystem.
mozconfig reference
SpiderMonkey (standalone JS shell):
(On the PPC64 box, cap parallelism at
-j20; the auto-detected-j32saturates the box duringlldlinking.)Full Firefox:
Full Firefox with Clang + LTO (ppc64le):
A Clang + ThinLTO build works on ppc64le and is measurably faster on
DOM/layout-heavy workloads than the plain GCC
-O2build. Two things make itwork: Clang with the LLVM linker (
lld), and system NSS — the bundledNSS
ppc-gcm.suses GAS-style semicolon statement separators that Clang'sintegrated assembler rejects, so building against the distro's NSS
(
--with-system-nss) sidesteps that entirely. This is exactly what the Fedorapackage build does.
For RPM packagers: the Fedora spec builds this with
rpmbuild --with build_with_clang --with build_with_lto.Big-endian (ppc64be): Node.js bootstrap
The full browser build runs Node.js at build time to transform the DevTools
debugger modules (
devtools/client/*viamozbuild/action/node.py). NothingNode produces ships in the binary — it is a build-time tool only — but the
build cannot finish without it, and Node on big-endian ppc64 is currently a
problem:
system Node.
nodejsis an unofficial port frozen at 20.19.5 andits
libnodesegfaults during a V8 conservative-stack-scan GC(
heap::base::Stack::IteratePointersImpl) when running the DevToolstransform — an endianness-specific V8/Node bug, unrelated to this port.
Two ways to get past it:
1. Skip the DevTools client (simplest). Set the DevTools build to
serverinstead ofall. This drops the browser-side debugger UI but keepsthe DevTools server (remote debugging still works) and needs no Node:
MOZ_DEVTOOLScannot be set frommozconfig(it is animply_option), sochange
imply_option("MOZ_DEVTOOLS", "all")to"server"inbrowser/moz.configure, or wait for a proper--disable-devtools-style knob.2. Offload Node to a working host (full DevTools). If you have a
little-endian ppc64le box (or any box with a working Node), run only the Node
steps there while the compile stays on the BE machine. Node just reads/writes
files in the source and object trees, so share the tree and forward
node:sshfs) and confirm itsNode runs
devtools/client/shared/build/build.jswithout crashing.nodewrapper first onPATHthatsshes the commandto the helper, rewriting the tree-path prefix (BE mountpoint ↔ helper
mountpoint) in both the arguments and in the
dep:lines Node prints back(the build system consumes those for incremental rebuilds):
Longer term the clean fix is a Node that does not crash on ppc64 BE (e.g.
building Node from source — Arch POWER's
nodejs-lts-ironrecipe builds20.20.0 for
powerpc64with--with-intl=system-icu).Known limitations
--with-system-nss+lld(see the Clang + LTO build recipe above). Only the bundled NSS is a problem — itsppc-gcm.suses GAS-style semicolons that Clang's integrated assembler rejects — so building against the distro NSS avoids it. PGO is still unavailable on ppc64le (GCC ICE / Clang runtime crash); LTO-only.ld.bfd: does linklibxul.sosuccessfully on ppc64le, but needs substantially more RAM during the link than lld (community reports ~20+ GiB resident, putting it out of reach for hosts with under ~24 GiB total). The P10 box uses BFD as a workaround for an LLDR_PPC64_TOC16_HAbug; lld stays the practical default everywhere else for speed.