Skip to content

Commit 725518f

Browse files
aykevldeadprogram
authored andcommitted
all: add linux/mipsle support
This adds linux/mipsle (little endian Mips) support to TinyGo. It also adds experimental linux/mips (big-endian) support. It doesn't quite work yet, some parts of the standard library (like the reflect package) currently seem to assume a little-endian system.
1 parent 04d1261 commit 725518f

23 files changed

+371
-11
lines changed

.github/workflows/build-macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
uses: actions/cache/restore@v4
6969
id: cache-llvm-build
7070
with:
71-
key: llvm-build-18-${{ matrix.os }}-v2
71+
key: llvm-build-18-${{ matrix.os }}-v3
7272
path: llvm-build
7373
- name: Build LLVM
7474
if: steps.cache-llvm-build.outputs.cache-hit != 'true'

.github/workflows/linux.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
uses: actions/cache/restore@v4
6969
id: cache-llvm-build
7070
with:
71-
key: llvm-build-18-linux-alpine-v1
71+
key: llvm-build-18-linux-alpine-v2
7272
path: llvm-build
7373
- name: Build LLVM
7474
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -223,7 +223,7 @@ jobs:
223223
uses: actions/cache/restore@v4
224224
id: cache-llvm-build
225225
with:
226-
key: llvm-build-18-linux-asserts-v1
226+
key: llvm-build-18-linux-asserts-v2
227227
path: llvm-build
228228
- name: Build LLVM
229229
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -336,7 +336,7 @@ jobs:
336336
uses: actions/cache/restore@v4
337337
id: cache-llvm-build
338338
with:
339-
key: llvm-build-18-linux-${{ matrix.goarch }}-v1
339+
key: llvm-build-18-linux-${{ matrix.goarch }}-v2
340340
path: llvm-build
341341
- name: Build LLVM
342342
if: steps.cache-llvm-build.outputs.cache-hit != 'true'

.github/workflows/windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
uses: actions/cache/restore@v4
6767
id: cache-llvm-build
6868
with:
69-
key: llvm-build-18-windows-v1
69+
key: llvm-build-18-windows-v2
7070
path: llvm-build
7171
- name: Build LLVM
7272
if: steps.cache-llvm-build.outputs.cache-hit != 'true'

GNUmakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ llvm-source: $(LLVM_PROJECTDIR)/llvm
245245
# Configure LLVM.
246246
TINYGO_SOURCE_DIR=$(shell pwd)
247247
$(LLVM_BUILDDIR)/build.ninja:
248-
mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR;Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
248+
mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
249249

250250
# Build LLVM.
251251
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
@@ -835,6 +835,7 @@ endif
835835
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0 ./testdata/stdlib.go
836836
@$(MD5SUM) test.hex
837837
GOOS=linux GOARCH=arm $(TINYGO) build -size short -o test.elf ./testdata/cgo
838+
GOOS=linux GOARCH=mips $(TINYGO) build -size short -o test.elf ./testdata/cgo
838839
GOOS=windows GOARCH=amd64 $(TINYGO) build -size short -o test.exe ./testdata/cgo
839840
GOOS=windows GOARCH=arm64 $(TINYGO) build -size short -o test.exe ./testdata/cgo
840841
GOOS=darwin GOARCH=amd64 $(TINYGO) build -size short -o test ./testdata/cgo
@@ -882,6 +883,7 @@ endif
882883
@cp -rp lib/musl/arch/arm build/release/tinygo/lib/musl/arch
883884
@cp -rp lib/musl/arch/generic build/release/tinygo/lib/musl/arch
884885
@cp -rp lib/musl/arch/i386 build/release/tinygo/lib/musl/arch
886+
@cp -rp lib/musl/arch/mips build/release/tinygo/lib/musl/arch
885887
@cp -rp lib/musl/arch/x86_64 build/release/tinygo/lib/musl/arch
886888
@cp -rp lib/musl/crt/crt1.c build/release/tinygo/lib/musl/crt
887889
@cp -rp lib/musl/COPYRIGHT build/release/tinygo/lib/musl

