compiler: make panic configurable

Currently defined: abort and trap. -panic=unwind should be implemented
in the future.
Этот коммит содержится в:
Ayke van Laethem 2019-04-24 16:00:36 +02:00 коммит произвёл Ron Evans
родитель d1efffe96b
коммит 0fd90c49cc
3 изменённых файлов: 74 добавлений и 40 удалений

Просмотреть файл

@ -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

10
main.go
Просмотреть файл

@ -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 {