mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-20 12:29:03 +00:00
compiler: make panic configurable
Currently defined: abort and trap. -panic=unwind should be implemented in the future.
This commit is contained in:
committed by
Ron Evans
parent
d1efffe96b
commit
0fd90c49cc
@@ -34,6 +34,7 @@ type Config struct {
|
|||||||
GOOS string //
|
GOOS string //
|
||||||
GOARCH string //
|
GOARCH string //
|
||||||
GC string // garbage collection strategy
|
GC string // garbage collection strategy
|
||||||
|
PanicStrategy string // panic strategy ("abort" or "trap")
|
||||||
CFlags []string // cflags to pass to cgo
|
CFlags []string // cflags to pass to cgo
|
||||||
LDFlags []string // ldflags to pass to cgo
|
LDFlags []string // ldflags to pass to cgo
|
||||||
DumpSSA bool // dump Go SSA, for compiler debugging
|
DumpSSA bool // dump Go SSA, for compiler debugging
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) erro
|
|||||||
}
|
}
|
||||||
builder.AddCoroutinePassesToExtensionPoints()
|
builder.AddCoroutinePassesToExtensionPoints()
|
||||||
|
|
||||||
|
if c.PanicStrategy == "trap" {
|
||||||
|
c.replacePanicsWithTrap() // -panic=trap
|
||||||
|
}
|
||||||
|
|
||||||
// Run function passes for each function.
|
// Run function passes for each function.
|
||||||
funcPasses := llvm.NewFunctionPassManagerForModule(c.mod)
|
funcPasses := llvm.NewFunctionPassManagerForModule(c.mod)
|
||||||
defer funcPasses.Dispose()
|
defer funcPasses.Dispose()
|
||||||
@@ -113,6 +117,25 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace panic calls with calls to llvm.trap, to reduce code size. This is the
|
||||||
|
// -panic=trap intrinsic.
|
||||||
|
func (c *Compiler) replacePanicsWithTrap() {
|
||||||
|
trap := c.mod.NamedFunction("llvm.trap")
|
||||||
|
for _, name := range []string{"runtime._panic", "runtime.runtimePanic"} {
|
||||||
|
fn := c.mod.NamedFunction(name)
|
||||||
|
if fn.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, use := range getUses(fn) {
|
||||||
|
if use.IsACallInst().IsNil() || use.CalledValue() != fn {
|
||||||
|
panic("expected use of a panic function to be a call")
|
||||||
|
}
|
||||||
|
c.builder.SetInsertPointBefore(use)
|
||||||
|
c.builder.CreateCall(trap, nil, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Eliminate created but not used maps.
|
// Eliminate created but not used maps.
|
||||||
//
|
//
|
||||||
// In the future, this should statically allocate created but never modified
|
// In the future, this should statically allocate created but never modified
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func (e *commandError) Error() string {
|
|||||||
type BuildConfig struct {
|
type BuildConfig struct {
|
||||||
opt string
|
opt string
|
||||||
gc string
|
gc string
|
||||||
|
panicStrategy string
|
||||||
printIR bool
|
printIR bool
|
||||||
dumpSSA bool
|
dumpSSA bool
|
||||||
debug bool
|
debug bool
|
||||||
@@ -61,6 +62,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
|||||||
GOOS: spec.GOOS,
|
GOOS: spec.GOOS,
|
||||||
GOARCH: spec.GOARCH,
|
GOARCH: spec.GOARCH,
|
||||||
GC: config.gc,
|
GC: config.gc,
|
||||||
|
PanicStrategy: config.panicStrategy,
|
||||||
CFlags: spec.CFlags,
|
CFlags: spec.CFlags,
|
||||||
LDFlags: spec.LDFlags,
|
LDFlags: spec.LDFlags,
|
||||||
Debug: config.debug,
|
Debug: config.debug,
|
||||||
@@ -507,6 +509,7 @@ func main() {
|
|||||||
outpath := flag.String("o", "", "output filename")
|
outpath := flag.String("o", "", "output filename")
|
||||||
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
||||||
gc := flag.String("gc", "", "garbage collector to use (none, dumb, marksweep)")
|
gc := flag.String("gc", "", "garbage collector to use (none, dumb, marksweep)")
|
||||||
|
panicStrategy := flag.String("panic", "print", "panic strategy (abort, trap)")
|
||||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||||
target := flag.String("target", "", "LLVM target")
|
target := flag.String("target", "", "LLVM target")
|
||||||
@@ -529,6 +532,7 @@ func main() {
|
|||||||
config := &BuildConfig{
|
config := &BuildConfig{
|
||||||
opt: *opt,
|
opt: *opt,
|
||||||
gc: *gc,
|
gc: *gc,
|
||||||
|
panicStrategy: *panicStrategy,
|
||||||
printIR: *printIR,
|
printIR: *printIR,
|
||||||
dumpSSA: *dumpSSA,
|
dumpSSA: *dumpSSA,
|
||||||
debug: !*nodebug,
|
debug: !*nodebug,
|
||||||
@@ -544,6 +548,12 @@ func main() {
|
|||||||
config.ldFlags = strings.Split(*ldFlags, " ")
|
config.ldFlags = strings.Split(*ldFlags, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *panicStrategy != "print" && *panicStrategy != "trap" {
|
||||||
|
fmt.Fprintln(os.Stderr, "Panic strategy must be either print or trap.")
|
||||||
|
usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
os.Setenv("CC", "clang -target="+*target)
|
os.Setenv("CC", "clang -target="+*target)
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
|
|||||||
Reference in New Issue
Block a user