diff --git a/builder/build.go b/builder/build.go index 44f41eb233..537fe8846f 100644 --- a/builder/build.go +++ b/builder/build.go @@ -396,6 +396,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe if errs != nil { return newMultiError(errs, pkg.ImportPath) } + transform.StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return errors.New("verification error after compiling package " + pkg.ImportPath) } @@ -481,6 +482,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe if err != nil { return err } + transform.StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return errors.New("verification error after interpreting " + pkgInit.Name()) } @@ -1191,6 +1193,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error { // linked IR is _expensive_ because dead code hasn't been removed yet, // easily costing a few hundred milliseconds. Therefore, only do it when // specifically requested. + transform.StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return errors.New("verification error after interpreting runtime.initAll") } @@ -1202,6 +1205,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error { if len(errs) > 0 { return newMultiError(errs, "") } + transform.StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return errors.New("verification failure after LLVM optimization passes") } @@ -1553,3 +1557,4 @@ func b2u8(b bool) uint8 { } return 0 } + diff --git a/cgo/libclang_config_llvm20.go b/cgo/libclang_config_llvm20.go index faa2e54d55..14902a2957 100644 --- a/cgo/libclang_config_llvm20.go +++ b/cgo/libclang_config_llvm20.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 +//go:build !byollvm && llvm20 package cgo diff --git a/cgo/libclang_config_llvm21.go b/cgo/libclang_config_llvm21.go new file mode 100644 index 0000000000..b26a69e6f2 --- /dev/null +++ b/cgo/libclang_config_llvm21.go @@ -0,0 +1,15 @@ +//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 + +package cgo + +/* +#cgo linux CFLAGS: -I/usr/include/llvm-21 -I/usr/include/llvm-c-21 -I/usr/lib/llvm-21/include +#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@21/include +#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@21/include +#cgo freebsd CFLAGS: -I/usr/local/llvm21/include +#cgo linux LDFLAGS: -L/usr/lib/llvm-21/lib -lclang +#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@21/lib -lclang +#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@21/lib -lclang +#cgo freebsd LDFLAGS: -L/usr/local/llvm21/lib -lclang +*/ +import "C" diff --git a/go.mod b/go.mod index 7d4ea5f189..40b741aca7 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( golang.org/x/sys v0.30.0 golang.org/x/tools v0.30.0 gopkg.in/yaml.v2 v2.4.0 - tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 + tinygo.org/x/go-llvm v0.0.0-20250929104024-00fb4309ddd2 ) require ( diff --git a/go.sum b/go.sum index 8c2330c3c5..5d6bb75689 100644 --- a/go.sum +++ b/go.sum @@ -60,3 +60,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8= tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= +tinygo.org/x/go-llvm v0.0.0-20250929104024-00fb4309ddd2 h1:PsrNpgfZNjozTahZwNrsRfdUxYPATE60vUn6UjK+/Jo= +tinygo.org/x/go-llvm v0.0.0-20250929104024-00fb4309ddd2/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= diff --git a/transform/optimizer.go b/transform/optimizer.go index 54f9762bc4..2b34ee9c81 100644 --- a/transform/optimizer.go +++ b/transform/optimizer.go @@ -129,6 +129,7 @@ func Optimize(mod llvm.Module, config *compileopts.Config) []error { return errs } } + StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return []error{errors.New("optimizations caused a verification failure")} } @@ -156,6 +157,7 @@ func Optimize(mod llvm.Module, config *compileopts.Config) []error { hasGCPass := MakeGCStackSlots(mod) if hasGCPass { + StripNoneParamAttrs(mod) if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil { return []error{errors.New("GC pass caused a verification failure")} } @@ -172,3 +174,16 @@ var functionsUsedInTransforms = []string{ "runtime.free", "runtime.nilPanic", } + +// StripNoneParamAttrs removes the "none" enum attribute (kind 0) from all +// function parameters. LLVM 21 removed "none" as a valid parameter attribute. +func StripNoneParamAttrs(mod llvm.Module) { + noneKind := llvm.AttributeKindID("none") + if noneKind == 0 { + for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { + for i := 0; i < fn.ParamsCount(); i++ { + fn.RemoveEnumAttributeAtIndex(i+1, 0) + } + } + } +}