Cross-Compilation of GNU Octave
One of the complications of cross-compiling Octave to WebAssembly, which had not been encountered with the R source code, was the extensive use of Fortran common symbols blocks in the internal libraries of Octave such as odepack.
C Source: liboctave/external/odepack/slsode.f
C-----------------------------------------------------------------------
C The following internal Common block contains
C (a) variables which are local to any subroutine but whose values must
C be preserved between calls to the routine ("own" variables), and
C (b) variables which are communicated between subroutines.
C The block SLS001 is declared in subroutines SLSODE, SINTDY, SSTODE,
C SPREPJ, and SSOLSY.
C Groups of variables are replaced by dummy arrays in the Common
C declarations in routines where those variables are not used.
C-----------------------------------------------------------------------
COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),
1 HOLD, RMAX, TESCO(3,12),
1 CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,
2 INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, NYH,
3 IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,
3 ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,
4 LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,
5 MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU
Initially, it was not possible to cross-compile these common blocks to WebAssembly because the latest version of LLVM (v20 at the time of testing) did not support common symbol linkage.
// Source: llvm/lib/MC/MCWasmStreamer.cpp
void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
Align ByteAlignment) {
llvm_unreachable("Common symbols are not yet implemented for Wasm");
}
As a temporary solution, LLVM was patched with the help of Serge Guelton to simulate common symbols as weak symbols.
void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
Align ByteAlignment) {
- llvm_unreachable("Common symbols are not yet implemented for Wasm");
+ auto *Symbol = cast(S);
+ getAssembler().registerSymbol(*Symbol);
+ Symbol->setWeak(true);
+ Symbol->setExternal(true);
}
A proper solution to enable support of common symbols is currently in progress and will likely be included in the next release of LLVM v22 (see llvm-project/pull/151478). For curious readers, the patched version of LLVM can be found here (linux only).
In addition to the patches for LLVM, GNU Octave required a few minor modifications to target WebAssembly; mainly this entailed disabling the GUI functionalities and consolidating the Fortran function signatures and calling conventions. A full list of patches can be found in the recipe directory on emscripten-forge.