From 9406a4d74a548b1ab6bbebc48c231b22d177dc24 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 10 Oct 2018 14:14:45 +0200 Subject: [PATCH] main: add -opt= flag for the optimization level --- main.go | 45 ++++++++++++++++++++++++++++++--------------- main_test.go | 2 +- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index ffb986e2..4aa4731d 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ var commands = map[string]string{ } // Helper function for Compiler object. -func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA, debug bool, printSizes string, action func(string) error) error { +func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, debug bool, printSizes string, action func(string) error) error { config := compiler.Config{ Triple: spec.Triple, Debug: debug, @@ -58,8 +58,22 @@ func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA, debug return err } - // TODO: provide a flag to disable (most) optimizations. - c.Optimize(2, 2, 5) // -Oz params + // Optimization levels here are roughly the same as Clang, but probably not + // exactly. + switch opt { + case "none:", "0": + c.Optimize(0, 0, 0) // -O0 + case "1": + c.Optimize(1, 0, 0) // -O1 + case "2": + c.Optimize(2, 0, 225) // -O2 + case "s": + c.Optimize(2, 1, 225) // -Os + case "z": + c.Optimize(2, 2, 5) // -Oz, default + default: + return errors.New("unknown optimization level: -opt=" + opt) + } if err := c.Verify(); err != nil { return err } @@ -166,13 +180,13 @@ func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA, debug } } -func Build(pkgName, outpath, target string, printIR, dumpSSA, debug bool, printSizes string) error { +func Build(pkgName, outpath, target, opt string, printIR, dumpSSA, debug bool, printSizes string) error { spec, err := LoadTarget(target) if err != nil { return err } - return Compile(pkgName, outpath, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { + return Compile(pkgName, outpath, opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { if err := os.Rename(tmppath, outpath); err != nil { // Moving failed. Do a file copy. inf, err := os.Open(tmppath) @@ -200,13 +214,13 @@ func Build(pkgName, outpath, target string, printIR, dumpSSA, debug bool, printS }) } -func Flash(pkgName, target, port string, printIR, dumpSSA, debug bool, printSizes string) error { +func Flash(pkgName, target, opt, port string, printIR, dumpSSA, debug bool, printSizes string) error { spec, err := LoadTarget(target) if err != nil { return err } - return Compile(pkgName, ".hex", spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { + return Compile(pkgName, ".hex", opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { if spec.Flasher == "" { return errors.New("no flash command specified - did you miss a -target flag?") } @@ -229,7 +243,7 @@ func Flash(pkgName, target, port string, printIR, dumpSSA, debug bool, printSize // // Note: this command is expected to execute just before exiting, as it // modifies global state. -func FlashGDB(pkgName, target, port string, printIR, dumpSSA, ocdOutput bool, printSizes string) error { +func FlashGDB(pkgName, target, opt, port string, printIR, dumpSSA, ocdOutput bool, printSizes string) error { spec, err := LoadTarget(target) if err != nil { return err @@ -240,7 +254,7 @@ func FlashGDB(pkgName, target, port string, printIR, dumpSSA, ocdOutput bool, pr } debug := true // always enable debug symbols - return Compile(pkgName, "", spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { + return Compile(pkgName, "", opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { if len(spec.OCDDaemon) != 0 { // We need a separate debugging daemon for on-chip debugging. daemon := exec.Command(spec.OCDDaemon[0], spec.OCDDaemon[1:]...) @@ -331,7 +345,7 @@ func Run(pkgName string) error { } // Compile and run the given program in an emulator. -func Emulate(pkgName, target string) error { +func Emulate(pkgName, target, opt string) error { spec, err := LoadTarget(target) if err != nil { return err @@ -340,7 +354,7 @@ func Emulate(pkgName, target string) error { return errors.New("no emulator configured for this target") } - return Compile(pkgName, ".elf", spec, false, false, false, "", func(tmppath string) error { + return Compile(pkgName, ".elf", opt, spec, false, false, false, "", func(tmppath string) error { args := append(spec.Emulator[1:], tmppath) cmd := exec.Command(spec.Emulator[0], args...) cmd.Stdout = os.Stdout @@ -369,6 +383,7 @@ func usage() { func main() { outpath := flag.String("o", "", "output filename") + opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z") printIR := flag.Bool("printir", false, "print LLVM IR") dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA") target := flag.String("target", llvm.DefaultTargetTriple(), "LLVM target") @@ -400,7 +415,7 @@ func main() { usage() os.Exit(1) } - err := Build(flag.Arg(0), *outpath, *target, *printIR, *dumpSSA, !*nodebug, *printSize) + err := Build(flag.Arg(0), *outpath, *target, *opt, *printIR, *dumpSSA, !*nodebug, *printSize) if err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) @@ -413,9 +428,9 @@ func main() { } var err error if command == "flash" { - err = Flash(flag.Arg(0), *target, *port, *printIR, *dumpSSA, !*nodebug, *printSize) + err = Flash(flag.Arg(0), *target, *opt, *port, *printIR, *dumpSSA, !*nodebug, *printSize) } else { - err = FlashGDB(flag.Arg(0), *target, *port, *printIR, *dumpSSA, *ocdOutput, *printSize) + err = FlashGDB(flag.Arg(0), *target, *opt, *port, *printIR, *dumpSSA, *ocdOutput, *printSize) } if err != nil { fmt.Fprintln(os.Stderr, "error:", err) @@ -431,7 +446,7 @@ func main() { if *target == llvm.DefaultTargetTriple() { err = Run(flag.Arg(0)) } else { - err = Emulate(flag.Arg(0), *target) + err = Emulate(flag.Arg(0), *target, *opt) } if err != nil { fmt.Fprintln(os.Stderr, "error:", err) diff --git a/main_test.go b/main_test.go index 0aaccca0..4d7e62f8 100644 --- a/main_test.go +++ b/main_test.go @@ -60,7 +60,7 @@ func runTest(path, tmpdir string, target string, t *testing.T) { // Build the test binary. binary := filepath.Join(tmpdir, "test") - err = Build(path, binary, target, false, false, false, "") + err = Build(path, binary, target, "z", false, false, false, "") if err != nil { t.Log("failed to build:", err) t.Fail()