mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-12 15:03:41 +00:00
compiler: lower interfaces in a separate pass
This commit changes many things:
* Most interface-related operations are moved into an optimization
pass for more modularity. IR construction creates pseudo-calls which
are lowered in this pass.
* Type codes are assigned in this interface lowering pass, after DCE.
* Type codes are sorted by usage: types more often used in type
asserts are assigned lower numbers to ease jump table construction
during machine code generation.
* Interface assertions are optimized: they are replaced by constant
false, comparison against a constant, or a typeswitch with only
concrete types in the general case.
* Interface calls are replaced with unreachable, direct calls, or a
concrete type switch with direct calls depending on the number of
implementing types. This hopefully makes some interface patterns
zero-cost.
These changes lead to a ~0.5K reduction in code size on Cortex-M for
testdata/interface.go. It appears that a major cause for this is the
replacement of function pointers with direct calls, which are far more
susceptible to optimization. Also, not having a fixed global array of
function pointers greatly helps dead code elimination.
This change also makes future optimizations easier, like optimizations
on interface value comparisons.
This commit is contained in:
@@ -64,7 +64,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||
fmt.Println(c.IR())
|
||||
}
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification error after IR construction")
|
||||
}
|
||||
|
||||
if config.initInterp {
|
||||
@@ -73,13 +73,13 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||
return err
|
||||
}
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification error after interpreting runtime.initAll")
|
||||
}
|
||||
}
|
||||
|
||||
c.ApplyFunctionSections() // -ffunction-sections
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification error after applying function sections")
|
||||
}
|
||||
|
||||
// Browsers cannot handle external functions that have type i64 because it
|
||||
@@ -92,7 +92,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||
return err
|
||||
}
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification error after running the wasm i64 hack")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,20 +100,23 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||
// exactly.
|
||||
switch config.opt {
|
||||
case "none:", "0":
|
||||
c.Optimize(0, 0, 0) // -O0
|
||||
err = c.Optimize(0, 0, 0) // -O0
|
||||
case "1":
|
||||
c.Optimize(1, 0, 0) // -O1
|
||||
err = c.Optimize(1, 0, 0) // -O1
|
||||
case "2":
|
||||
c.Optimize(2, 0, 225) // -O2
|
||||
err = c.Optimize(2, 0, 225) // -O2
|
||||
case "s":
|
||||
c.Optimize(2, 1, 225) // -Os
|
||||
err = c.Optimize(2, 1, 225) // -Os
|
||||
case "z":
|
||||
c.Optimize(2, 2, 5) // -Oz, default
|
||||
err = c.Optimize(2, 2, 5) // -Oz, default
|
||||
default:
|
||||
return errors.New("unknown optimization level: -opt=" + config.opt)
|
||||
err = errors.New("unknown optimization level: -opt=" + config.opt)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification failure after LLVM optimization passes")
|
||||
}
|
||||
|
||||
// On the AVR, pointers can point either to flash or to RAM, but we don't
|
||||
@@ -124,7 +127,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||
if strings.HasPrefix(spec.Triple, "avr") {
|
||||
c.NonConstGlobals()
|
||||
if err := c.Verify(); err != nil {
|
||||
return err
|
||||
return errors.New("verification error after making all globals non-constant on AVR")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +385,10 @@ func Run(pkgName string) error {
|
||||
// -Oz, which is the fastest optimization level (faster than -O0, -O1, -O2
|
||||
// and -Os). Turn off the inliner, as the inliner increases optimization
|
||||
// time.
|
||||
c.Optimize(2, 2, 0)
|
||||
err = c.Optimize(2, 2, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
engine, err := llvm.NewExecutionEngine(c.Module())
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user