aboutsummaryrefslogtreecommitdiffhomepage
path: root/main.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2018-11-09 17:16:36 +0100
committerAyke van Laethem <[email protected]>2018-12-01 13:26:06 +0100
commitb4c90f36776fcd2f8a2ab30b50928442c973afc5 (patch)
tree9aaa2556aa805cba7aa8f2f0e372c639df2616e1 /main.go
parente45c4ac182aae5ad7fab876660cec531287199b8 (diff)
downloadtinygo-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.go32
1 files changed, 19 insertions, 13 deletions
diff --git a/main.go b/main.go
index 7466b8ad7..d85554ac0 100644
--- a/main.go
+++ b/main.go
@@ -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 {