diff options
Diffstat (limited to 'transform')
-rw-r--r-- | transform/interface-lowering.go | 10 | ||||
-rw-r--r-- | transform/interface-lowering_test.go | 2 | ||||
-rw-r--r-- | transform/interrupt.go | 5 | ||||
-rw-r--r-- | transform/interrupt_test.go | 2 | ||||
-rw-r--r-- | transform/optimizer.go | 18 | ||||
-rw-r--r-- | transform/wasm-abi.go | 4 |
6 files changed, 23 insertions, 18 deletions
diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go index 56956a39a..e8b6deecf 100644 --- a/transform/interface-lowering.go +++ b/transform/interface-lowering.go @@ -133,6 +133,7 @@ func (itf *interfaceInfo) id() string { // should be seen as a regular function call (see LowerInterfaces). type lowerInterfacesPass struct { mod llvm.Module + sizeLevel int // LLVM optimization size level, 1 means -opt=s and 2 means -opt=z builder llvm.Builder ctx llvm.Context uintptrType llvm.Type @@ -145,9 +146,10 @@ type lowerInterfacesPass struct { // emitted by the compiler as higher-level intrinsics. They need some lowering // before LLVM can work on them. This is done so that a few cleanup passes can // run before assigning the final type codes. -func LowerInterfaces(mod llvm.Module) error { +func LowerInterfaces(mod llvm.Module, sizeLevel int) error { p := &lowerInterfacesPass{ mod: mod, + sizeLevel: sizeLevel, builder: mod.Context().NewBuilder(), ctx: mod.Context(), uintptrType: mod.Context().IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8), @@ -594,6 +596,9 @@ func (p *lowerInterfacesPass) createInterfaceImplementsFunc(itf *interfaceInfo) fn := itf.assertFunc fn.SetLinkage(llvm.InternalLinkage) fn.SetUnnamedAddr(true) + if p.sizeLevel >= 2 { + fn.AddFunctionAttr(p.ctx.CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0)) + } // TODO: debug info @@ -653,6 +658,9 @@ func (p *lowerInterfacesPass) createInterfaceMethodFunc(itf *interfaceInfo, sign fn := itf.methodFuncs[signature] fn.SetLinkage(llvm.InternalLinkage) fn.SetUnnamedAddr(true) + if p.sizeLevel >= 2 { + fn.AddFunctionAttr(p.ctx.CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0)) + } // TODO: debug info diff --git a/transform/interface-lowering_test.go b/transform/interface-lowering_test.go index f3652cc90..e1c3c2dcc 100644 --- a/transform/interface-lowering_test.go +++ b/transform/interface-lowering_test.go @@ -9,7 +9,7 @@ import ( func TestInterfaceLowering(t *testing.T) { t.Parallel() testTransform(t, "testdata/interface", func(mod llvm.Module) { - err := LowerInterfaces(mod) + err := LowerInterfaces(mod, 0) if err != nil { t.Error(err) } diff --git a/transform/interrupt.go b/transform/interrupt.go index 1c3247d5e..d5d7d47e9 100644 --- a/transform/interrupt.go +++ b/transform/interrupt.go @@ -22,7 +22,7 @@ import ( // simply call the registered handlers. This might seem like it causes extra // overhead, but in fact inlining and const propagation will eliminate most if // not all of that. -func LowerInterrupts(mod llvm.Module) []error { +func LowerInterrupts(mod llvm.Module, sizeLevel int) []error { var errs []error // Discover interrupts. The runtime/interrupt.Register call is a compiler @@ -182,6 +182,9 @@ func LowerInterrupts(mod llvm.Module) []error { // Create the wrapper function which is the actual interrupt handler // that is inserted in the interrupt vector. fn.SetUnnamedAddr(true) + if sizeLevel >= 2 { + fn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID("optsize"), 0)) + } fn.SetSection(".text." + name) if isSoftwareVectored { fn.SetLinkage(llvm.InternalLinkage) diff --git a/transform/interrupt_test.go b/transform/interrupt_test.go index 00a199063..60d83da15 100644 --- a/transform/interrupt_test.go +++ b/transform/interrupt_test.go @@ -11,7 +11,7 @@ func TestInterruptLowering(t *testing.T) { for _, subtest := range []string{"avr", "cortexm"} { t.Run(subtest, func(t *testing.T) { testTransform(t, "testdata/interrupt-"+subtest, func(mod llvm.Module) { - errs := LowerInterrupts(mod) + errs := LowerInterrupts(mod, 0) if len(errs) != 0 { t.Fail() for _, err := range errs { diff --git a/transform/optimizer.go b/transform/optimizer.go index e10144b92..108219106 100644 --- a/transform/optimizer.go +++ b/transform/optimizer.go @@ -76,12 +76,12 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i OptimizeStringToBytes(mod) OptimizeReflectImplements(mod) OptimizeAllocs(mod) - err := LowerInterfaces(mod) + err := LowerInterfaces(mod, sizeLevel) if err != nil { return []error{err} } - errs := LowerInterrupts(mod) + errs := LowerInterrupts(mod, sizeLevel) if len(errs) > 0 { return errs } @@ -102,14 +102,14 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i } else { // Must be run at any optimization level. - err := LowerInterfaces(mod) + err := LowerInterfaces(mod, sizeLevel) if err != nil { return []error{err} } if config.FuncImplementation() == "switch" { LowerFuncValues(mod) } - errs := LowerInterrupts(mod) + errs := LowerInterrupts(mod, sizeLevel) if len(errs) > 0 { return errs } @@ -153,16 +153,6 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i return []error{errors.New("optimizations caused a verification failure")} } - if sizeLevel >= 2 { - // Set the "optsize" attribute to make slightly smaller binaries at the - // cost of some performance. - kind := llvm.AttributeKindID("optsize") - attr := mod.Context().CreateEnumAttribute(kind, 0) - for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { - fn.AddFunctionAttr(attr) - } - } - // After TinyGo-specific transforms have finished, undo exporting these functions. for _, name := range getFunctionsUsedInTransforms(config) { fn := mod.NamedFunction(name) diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go index 0c3af9a3d..85e419145 100644 --- a/transform/wasm-abi.go +++ b/transform/wasm-abi.go @@ -73,6 +73,10 @@ func ExternalInt64AsPtr(mod llvm.Module) error { fn.SetName(name + "$i64wrap") externalFnType := llvm.FunctionType(returnType, paramTypes, fnType.IsFunctionVarArg()) externalFn := llvm.AddFunction(mod, name, externalFnType) + optsize := fn.GetEnumFunctionAttribute(llvm.AttributeKindID("optsize")) + if !optsize.IsNil() { + fn.AddFunctionAttr(optsize) + } if fn.IsDeclaration() { // Just a declaration: the definition doesn't exist on the Go side |