Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cc3ec22

Browse files
committedSep 14, 2020
main: add initial support for (in-development) LLVM 11
This can be useful to test improvements in LLVM master and to make it possible to support LLVM 11 for the most part already before the next release. That also allows catching LLVM bugs early to fix them upstream. Note that tests do not yet pass for this LLVM version, but the TinyGo compiler can be built with the binaries from apt.llvm.org (at the time of making this commit).
1 parent 5b81b83 commit cc3ec22

11 files changed

+86
-15
lines changed
 

‎.circleci/config.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,12 @@ jobs:
413413
steps:
414414
- test-linux:
415415
llvm: "10"
416-
test-llvm10-go115:
416+
test-llvm11-go115:
417417
docker:
418418
- image: circleci/golang:1.15-buster
419419
steps:
420420
- test-linux:
421-
llvm: "10"
421+
llvm: "11"
422422
assert-test-linux:
423423
docker:
424424
- image: circleci/golang:1.14-stretch
@@ -450,7 +450,7 @@ workflows:
450450
- test-llvm10-go112
451451
- test-llvm10-go113
452452
- test-llvm10-go114
453-
- test-llvm10-go115
453+
- test-llvm11-go115
454454
- build-linux
455455
- build-macos
456456
- assert-test-linux

‎builder/build.go

+11
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
129129
}
130130
}
131131

132+
// LLVM 11 by default tries to emit tail calls (even with the target feature
133+
// disabled) unless it is explicitly disabled with a function attribute.
134+
// This is a problem, as it tries to emit them and prints an error when it
135+
// can't with this feature disabled.
136+
// Because as of september 2020 tail calls are not yet widely supported,
137+
// they need to be disabled until they are widely supported (at which point
138+
// the +tail-call target feautre can be set).
139+
if strings.HasPrefix(config.Triple(), "wasm") {
140+
transform.DisableTailCalls(mod)
141+
}
142+
132143
// Make sure stack sizes are loaded from a separate section so they can be
133144
// modified after linking.
134145
var stackSizeLoads []string

