Compare commits
2 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db2de4ca7d | ||
|
|
47ec68f853 |
8 changed files with 937 additions and 4 deletions
|
|
@ -1,7 +1,7 @@
|
|||
From ee856392109e39cf60e83022441c94adee205447 Mon Sep 17 00:00:00 2001
|
||||
From: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
Date: Tue, 15 Dec 2020 05:06:04 -0500
|
||||
Subject: [PATCH 1/3] Skip WASI tests.
|
||||
Subject: [PATCH 1/7] Skip WASI tests.
|
||||
|
||||
We do not have wasmtime available.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
From 1f60829a1fffdcbe268c1998a560fdeb6029407e Mon Sep 17 00:00:00 2001
|
||||
From: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
Date: Mon, 3 Jan 2022 22:39:31 -0500
|
||||
Subject: [PATCH 2/3] Skip some cross Linux tests where qemu is broken
|
||||
Subject: [PATCH 2/7] Skip some cross Linux tests where qemu is broken
|
||||
|
||||
The upstream issues will hopefully be fixed soon:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
From 3f6a6f241ab37976f07e792986b5c47fdde20c8a Mon Sep 17 00:00:00 2001
|
||||
From: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
Date: Sun, 6 Feb 2022 03:49:16 -0500
|
||||
Subject: [PATCH 3/3] Suggest optional packages to install if missing
|
||||
Subject: [PATCH 3/7] Suggest optional packages to install if missing
|
||||
|
||||
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
---
|
||||
|
|
|
|||
121
0004-transform-fix-bug-in-StringToBytes-optimization-pass.patch
Normal file
121
0004-transform-fix-bug-in-StringToBytes-optimization-pass.patch
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
From bf51015656ff3b1bbe6b41ea1155610178c2961d Mon Sep 17 00:00:00 2001
|
||||
From: Ayke van Laethem <aykevanlaethem@gmail.com>
|
||||
Date: Thu, 21 Sep 2023 15:39:06 +0200
|
||||
Subject: [PATCH 4/7] transform: fix bug in StringToBytes optimization pass
|
||||
|
||||
Previously, this pass would convert any read-only use of a
|
||||
runtime.stringToBytes call to use the original string buffer instead.
|
||||
This is incorrect: if there are any writes to the resulting buffer, none
|
||||
of the slice buffer pointers can be converted to use the original
|
||||
read-only string buffer.
|
||||
|
||||
This commit fixes that bug and adds a test to prove the new (correct)
|
||||
behavior.
|
||||
|
||||
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
---
|
||||
transform/rtcalls.go | 24 ++++++++++++++++++------
|
||||
transform/testdata/stringtobytes.ll | 16 ++++++++++++++++
|
||||
transform/testdata/stringtobytes.out.ll | 10 ++++++++++
|
||||
3 files changed, 44 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/transform/rtcalls.go b/transform/rtcalls.go
|
||||
index 36d2853b..0b6feff2 100644
|
||||
--- a/transform/rtcalls.go
|
||||
+++ b/transform/rtcalls.go
|
||||
@@ -28,32 +28,44 @@ func OptimizeStringToBytes(mod llvm.Module) {
|
||||
|
||||
// strptr is always constant because strings are always constant.
|
||||
|
||||
- convertedAllUses := true
|
||||
+ var pointerUses []llvm.Value
|
||||
+ canConvertPointer := true
|
||||
for _, use := range getUses(call) {
|
||||
if use.IsAExtractValueInst().IsNil() {
|
||||
// Expected an extractvalue, but this is something else.
|
||||
- convertedAllUses = false
|
||||
+ canConvertPointer = false
|
||||
continue
|
||||
}
|
||||
switch use.Type().TypeKind() {
|
||||
case llvm.IntegerTypeKind:
|
||||
// A length (len or cap). Propagate the length value.
|
||||
+ // This can always be done because the byte slice is always the
|
||||
+ // same length as the original string.
|
||||
use.ReplaceAllUsesWith(strlen)
|
||||
use.EraseFromParentAsInstruction()
|
||||
case llvm.PointerTypeKind:
|
||||
// The string pointer itself.
|
||||
if !isReadOnly(use) {
|
||||
- convertedAllUses = false
|
||||
+ // There is a store to the byte slice. This means that none
|
||||
+ // of the pointer uses can't be propagated.
|
||||
+ canConvertPointer = false
|
||||
continue
|
||||
}
|
||||
- use.ReplaceAllUsesWith(strptr)
|
||||
- use.EraseFromParentAsInstruction()
|
||||
+ // It may be that the pointer value can be propagated, if all of
|
||||
+ // the pointer uses are readonly.
|
||||
+ pointerUses = append(pointerUses, use)
|
||||
default:
|
||||
// should not happen
|
||||
panic("unknown return type of runtime.stringToBytes: " + use.Type().String())
|
||||
}
|
||||
}
|
||||
- if convertedAllUses {
|
||||
+ if canConvertPointer {
|
||||
+ // All pointer uses are readonly, so they can be converted.
|
||||
+ for _, use := range pointerUses {
|
||||
+ use.ReplaceAllUsesWith(strptr)
|
||||
+ use.EraseFromParentAsInstruction()
|
||||
+ }
|
||||
+
|
||||
// Call to runtime.stringToBytes can be eliminated: both the input
|
||||
// and the output is constant.
|
||||
call.EraseFromParentAsInstruction()
|
||||
diff --git a/transform/testdata/stringtobytes.ll b/transform/testdata/stringtobytes.ll
|
||||
index fa43f3d0..06373a51 100644
|
||||
--- a/transform/testdata/stringtobytes.ll
|
||||
+++ b/transform/testdata/stringtobytes.ll
|
||||
@@ -30,3 +30,19 @@ entry:
|
||||
call fastcc void @writeToSlice(ptr %1, i64 %2, i64 %3)
|
||||
ret void
|
||||
}
|
||||
+
|
||||
+; Test that pointer values are never propagated if there is even a single write
|
||||
+; to the pointer value (but len/cap values still can be).
|
||||
+define void @testReadSome() {
|
||||
+entry:
|
||||
+ %s = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)
|
||||
+ %s.ptr = extractvalue { ptr, i64, i64 } %s, 0
|
||||
+ %s.len = extractvalue { ptr, i64, i64 } %s, 1
|
||||
+ %s.cap = extractvalue { ptr, i64, i64 } %s, 2
|
||||
+ call fastcc void @writeToSlice(ptr %s.ptr, i64 %s.len, i64 %s.cap)
|
||||
+ %s.ptr2 = extractvalue { ptr, i64, i64 } %s, 0
|
||||
+ %s.len2 = extractvalue { ptr, i64, i64 } %s, 1
|
||||
+ %s.cap2 = extractvalue { ptr, i64, i64 } %s, 2
|
||||
+ call fastcc void @printSlice(ptr %s.ptr2, i64 %s.len2, i64 %s.cap2)
|
||||
+ ret void
|
||||
+}
|
||||
diff --git a/transform/testdata/stringtobytes.out.ll b/transform/testdata/stringtobytes.out.ll
|
||||
index 30aa520a..b33a1755 100644
|
||||
--- a/transform/testdata/stringtobytes.out.ll
|
||||
+++ b/transform/testdata/stringtobytes.out.ll
|
||||
@@ -22,3 +22,13 @@ entry:
|
||||
call fastcc void @writeToSlice(ptr %1, i64 6, i64 6)
|
||||
ret void
|
||||
}
|
||||
+
|
||||
+define void @testReadSome() {
|
||||
+entry:
|
||||
+ %s = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)
|
||||
+ %s.ptr = extractvalue { ptr, i64, i64 } %s, 0
|
||||
+ call fastcc void @writeToSlice(ptr %s.ptr, i64 6, i64 6)
|
||||
+ %s.ptr2 = extractvalue { ptr, i64, i64 } %s, 0
|
||||
+ call fastcc void @printSlice(ptr %s.ptr2, i64 6, i64 6)
|
||||
+ ret void
|
||||
+}
|
||||
--
|
||||
2.41.0
|
||||
|
||||
424
0005-all-use-the-new-LLVM-pass-manager.patch
Normal file
424
0005-all-use-the-new-LLVM-pass-manager.patch
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
From 3dcb55f940011bb9bcb75d98182290da60642e4d Mon Sep 17 00:00:00 2001
|
||||
From: Ayke van Laethem <aykevanlaethem@gmail.com>
|
||||
Date: Tue, 19 Sep 2023 22:37:44 +0200
|
||||
Subject: [PATCH 5/7] all: use the new LLVM pass manager
|
||||
|
||||
The old LLVM pass manager is deprecated and should not be used anymore.
|
||||
Moreover, the pass manager builder (which we used to set up a pass
|
||||
pipeline) is actually removed from LLVM entirely in LLVM 17:
|
||||
https://reviews.llvm.org/D145387
|
||||
https://reviews.llvm.org/D145835
|
||||
|
||||
The new pass manager does change the binary size in many cases: both
|
||||
growing and shrinking it. However, on average the binary size remains
|
||||
more or less the same.
|
||||
|
||||
This is needed as a preparation for LLVM 17.
|
||||
|
||||
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
---
|
||||
builder/build.go | 19 +++--
|
||||
builder/sizes_test.go | 6 +-
|
||||
compileopts/config.go | 12 ++--
|
||||
compiler/compiler_test.go | 12 ++--
|
||||
interp/interp_test.go | 9 +--
|
||||
transform/allocs_test.go | 11 +--
|
||||
transform/interface-lowering_test.go | 10 +--
|
||||
transform/maps_test.go | 11 +--
|
||||
transform/optimizer.go | 102 +++++++++------------------
|
||||
transform/transform.go | 2 +-
|
||||
10 files changed, 76 insertions(+), 118 deletions(-)
|
||||
|
||||
diff --git a/builder/build.go b/builder/build.go
|
||||
index dc360b92..d920a598 100644
|
||||
--- a/builder/build.go
|
||||
+++ b/builder/build.go
|
||||
@@ -83,8 +83,7 @@ type packageAction struct {
|
||||
FileHashes map[string]string // hash of every file that's part of the package
|
||||
EmbeddedFiles map[string]string // hash of all the //go:embed files in the package
|
||||
Imports map[string]string // map from imported package to action ID hash
|
||||
- OptLevel int // LLVM optimization level (0-3)
|
||||
- SizeLevel int // LLVM optimization for size level (0-2)
|
||||
+ OptLevel string // LLVM optimization level (O0, O1, O2, Os, Oz)
|
||||
UndefinedGlobals []string // globals that are left as external globals (no initializer)
|
||||
}
|
||||
|
||||
@@ -158,7 +157,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
return BuildResult{}, fmt.Errorf("unknown libc: %s", config.Target.Libc)
|
||||
}
|
||||
|
||||
- optLevel, sizeLevel, _ := config.OptLevels()
|
||||
+ optLevel, speedLevel, sizeLevel := config.OptLevel()
|
||||
compilerConfig := &compiler.Config{
|
||||
Triple: config.Triple(),
|
||||
CPU: config.CPU(),
|
||||
@@ -321,7 +320,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
EmbeddedFiles: make(map[string]string, len(allFiles)),
|
||||
Imports: make(map[string]string, len(pkg.Pkg.Imports())),
|
||||
OptLevel: optLevel,
|
||||
- SizeLevel: sizeLevel,
|
||||
UndefinedGlobals: undefinedGlobals,
|
||||
}
|
||||
for filePath, hash := range pkg.FileHashes {
|
||||
@@ -743,17 +741,17 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
if config.GOOS() == "windows" {
|
||||
// Options for the MinGW wrapper for the lld COFF linker.
|
||||
ldflags = append(ldflags,
|
||||
- "-Xlink=/opt:lldlto="+strconv.Itoa(optLevel),
|
||||
+ "-Xlink=/opt:lldlto="+strconv.Itoa(speedLevel),
|
||||
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"))
|
||||
} else if config.GOOS() == "darwin" {
|
||||
// Options for the ld64-compatible lld linker.
|
||||
ldflags = append(ldflags,
|
||||
- "--lto-O"+strconv.Itoa(optLevel),
|
||||
+ "--lto-O"+strconv.Itoa(speedLevel),
|
||||
"-cache_path_lto", filepath.Join(cacheDir, "thinlto"))
|
||||
} else {
|
||||
// Options for the ELF linker.
|
||||
ldflags = append(ldflags,
|
||||
- "--lto-O"+strconv.Itoa(optLevel),
|
||||
+ "--lto-O"+strconv.Itoa(speedLevel),
|
||||
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"),
|
||||
)
|
||||
}
|
||||
@@ -1066,10 +1064,9 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
- // Optimization levels here are roughly the same as Clang, but probably not
|
||||
- // exactly.
|
||||
- optLevel, sizeLevel, inlinerThreshold := config.OptLevels()
|
||||
- errs := transform.Optimize(mod, config, optLevel, sizeLevel, inlinerThreshold)
|
||||
+ // Run most of the whole-program optimizations (including the whole
|
||||
+ // O0/O1/O2/Os/Oz optimization pipeline).
|
||||
+ errs := transform.Optimize(mod, config)
|
||||
if len(errs) > 0 {
|
||||
return newMultiError(errs)
|
||||
}
|
||||
diff --git a/builder/sizes_test.go b/builder/sizes_test.go
|
||||
index 7aaab78a..dc45898e 100644
|
||||
--- a/builder/sizes_test.go
|
||||
+++ b/builder/sizes_test.go
|
||||
@@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
|
||||
// This is a small number of very diverse targets that we want to test.
|
||||
tests := []sizeTest{
|
||||
// microcontrollers
|
||||
- {"hifive1b", "examples/echo", 4568, 280, 0, 2252},
|
||||
- {"microbit", "examples/serial", 2728, 388, 8, 2256},
|
||||
- {"wioterminal", "examples/pininterrupt", 5996, 1484, 116, 6816},
|
||||
+ {"hifive1b", "examples/echo", 4484, 280, 0, 2252},
|
||||
+ {"microbit", "examples/serial", 2724, 388, 8, 2256},
|
||||
+ {"wioterminal", "examples/pininterrupt", 6000, 1484, 116, 6816},
|
||||
|
||||
// TODO: also check wasm. Right now this is difficult, because
|
||||
// wasm binaries are run through wasm-opt and therefore the
|
||||
diff --git a/compileopts/config.go b/compileopts/config.go
|
||||
index 39fc4f2a..5ad45c60 100644
|
||||
--- a/compileopts/config.go
|
||||
+++ b/compileopts/config.go
|
||||
@@ -145,18 +145,18 @@ func (c *Config) Serial() string {
|
||||
|
||||
// OptLevels returns the optimization level (0-2), size level (0-2), and inliner
|
||||
// threshold as used in the LLVM optimization pipeline.
|
||||
-func (c *Config) OptLevels() (optLevel, sizeLevel int, inlinerThreshold uint) {
|
||||
+func (c *Config) OptLevel() (level string, speedLevel, sizeLevel int) {
|
||||
switch c.Options.Opt {
|
||||
case "none", "0":
|
||||
- return 0, 0, 0 // -O0
|
||||
+ return "O0", 0, 0
|
||||
case "1":
|
||||
- return 1, 0, 0 // -O1
|
||||
+ return "O1", 1, 0
|
||||
case "2":
|
||||
- return 2, 0, 225 // -O2
|
||||
+ return "O2", 2, 0
|
||||
case "s":
|
||||
- return 2, 1, 225 // -Os
|
||||
+ return "Os", 2, 1
|
||||
case "z":
|
||||
- return 2, 2, 5 // -Oz, default
|
||||
+ return "Oz", 2, 2 // default
|
||||
default:
|
||||
// This is not shown to the user: valid choices are already checked as
|
||||
// part of Options.Verify(). It is here as a sanity check.
|
||||
diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go
|
||||
index 92ce31b0..147e622a 100644
|
||||
--- a/compiler/compiler_test.go
|
||||
+++ b/compiler/compiler_test.go
|
||||
@@ -91,14 +91,12 @@ func TestCompiler(t *testing.T) {
|
||||
}
|
||||
|
||||
// Optimize IR a little.
|
||||
- funcPasses := llvm.NewFunctionPassManagerForModule(mod)
|
||||
- defer funcPasses.Dispose()
|
||||
- funcPasses.AddInstructionCombiningPass()
|
||||
- funcPasses.InitializeFunc()
|
||||
- for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
|
||||
- funcPasses.RunFunc(fn)
|
||||
+ passOptions := llvm.NewPassBuilderOptions()
|
||||
+ defer passOptions.Dispose()
|
||||
+ err = mod.RunPasses("instcombine", llvm.TargetMachine{}, passOptions)
|
||||
+ if err != nil {
|
||||
+ t.Error(err)
|
||||
}
|
||||
- funcPasses.FinalizeFunc()
|
||||
|
||||
outFilePrefix := tc.file[:len(tc.file)-3]
|
||||
if tc.target != "" {
|
||||
diff --git a/interp/interp_test.go b/interp/interp_test.go
|
||||
index fc567af2..cac56508 100644
|
||||
--- a/interp/interp_test.go
|
||||
+++ b/interp/interp_test.go
|
||||
@@ -77,12 +77,9 @@ func runTest(t *testing.T, pathPrefix string) {
|
||||
}
|
||||
|
||||
// Run some cleanup passes to get easy-to-read outputs.
|
||||
- pm := llvm.NewPassManager()
|
||||
- defer pm.Dispose()
|
||||
- pm.AddGlobalOptimizerPass()
|
||||
- pm.AddDeadStoreEliminationPass()
|
||||
- pm.AddAggressiveDCEPass()
|
||||
- pm.Run(mod)
|
||||
+ to := llvm.NewPassBuilderOptions()
|
||||
+ defer to.Dispose()
|
||||
+ mod.RunPasses("globalopt,dse,adce", llvm.TargetMachine{}, to)
|
||||
|
||||
// Read the expected output IR.
|
||||
out, err := os.ReadFile(pathPrefix + ".out.ll")
|
||||
diff --git a/transform/allocs_test.go b/transform/allocs_test.go
|
||||
index 27bb9706..59a5b14e 100644
|
||||
--- a/transform/allocs_test.go
|
||||
+++ b/transform/allocs_test.go
|
||||
@@ -38,11 +38,12 @@ func TestAllocs2(t *testing.T) {
|
||||
mod := compileGoFileForTesting(t, "./testdata/allocs2.go")
|
||||
|
||||
// Run functionattrs pass, which is necessary for escape analysis.
|
||||
- pm := llvm.NewPassManager()
|
||||
- defer pm.Dispose()
|
||||
- pm.AddInstructionCombiningPass()
|
||||
- pm.AddFunctionAttrsPass()
|
||||
- pm.Run(mod)
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ err := mod.RunPasses("function(instcombine),function-attrs", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ t.Error("failed to run passes:", err)
|
||||
+ }
|
||||
|
||||
// Run heap to stack transform.
|
||||
var testOutputs []allocsTestOutput
|
||||
diff --git a/transform/interface-lowering_test.go b/transform/interface-lowering_test.go
|
||||
index 7bcce605..65f14dd9 100644
|
||||
--- a/transform/interface-lowering_test.go
|
||||
+++ b/transform/interface-lowering_test.go
|
||||
@@ -15,9 +15,11 @@ func TestInterfaceLowering(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
- pm := llvm.NewPassManager()
|
||||
- defer pm.Dispose()
|
||||
- pm.AddGlobalDCEPass()
|
||||
- pm.Run(mod)
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ err = mod.RunPasses("globaldce", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ t.Error("failed to run passes:", err)
|
||||
+ }
|
||||
})
|
||||
}
|
||||
diff --git a/transform/maps_test.go b/transform/maps_test.go
|
||||
index e8b11133..329de698 100644
|
||||
--- a/transform/maps_test.go
|
||||
+++ b/transform/maps_test.go
|
||||
@@ -15,10 +15,11 @@ func TestOptimizeMaps(t *testing.T) {
|
||||
|
||||
// Run an optimization pass, to clean up the result.
|
||||
// This shows that all code related to the map is really eliminated.
|
||||
- pm := llvm.NewPassManager()
|
||||
- defer pm.Dispose()
|
||||
- pm.AddDeadStoreEliminationPass()
|
||||
- pm.AddAggressiveDCEPass()
|
||||
- pm.Run(mod)
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ err := mod.RunPasses("dse,adce", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ t.Error("failed to run passes:", err)
|
||||
+ }
|
||||
})
|
||||
}
|
||||
diff --git a/transform/optimizer.go b/transform/optimizer.go
|
||||
index 20258ef4..42acc2dd 100644
|
||||
--- a/transform/optimizer.go
|
||||
+++ b/transform/optimizer.go
|
||||
@@ -14,54 +14,22 @@ import (
|
||||
// OptimizePackage runs optimization passes over the LLVM module for the given
|
||||
// Go package.
|
||||
func OptimizePackage(mod llvm.Module, config *compileopts.Config) {
|
||||
- optLevel, sizeLevel, _ := config.OptLevels()
|
||||
-
|
||||
- // Run function passes for each function in the module.
|
||||
- // These passes are intended to be run on each function right
|
||||
- // after they're created to reduce IR size (and maybe also for
|
||||
- // cache locality to improve performance), but for now they're
|
||||
- // run here for each function in turn. Maybe this can be
|
||||
- // improved in the future.
|
||||
- builder := llvm.NewPassManagerBuilder()
|
||||
- defer builder.Dispose()
|
||||
- builder.SetOptLevel(optLevel)
|
||||
- builder.SetSizeLevel(sizeLevel)
|
||||
- funcPasses := llvm.NewFunctionPassManagerForModule(mod)
|
||||
- defer funcPasses.Dispose()
|
||||
- builder.PopulateFunc(funcPasses)
|
||||
- funcPasses.InitializeFunc()
|
||||
- for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
|
||||
- if fn.IsDeclaration() {
|
||||
- continue
|
||||
- }
|
||||
- funcPasses.RunFunc(fn)
|
||||
- }
|
||||
- funcPasses.FinalizeFunc()
|
||||
+ _, speedLevel, _ := config.OptLevel()
|
||||
|
||||
// Run TinyGo-specific optimization passes.
|
||||
- if optLevel > 0 {
|
||||
+ if speedLevel > 0 {
|
||||
OptimizeMaps(mod)
|
||||
}
|
||||
}
|
||||
|
||||
// Optimize runs a number of optimization and transformation passes over the
|
||||
// given module. Some passes are specific to TinyGo, others are generic LLVM
|
||||
-// passes. You can set a preferred performance (0-3) and size (0-2) level and
|
||||
-// control the limits of the inliner (higher numbers mean more inlining, set it
|
||||
-// to 0 to disable entirely).
|
||||
+// passes.
|
||||
//
|
||||
// Please note that some optimizations are not optional, thus Optimize must
|
||||
-// alwasy be run before emitting machine code. Set all controls (optLevel,
|
||||
-// sizeLevel, inlinerThreshold) to 0 to reduce the number of optimizations to a
|
||||
-// minimum.
|
||||
-func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel int, inlinerThreshold uint) []error {
|
||||
- builder := llvm.NewPassManagerBuilder()
|
||||
- defer builder.Dispose()
|
||||
- builder.SetOptLevel(optLevel)
|
||||
- builder.SetSizeLevel(sizeLevel)
|
||||
- if inlinerThreshold != 0 {
|
||||
- builder.UseInlinerWithThreshold(inlinerThreshold)
|
||||
- }
|
||||
+// alwasy be run before emitting machine code.
|
||||
+func Optimize(mod llvm.Module, config *compileopts.Config) []error {
|
||||
+ optLevel, speedLevel, _ := config.OptLevel()
|
||||
|
||||
// Make sure these functions are kept in tact during TinyGo transformation passes.
|
||||
for _, name := range functionsUsedInTransforms {
|
||||
@@ -84,23 +52,20 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i
|
||||
}
|
||||
}
|
||||
|
||||
- if optLevel > 0 {
|
||||
+ if speedLevel > 0 {
|
||||
// Run some preparatory passes for the Go optimizer.
|
||||
- goPasses := llvm.NewPassManager()
|
||||
- defer goPasses.Dispose()
|
||||
- goPasses.AddGlobalDCEPass()
|
||||
- goPasses.AddGlobalOptimizerPass()
|
||||
- goPasses.AddIPSCCPPass()
|
||||
- goPasses.AddInstructionCombiningPass() // necessary for OptimizeReflectImplements
|
||||
- goPasses.AddAggressiveDCEPass()
|
||||
- goPasses.AddFunctionAttrsPass()
|
||||
- goPasses.Run(mod)
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ err := mod.RunPasses("globaldce,globalopt,ipsccp,instcombine,adce,function-attrs", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ return []error{fmt.Errorf("could not build pass pipeline: %w", err)}
|
||||
+ }
|
||||
|
||||
// Run TinyGo-specific optimization passes.
|
||||
OptimizeStringToBytes(mod)
|
||||
OptimizeReflectImplements(mod)
|
||||
OptimizeAllocs(mod, nil, nil)
|
||||
- err := LowerInterfaces(mod, config)
|
||||
+ err = LowerInterfaces(mod, config)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
@@ -113,7 +78,10 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i
|
||||
// After interfaces are lowered, there are many more opportunities for
|
||||
// interprocedural optimizations. To get them to work, function
|
||||
// attributes have to be updated first.
|
||||
- goPasses.Run(mod)
|
||||
+ err = mod.RunPasses("globaldce,globalopt,ipsccp,instcombine,adce,function-attrs", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ return []error{fmt.Errorf("could not build pass pipeline: %w", err)}
|
||||
+ }
|
||||
|
||||
// Run TinyGo-specific interprocedural optimizations.
|
||||
OptimizeAllocs(mod, config.Options.PrintAllocs, func(pos token.Position, msg string) {
|
||||
@@ -134,10 +102,12 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i
|
||||
}
|
||||
|
||||
// Clean up some leftover symbols of the previous transformations.
|
||||
- goPasses := llvm.NewPassManager()
|
||||
- defer goPasses.Dispose()
|
||||
- goPasses.AddGlobalDCEPass()
|
||||
- goPasses.Run(mod)
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ err = mod.RunPasses("globaldce", llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ return []error{fmt.Errorf("could not build pass pipeline: %w", err)}
|
||||
+ }
|
||||
}
|
||||
|
||||
if config.Scheduler() == "none" {
|
||||
@@ -169,23 +139,15 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i
|
||||
fn.SetLinkage(llvm.InternalLinkage)
|
||||
}
|
||||
|
||||
- // Run function passes again, because without it, llvm.coro.size.i32()
|
||||
- // doesn't get lowered.
|
||||
- funcPasses := llvm.NewFunctionPassManagerForModule(mod)
|
||||
- defer funcPasses.Dispose()
|
||||
- builder.PopulateFunc(funcPasses)
|
||||
- funcPasses.InitializeFunc()
|
||||
- for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
|
||||
- funcPasses.RunFunc(fn)
|
||||
+ // Run the default pass pipeline.
|
||||
+ // TODO: set the PrepareForThinLTO flag somehow.
|
||||
+ po := llvm.NewPassBuilderOptions()
|
||||
+ defer po.Dispose()
|
||||
+ passes := fmt.Sprintf("default<%s>", optLevel)
|
||||
+ err := mod.RunPasses(passes, llvm.TargetMachine{}, po)
|
||||
+ if err != nil {
|
||||
+ return []error{fmt.Errorf("could not build pass pipeline: %w", err)}
|
||||
}
|
||||
- funcPasses.FinalizeFunc()
|
||||
-
|
||||
- // Run module passes.
|
||||
- // TODO: somehow set the PrepareForThinLTO flag in the pass manager builder.
|
||||
- modPasses := llvm.NewPassManager()
|
||||
- defer modPasses.Dispose()
|
||||
- builder.Populate(modPasses)
|
||||
- modPasses.Run(mod)
|
||||
|
||||
hasGCPass := MakeGCStackSlots(mod)
|
||||
if hasGCPass {
|
||||
diff --git a/transform/transform.go b/transform/transform.go
|
||||
index ab08317e..429cbd5f 100644
|
||||
--- a/transform/transform.go
|
||||
+++ b/transform/transform.go
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
// the -opt= compiler flag.
|
||||
func AddStandardAttributes(fn llvm.Value, config *compileopts.Config) {
|
||||
ctx := fn.Type().Context()
|
||||
- _, sizeLevel, _ := config.OptLevels()
|
||||
+ _, _, sizeLevel := config.OptLevel()
|
||||
if sizeLevel >= 1 {
|
||||
fn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0))
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
||||
222
0006-avr-don-t-compile-large-parts-of-picolibc-math-stdio.patch
Normal file
222
0006-avr-don-t-compile-large-parts-of-picolibc-math-stdio.patch
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
From 0321eecc6d29d5b571930ed97f392623fe80a2e5 Mon Sep 17 00:00:00 2001
|
||||
From: Ayke van Laethem <aykevanlaethem@gmail.com>
|
||||
Date: Sat, 23 Sep 2023 14:57:25 +0200
|
||||
Subject: [PATCH 6/7] avr: don't compile large parts of picolibc (math, stdio)
|
||||
|
||||
These parts aren't critical and lead to crashes on small chips without
|
||||
long jumps (like the attiny85) with LLVM 17. (Older LLVM versions would
|
||||
emit long jumps regardless, even if the chip didn't support those).
|
||||
|
||||
For more information, see: https://github.com/llvm/llvm-project/issues/67042
|
||||
|
||||
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
---
|
||||
builder/picolibc.go | 172 ++++++++++++++++++++++++--------------------
|
||||
1 file changed, 93 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/builder/picolibc.go b/builder/picolibc.go
|
||||
index 1b7c748b..91ad27be 100644
|
||||
--- a/builder/picolibc.go
|
||||
+++ b/builder/picolibc.go
|
||||
@@ -3,6 +3,7 @@ package builder
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
+ "strings"
|
||||
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
@@ -41,91 +42,23 @@ var Picolibc = Library{
|
||||
},
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
|
||||
librarySources: func(target string) ([]string, error) {
|
||||
- return picolibcSources, nil
|
||||
+ sources := append([]string(nil), picolibcSources...)
|
||||
+ if !strings.HasPrefix(target, "avr") {
|
||||
+ // Small chips without long jumps can't compile many files (printf,
|
||||
+ // pow, etc). Therefore exclude those source files for those chips.
|
||||
+ // Unfortunately it's difficult to exclude only some chips, so this
|
||||
+ // excludes those files on all AVR chips for now.
|
||||
+ // More information:
|
||||
+ // https://github.com/llvm/llvm-project/issues/67042
|
||||
+ sources = append(sources, picolibcSourcesLarge...)
|
||||
+ }
|
||||
+ return sources, nil
|
||||
},
|
||||
}
|
||||
|
||||
var picolibcSources = []string{
|
||||
"../../picolibc-stdio.c",
|
||||
|
||||
- // srcs_tinystdio
|
||||
- "libc/tinystdio/asprintf.c",
|
||||
- "libc/tinystdio/bufio.c",
|
||||
- "libc/tinystdio/clearerr.c",
|
||||
- "libc/tinystdio/ecvt_r.c",
|
||||
- "libc/tinystdio/ecvt.c",
|
||||
- "libc/tinystdio/ecvtf_r.c",
|
||||
- "libc/tinystdio/ecvtf.c",
|
||||
- "libc/tinystdio/fcvt.c",
|
||||
- "libc/tinystdio/fcvt_r.c",
|
||||
- "libc/tinystdio/fcvtf.c",
|
||||
- "libc/tinystdio/fcvtf_r.c",
|
||||
- "libc/tinystdio/gcvt.c",
|
||||
- "libc/tinystdio/gcvtf.c",
|
||||
- "libc/tinystdio/fclose.c",
|
||||
- "libc/tinystdio/fdevopen.c",
|
||||
- "libc/tinystdio/feof.c",
|
||||
- "libc/tinystdio/ferror.c",
|
||||
- "libc/tinystdio/fflush.c",
|
||||
- "libc/tinystdio/fgetc.c",
|
||||
- "libc/tinystdio/fgets.c",
|
||||
- "libc/tinystdio/fileno.c",
|
||||
- "libc/tinystdio/filestrget.c",
|
||||
- "libc/tinystdio/filestrput.c",
|
||||
- "libc/tinystdio/filestrputalloc.c",
|
||||
- "libc/tinystdio/fmemopen.c",
|
||||
- "libc/tinystdio/fprintf.c",
|
||||
- "libc/tinystdio/fputc.c",
|
||||
- "libc/tinystdio/fputs.c",
|
||||
- "libc/tinystdio/fread.c",
|
||||
- //"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
|
||||
- "libc/tinystdio/fscanf.c",
|
||||
- "libc/tinystdio/fseek.c",
|
||||
- "libc/tinystdio/fseeko.c",
|
||||
- "libc/tinystdio/ftell.c",
|
||||
- "libc/tinystdio/ftello.c",
|
||||
- "libc/tinystdio/fwrite.c",
|
||||
- "libc/tinystdio/getchar.c",
|
||||
- "libc/tinystdio/gets.c",
|
||||
- "libc/tinystdio/matchcaseprefix.c",
|
||||
- "libc/tinystdio/mktemp.c",
|
||||
- "libc/tinystdio/perror.c",
|
||||
- "libc/tinystdio/printf.c",
|
||||
- "libc/tinystdio/putchar.c",
|
||||
- "libc/tinystdio/puts.c",
|
||||
- "libc/tinystdio/rewind.c",
|
||||
- "libc/tinystdio/scanf.c",
|
||||
- "libc/tinystdio/setbuf.c",
|
||||
- "libc/tinystdio/setbuffer.c",
|
||||
- "libc/tinystdio/setlinebuf.c",
|
||||
- "libc/tinystdio/setvbuf.c",
|
||||
- "libc/tinystdio/snprintf.c",
|
||||
- "libc/tinystdio/sprintf.c",
|
||||
- "libc/tinystdio/snprintfd.c",
|
||||
- "libc/tinystdio/snprintff.c",
|
||||
- "libc/tinystdio/sprintff.c",
|
||||
- "libc/tinystdio/sprintfd.c",
|
||||
- "libc/tinystdio/sscanf.c",
|
||||
- "libc/tinystdio/strfromf.c",
|
||||
- "libc/tinystdio/strfromd.c",
|
||||
- "libc/tinystdio/strtof.c",
|
||||
- "libc/tinystdio/strtof_l.c",
|
||||
- "libc/tinystdio/strtod.c",
|
||||
- "libc/tinystdio/strtod_l.c",
|
||||
- "libc/tinystdio/ungetc.c",
|
||||
- "libc/tinystdio/vasprintf.c",
|
||||
- "libc/tinystdio/vfiprintf.c",
|
||||
- "libc/tinystdio/vfprintf.c",
|
||||
- "libc/tinystdio/vfprintff.c",
|
||||
- "libc/tinystdio/vfscanf.c",
|
||||
- "libc/tinystdio/vfiscanf.c",
|
||||
- "libc/tinystdio/vfscanff.c",
|
||||
- "libc/tinystdio/vprintf.c",
|
||||
- "libc/tinystdio/vscanf.c",
|
||||
- "libc/tinystdio/vsscanf.c",
|
||||
- "libc/tinystdio/vsnprintf.c",
|
||||
- "libc/tinystdio/vsprintf.c",
|
||||
-
|
||||
"libc/string/bcmp.c",
|
||||
"libc/string/bcopy.c",
|
||||
"libc/string/bzero.c",
|
||||
@@ -229,6 +162,87 @@ var picolibcSources = []string{
|
||||
"libc/string/wmempcpy.c",
|
||||
"libc/string/wmemset.c",
|
||||
"libc/string/xpg_strerror_r.c",
|
||||
+}
|
||||
+
|
||||
+// Parts of picolibc that are too large for small AVRs.
|
||||
+var picolibcSourcesLarge = []string{
|
||||
+ // srcs_tinystdio
|
||||
+ "libc/tinystdio/asprintf.c",
|
||||
+ "libc/tinystdio/bufio.c",
|
||||
+ "libc/tinystdio/clearerr.c",
|
||||
+ "libc/tinystdio/ecvt_r.c",
|
||||
+ "libc/tinystdio/ecvt.c",
|
||||
+ "libc/tinystdio/ecvtf_r.c",
|
||||
+ "libc/tinystdio/ecvtf.c",
|
||||
+ "libc/tinystdio/fcvt.c",
|
||||
+ "libc/tinystdio/fcvt_r.c",
|
||||
+ "libc/tinystdio/fcvtf.c",
|
||||
+ "libc/tinystdio/fcvtf_r.c",
|
||||
+ "libc/tinystdio/gcvt.c",
|
||||
+ "libc/tinystdio/gcvtf.c",
|
||||
+ "libc/tinystdio/fclose.c",
|
||||
+ "libc/tinystdio/fdevopen.c",
|
||||
+ "libc/tinystdio/feof.c",
|
||||
+ "libc/tinystdio/ferror.c",
|
||||
+ "libc/tinystdio/fflush.c",
|
||||
+ "libc/tinystdio/fgetc.c",
|
||||
+ "libc/tinystdio/fgets.c",
|
||||
+ "libc/tinystdio/fileno.c",
|
||||
+ "libc/tinystdio/filestrget.c",
|
||||
+ "libc/tinystdio/filestrput.c",
|
||||
+ "libc/tinystdio/filestrputalloc.c",
|
||||
+ "libc/tinystdio/fmemopen.c",
|
||||
+ "libc/tinystdio/fprintf.c",
|
||||
+ "libc/tinystdio/fputc.c",
|
||||
+ "libc/tinystdio/fputs.c",
|
||||
+ "libc/tinystdio/fread.c",
|
||||
+ //"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
|
||||
+ "libc/tinystdio/fscanf.c",
|
||||
+ "libc/tinystdio/fseek.c",
|
||||
+ "libc/tinystdio/fseeko.c",
|
||||
+ "libc/tinystdio/ftell.c",
|
||||
+ "libc/tinystdio/ftello.c",
|
||||
+ "libc/tinystdio/fwrite.c",
|
||||
+ "libc/tinystdio/getchar.c",
|
||||
+ "libc/tinystdio/gets.c",
|
||||
+ "libc/tinystdio/matchcaseprefix.c",
|
||||
+ "libc/tinystdio/mktemp.c",
|
||||
+ "libc/tinystdio/perror.c",
|
||||
+ "libc/tinystdio/printf.c",
|
||||
+ "libc/tinystdio/putchar.c",
|
||||
+ "libc/tinystdio/puts.c",
|
||||
+ "libc/tinystdio/rewind.c",
|
||||
+ "libc/tinystdio/scanf.c",
|
||||
+ "libc/tinystdio/setbuf.c",
|
||||
+ "libc/tinystdio/setbuffer.c",
|
||||
+ "libc/tinystdio/setlinebuf.c",
|
||||
+ "libc/tinystdio/setvbuf.c",
|
||||
+ "libc/tinystdio/snprintf.c",
|
||||
+ "libc/tinystdio/sprintf.c",
|
||||
+ "libc/tinystdio/snprintfd.c",
|
||||
+ "libc/tinystdio/snprintff.c",
|
||||
+ "libc/tinystdio/sprintff.c",
|
||||
+ "libc/tinystdio/sprintfd.c",
|
||||
+ "libc/tinystdio/sscanf.c",
|
||||
+ "libc/tinystdio/strfromf.c",
|
||||
+ "libc/tinystdio/strfromd.c",
|
||||
+ "libc/tinystdio/strtof.c",
|
||||
+ "libc/tinystdio/strtof_l.c",
|
||||
+ "libc/tinystdio/strtod.c",
|
||||
+ "libc/tinystdio/strtod_l.c",
|
||||
+ "libc/tinystdio/ungetc.c",
|
||||
+ "libc/tinystdio/vasprintf.c",
|
||||
+ "libc/tinystdio/vfiprintf.c",
|
||||
+ "libc/tinystdio/vfprintf.c",
|
||||
+ "libc/tinystdio/vfprintff.c",
|
||||
+ "libc/tinystdio/vfscanf.c",
|
||||
+ "libc/tinystdio/vfiscanf.c",
|
||||
+ "libc/tinystdio/vfscanff.c",
|
||||
+ "libc/tinystdio/vprintf.c",
|
||||
+ "libc/tinystdio/vscanf.c",
|
||||
+ "libc/tinystdio/vsscanf.c",
|
||||
+ "libc/tinystdio/vsnprintf.c",
|
||||
+ "libc/tinystdio/vsprintf.c",
|
||||
|
||||
"libm/common/sf_finite.c",
|
||||
"libm/common/sf_copysign.c",
|
||||
--
|
||||
2.41.0
|
||||
|
||||
157
0007-all-add-initial-LLVM-17-support.patch
Normal file
157
0007-all-add-initial-LLVM-17-support.patch
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
From 55fd04af5a6a815224b436ee491ed05b0ef4ee7c Mon Sep 17 00:00:00 2001
|
||||
From: Ayke van Laethem <aykevanlaethem@gmail.com>
|
||||
Date: Sat, 23 Sep 2023 15:03:24 +0200
|
||||
Subject: [PATCH 7/7] all: add initial LLVM 17 support
|
||||
|
||||
This allows us to test LLVM 17 already, before it's available in
|
||||
Homebrew etc.
|
||||
|
||||
Full support for LLVM 17 will have to wait until Espressif rebases their
|
||||
Xtensa fork of LLVM.
|
||||
|
||||
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
|
||||
---
|
||||
.circleci/config.yml | 13 +++++++++++--
|
||||
.github/workflows/build-macos.yml | 16 +++++++++++++---
|
||||
cgo/libclang_config_llvm16.go | 2 +-
|
||||
cgo/libclang_config_llvm17.go | 15 +++++++++++++++
|
||||
go.mod | 2 +-
|
||||
go.sum | 4 ++--
|
||||
6 files changed, 43 insertions(+), 9 deletions(-)
|
||||
create mode 100644 cgo/libclang_config_llvm17.go
|
||||
|
||||
diff --git a/.circleci/config.yml b/.circleci/config.yml
|
||||
index 1dff3ba7..86da321d 100644
|
||||
--- a/.circleci/config.yml
|
||||
+++ b/.circleci/config.yml
|
||||
@@ -55,7 +55,7 @@ commands:
|
||||
- run:
|
||||
name: "Install apt dependencies"
|
||||
command: |
|
||||
- echo 'deb https://apt.llvm.org/buster/ llvm-toolchain-buster-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list
|
||||
+ echo 'deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y \
|
||||
@@ -100,11 +100,18 @@ commands:
|
||||
jobs:
|
||||
test-llvm14-go118:
|
||||
docker:
|
||||
- - image: golang:1.18-buster
|
||||
+ - image: golang:1.18-bullseye
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "14"
|
||||
resource_class: large
|
||||
+ test-llvm17-go121:
|
||||
+ docker:
|
||||
+ - image: golang:1.21-bullseye
|
||||
+ steps:
|
||||
+ - test-linux:
|
||||
+ llvm: "17"
|
||||
+ resource_class: large
|
||||
|
||||
workflows:
|
||||
test-all:
|
||||
@@ -112,3 +119,5 @@ workflows:
|
||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||
# least the smoke tests still pass.
|
||||
- test-llvm14-go118
|
||||
+ # This tests the upcoming LLVM 17 support.
|
||||
+ - test-llvm17-go121
|
||||
diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml
|
||||
index 1284a4ed..be8bdb03 100644
|
||||
--- a/.github/workflows/build-macos.yml
|
||||
+++ b/.github/workflows/build-macos.yml
|
||||
@@ -116,11 +116,15 @@ jobs:
|
||||
test-macos-homebrew:
|
||||
name: homebrew-install
|
||||
runs-on: macos-latest
|
||||
+ strategy:
|
||||
+ matrix:
|
||||
+ version: [16, 17]
|
||||
steps:
|
||||
+ - name: Update Homebrew
|
||||
+ run: brew update
|
||||
- name: Install LLVM
|
||||
- shell: bash
|
||||
run: |
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@16
|
||||
+ HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@${{ matrix.version }}
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Go
|
||||
@@ -128,7 +132,13 @@ jobs:
|
||||
with:
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
- - name: Build TinyGo
|
||||
+ - name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||
+ run: go install -tags=llvm${{ matrix.version }}
|
||||
+ - name: Check binary
|
||||
+ run: tinygo version
|
||||
+ - name: Build TinyGo (default LLVM)
|
||||
+ if: matrix.version == 16
|
||||
run: go install
|
||||
- name: Check binary
|
||||
+ if: matrix.version == 16
|
||||
run: tinygo version
|
||||
diff --git a/cgo/libclang_config_llvm16.go b/cgo/libclang_config_llvm16.go
|
||||
index 79aacd2f..28091701 100644
|
||||
--- a/cgo/libclang_config_llvm16.go
|
||||
+++ b/cgo/libclang_config_llvm16.go
|
||||
@@ -1,4 +1,4 @@
|
||||
-//go:build !byollvm && !llvm14 && !llvm15
|
||||
+//go:build !byollvm && !llvm14 && !llvm15 && !llvm17
|
||||
|
||||
package cgo
|
||||
|
||||
diff --git a/cgo/libclang_config_llvm17.go b/cgo/libclang_config_llvm17.go
|
||||
new file mode 100644
|
||||
index 00000000..fd6d1480
|
||||
--- /dev/null
|
||||
+++ b/cgo/libclang_config_llvm17.go
|
||||
@@ -0,0 +1,15 @@
|
||||
+//go:build !byollvm && llvm17
|
||||
+
|
||||
+package cgo
|
||||
+
|
||||
+/*
|
||||
+#cgo linux CFLAGS: -I/usr/include/llvm-17 -I/usr/include/llvm-c-17 -I/usr/lib/llvm-17/include
|
||||
+#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@17/include
|
||||
+#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@17/include
|
||||
+#cgo freebsd CFLAGS: -I/usr/local/llvm17/include
|
||||
+#cgo linux LDFLAGS: -L/usr/lib/llvm-17/lib -lclang
|
||||
+#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@17/lib -lclang -lffi
|
||||
+#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@17/lib -lclang -lffi
|
||||
+#cgo freebsd LDFLAGS: -L/usr/local/llvm17/lib -lclang
|
||||
+*/
|
||||
+import "C"
|
||||
diff --git a/go.mod b/go.mod
|
||||
index 9af3402b..36d601f8 100644
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -18,7 +18,7 @@ require (
|
||||
golang.org/x/sys v0.11.0
|
||||
golang.org/x/tools v0.12.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
- tinygo.org/x/go-llvm v0.0.0-20230918183930-9edb6403d0bc
|
||||
+ tinygo.org/x/go-llvm v0.0.0-20230923132128-bba3c7009bfd
|
||||
)
|
||||
|
||||
require (
|
||||
diff --git a/go.sum b/go.sum
|
||||
index 587efdf2..1b5ad074 100644
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -65,5 +65,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
-tinygo.org/x/go-llvm v0.0.0-20230918183930-9edb6403d0bc h1:IVX1dqCX3c88P7iEMBtz1xCAM4UIqCMgbqHdSefBaWE=
|
||||
-tinygo.org/x/go-llvm v0.0.0-20230918183930-9edb6403d0bc/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
+tinygo.org/x/go-llvm v0.0.0-20230923132128-bba3c7009bfd h1:iSVvs8r3ooxYTsmcf7FKCHq83eOSUkWKtmQhnDadDQU=
|
||||
+tinygo.org/x/go-llvm v0.0.0-20230923132128-bba3c7009bfd/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
--
|
||||
2.41.0
|
||||
|
||||
11
tinygo.spec
11
tinygo.spec
|
|
@ -77,6 +77,15 @@ Patch0002: 0002-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
|
|||
# Add Fedora specific dnf instructions
|
||||
Patch0003: 0003-Suggest-optional-packages-to-install-if-missing.patch
|
||||
|
||||
# Support LLVM 17.
|
||||
# https://github.com/tinygo-org/tinygo/pull/3923
|
||||
Patch0004: 0004-transform-fix-bug-in-StringToBytes-optimization-pass.patch
|
||||
# https://github.com/tinygo-org/tinygo/pull/3918
|
||||
Patch0005: 0005-all-use-the-new-LLVM-pass-manager.patch
|
||||
# https://github.com/tinygo-org/tinygo/pull/3913
|
||||
Patch0006: 0006-avr-don-t-compile-large-parts-of-picolibc-math-stdio.patch
|
||||
Patch0007: 0007-all-add-initial-LLVM-17-support.patch
|
||||
|
||||
# Not supported upstream yet.
|
||||
ExcludeArch: ppc64le s390x
|
||||
# https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval
|
||||
|
|
@ -97,7 +106,7 @@ BuildRequires: golang(github.com/mattn/go-tty) >= 0.0.4
|
|||
BuildRequires: golang(github.com/sigurn/crc16)
|
||||
BuildRequires: golang(go.bug.st/serial) >= 1.6.0
|
||||
BuildRequires: golang(golang.org/x/tools/go/ast/astutil)
|
||||
BuildRequires: golang(golang.org/x/tools/go/ssa) >= 0.12
|
||||
BuildRequires: golang(golang.org/x/tools/go/ssa) >= 0.11
|
||||
BuildRequires: golang(gopkg.in/yaml.v2) >= 2.4.0
|
||||
BuildRequires: golang(tinygo.org/x/go-llvm)
|
||||
BuildRequires: golang-tests
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue