diff options
author | Ayke van Laethem <[email protected]> | 2018-11-09 17:16:36 +0100 |
---|---|---|
committer | Ayke van Laethem <[email protected]> | 2018-12-01 13:26:06 +0100 |
commit | b4c90f36776fcd2f8a2ab30b50928442c973afc5 (patch) | |
tree | 9aaa2556aa805cba7aa8f2f0e372c639df2616e1 /main.go | |
parent | e45c4ac182aae5ad7fab876660cec531287199b8 (diff) | |
download | tinygo-b4c90f36776fcd2f8a2ab30b50928442c973afc5.tar.gz tinygo-b4c90f36776fcd2f8a2ab30b50928442c973afc5.zip |
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.
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 32 |
1 files changed, 19 insertions, 13 deletions
@@ -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,21 +100,24 @@ 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 := c.Verify(); err != nil { + if err != nil { return err } + if err := c.Verify(); err != nil { + 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 // know. As a temporary fix, load all global variables in RAM. @@ -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 { |