builder/builder_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ func TestClangAttributes(t *testing.T) {
5757
{GOOS: "linux", GOARCH: "arm", GOARM: "6"},
5858
{GOOS: "linux", GOARCH: "arm", GOARM: "7"},
5959
{GOOS: "linux", GOARCH: "arm64"},
60+
{GOOS: "linux", GOARCH: "mips"},
61+
{GOOS: "linux", GOARCH: "mipsle"},
6062
{GOOS: "darwin", GOARCH: "amd64"},
6163
{GOOS: "darwin", GOARCH: "arm64"},
6264
{GOOS: "windows", GOARCH: "amd64"},

builder/library.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
182182
if strings.HasPrefix(target, "riscv64-") {
183183
args = append(args, "-march=rv64gc")
184184
}
185+
if strings.HasPrefix(target, "mips") {
186+
args = append(args, "-fno-pic")
187+
}
185188

186189
var once sync.Once
187190

compileopts/config.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,10 @@ func (c *Config) RP2040BootPatch() bool {
212212
func MuslArchitecture(triple string) string {
213213
arch := strings.Split(triple, "-")[0]
214214
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
215-
arch = "arm"
215+
return "arm"
216+
}
217+
if arch == "mipsel" {
218+
return "mips"
216219
}
217220
return arch
218221
}

compileopts/target.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
193193
default:
194194
return nil, fmt.Errorf("invalid GOARM=%s, must be 5, 6, or 7", options.GOARM)
195195
}
196+
case "mips":
197+
llvmarch = "mips"
198+
case "mipsle":
199+
llvmarch = "mipsel"
196200
case "wasm":
197201
llvmarch = "wasm32"
198202
default:
@@ -327,6 +331,10 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
327331
} else { // linux
328332
spec.Features = "+fp-armv8,+neon,-fmv,-outline-atomics"
329333
}
334+
case "mips", "mipsle":
335+
spec.CPU = "mips32r2"
336+
spec.Features = "+fpxx,+mips32r2,+nooddspreg,-noabicalls"
337+
spec.CFlags = append(spec.CFlags, "-fno-pic")
330338
case "wasm":
331339
spec.CPU = "generic"
332340
spec.Features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext"
@@ -419,8 +427,12 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
419427
// operating systems so we need separate assembly files.
420428
suffix = "_windows"
421429
}
422-
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/asm_"+goarch+suffix+".S")
423-
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_stack_"+goarch+suffix+".S")
430+
asmGoarch := goarch
431+
if goarch == "mips" || goarch == "mipsle" {
432+
asmGoarch = "mipsx"
433+
}
434+
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/asm_"+asmGoarch+suffix+".S")
435+
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_stack_"+asmGoarch+suffix+".S")
424436
}
425437
if goarch != runtime.GOARCH {
426438
// Some educated guesses as to how to invoke helper programs.
@@ -438,6 +450,10 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
438450
spec.Emulator = "qemu-arm {}"
439451
case "arm64":
440452
spec.Emulator = "qemu-aarch64 {}"
453+
case "mips":
454+
spec.Emulator = "qemu-mips {}"
455+
case "mipsle":
456+
spec.Emulator = "qemu-mipsel {}"
441457
}
442458
}
443459
}

compiler/defer.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ std z+5, r29
187187
ldi r24, 0
188188
1:`
189189
constraints = "={r24},z,~{r0},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r25},~{r26},~{r27}"
190+
case "mips":
191+
// $4 flag (zero or non-zero)
192+
// $5 defer frame
193+
asmString = `
194+
.set noat
195+
move $$4, $$zero
196+
jal 1f
197+
1:
198+
addiu $$ra, 8
199+
sw $$ra, 4($$5)
200+
.set at`
201+
constraints = "={$4},{$5},~{$1},~{$2},~{$3},~{$5},~{$6},~{$7},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$16},~{$17},~{$18},~{$19},~{$20},~{$21},~{$22},~{$23},~{$24},~{$25},~{$26},~{$27},~{$28},~{$29},~{$30},~{$31},~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f12},~{$f13},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31},~{memory}"
190202
case "riscv32":
191203
asmString = `
192204
la a2, 1f

compiler/llvm.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ func (c *compilerContext) archFamily() string {
429429
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
430430
return "arm"
431431
}
432+
if arch == "mipsel" {
433+
return "mips"
434+
}
432435
return arch
433436
}
434437

0 commit comments

Comments
 (0)