‎builder/objcopy.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func extractROM(path string) (uint64, []byte, error) {
5757

5858
progs := make(progSlice, 0, 2)
5959
for _, prog := range f.Progs {
60-
if prog.Type != elf.PT_LOAD || prog.Filesz == 0 {
60+
if prog.Type != elf.PT_LOAD || prog.Filesz == 0 || prog.Off == 0 {
6161
continue
6262
}
6363
progs = append(progs, prog)
@@ -69,6 +69,12 @@ func extractROM(path string) (uint64, []byte, error) {
6969

7070
var rom []byte
7171
for _, prog := range progs {
72+
romEnd := progs[0].Paddr + uint64(len(rom))
73+
if prog.Paddr > romEnd && prog.Paddr < romEnd+16 {
74+
// Sometimes, the linker seems to insert a bit of padding between
75+
// segments. Simply zero-fill these parts.
76+
rom = append(rom, make([]byte, prog.Paddr-romEnd)...)
77+
}
7278
if prog.Paddr != progs[0].Paddr+uint64(len(rom)) {
7379
return 0, nil, objcopyError{"ROM segments are non-contiguous: " + path, nil}
7480
}

‎cgo/libclang_config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// +build !byollvm
2-
// +build !llvm9
2+
// +build !llvm9,!llvm11
33

44
package cgo
55

‎cgo/libclang_config_llvm11.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// +build !byollvm
2+
// +build llvm11
3+
4+
package cgo
5+
6+
/*
7+
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
8+
#cgo darwin CFLAGS: -I/usr/local/opt/llvm@11/include
9+
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
10+
#cgo linux LDFLAGS: -L/usr/lib/llvm-11/lib -lclang
11+
#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@11/lib -lclang -lffi
12+
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
13+
*/
14+
import "C"

‎go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ require (
1010
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
1111
go.bug.st/serial v1.0.0
1212
golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2
13-
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d
13+
tinygo.org/x/go-llvm v0.0.0-20200503224449-70c558526021
1414
)

‎go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbO
4646
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4747
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4848
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
49-
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d h1:hcX7vpB067GWM/EH4sGGOti0PMgIx+0bbZwUXctOIvE=
50-
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE=
49+
tinygo.org/x/go-llvm v0.0.0-20200503224449-70c558526021 h1:d8T98WXGjrTgDmMXgxa6nb9EAYXGXwnzXygnJl6d+ac=
50+
tinygo.org/x/go-llvm v0.0.0-20200503224449-70c558526021/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE=

‎interp/interp_test.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package interp
33
import (
44
"io/ioutil"
55
"os"
6+
"regexp"
67
"strings"
78
"testing"
89

@@ -66,6 +67,8 @@ func runTest(t *testing.T, pathPrefix string) {
6667
}
6768
}
6869

70+
var alignRegexp = regexp.MustCompile(", align [0-9]+$")
71+
6972
// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly
7073
// equal. That means, only relevant lines are compared (excluding comments
7174
// etc.).
@@ -75,8 +78,18 @@ func fuzzyEqualIR(s1, s2 string) bool {
7578
if len(lines1) != len(lines2) {
7679
return false
7780
}
78-
for i, line := range lines1 {
79-
if line != lines2[i] {
81+
for i, line1 := range lines1 {
82+
line2 := lines2[i]
83+
match1 := alignRegexp.MatchString(line1)
84+
match2 := alignRegexp.MatchString(line2)
85+
if match1 != match2 {
86+
// Only one of the lines has the align keyword. Remove it.
87+
// This is a change to make the test work in both LLVM 10 and LLVM
88+
// 11 (LLVM 11 appears to automatically add alignment everywhere).
89+
line1 = alignRegexp.ReplaceAllString(line1, "")
90+
line2 = alignRegexp.ReplaceAllString(line2, "")
91+
}
92+
if line1 != line2 {
8093
return false
8194
}
8295
}

‎targets/gameboy-advance.ld

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ SECTIONS
1919
{
2020
KEEP (*(.init))
2121
*(.text)
22+
*(.text.*)
2223
. = ALIGN(4);
2324
} >rom
2425

2526
.rodata :
2627
{
2728
. = ALIGN(4);
2829
*(.rodata)
29-
*(.rodata*)
30+
*(.rodata.*)
3031
. = ALIGN(4);
3132
} >rom
3233

@@ -51,7 +52,7 @@ SECTIONS
5152
. = ALIGN(4);
5253
_sdata = .; /* used by startup code */
5354
*(.data)
54-
*(.data*)
55+
*(.data.*)
5556
*(.iwram .iwram.*)
5657
. = ALIGN(4);
5758
_edata = .; /* used by startup code */
@@ -63,7 +64,7 @@ SECTIONS
6364
. = ALIGN(4);
6465
_sbss = .; /* used by startup code */
6566
*(.bss)
66-
*(.bss*)
67+
*(.bss.*)
6768
*(COMMON)
6869
. = ALIGN(4);
6970
_ebss = .; /* used by startup code */

‎transform/globals.go

+14
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,17 @@ func NonConstGlobals(mod llvm.Module) {
3131
global = llvm.NextGlobal(global)
3232
}
3333
}
34+
35+
// DisableTailCalls adds the "disable-tail-calls"="true" function attribute to
36+
// all functions. This may be necessary, in particular to avoid an error with
37+
// WebAssembly in LLVM 11.
38+
func DisableTailCalls(mod llvm.Module) {
39+
attribute := mod.Context().CreateStringAttribute("disable-tail-calls", "true")
40+
llvmFn := mod.FirstFunction()
41+
for !llvmFn.IsNil() {
42+
if !llvmFn.IsDeclaration() {
43+
llvmFn.AddFunctionAttr(attribute)
44+
}
45+
llvmFn = llvm.NextFunction(llvmFn)
46+
}
47+
}

‎transform/transform_test.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
6161
}
6262
}
6363

64+
var alignRegexp = regexp.MustCompile(", align [0-9]+$")
65+
6466
// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly
6567
// equal. That means, only relevant lines are compared (excluding comments
6668
// etc.).
@@ -70,8 +72,18 @@ func fuzzyEqualIR(s1, s2 string) bool {
7072
if len(lines1) != len(lines2) {
7173
return false
7274
}
73-
for i, line := range lines1 {
74-
if line != lines2[i] {
75+
for i, line1 := range lines1 {
76+
line2 := lines2[i]
77+
match1 := alignRegexp.MatchString(line1)
78+
match2 := alignRegexp.MatchString(line2)
79+
if match1 != match2 {
80+
// Only one of the lines has the align keyword. Remove it.
81+
// This is a change to make the test work in both LLVM 10 and LLVM
82+
// 11 (LLVM 11 appears to automatically add alignment everywhere).
83+
line1 = alignRegexp.ReplaceAllString(line1, "")
84+
line2 = alignRegexp.ReplaceAllString(line2, "")
85+
}
86+
if line1 != line2 {
7587
return false
7688
}
7789
}

0 commit comments

Comments
 (0)
Please sign in to comment.