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 //
GOARCH string //
GC string // garbage collection strategy
PanicStrategy string // panic strategy ("abort" or "trap")
CFlags []string // cflags to pass to cgo
LDFlags []string // ldflags to pass to cgo
DumpSSA bool // dump Go SSA, for compiler debugging

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

@ -18,6 +18,10 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) erro
}
builder.AddCoroutinePassesToExtensionPoints()
if c.PanicStrategy == "trap" {
c.replacePanicsWithTrap() // -panic=trap
}
// Run function passes for each function.
funcPasses := llvm.NewFunctionPassManagerForModule(c.mod)
defer funcPasses.Dispose()
@ -113,6 +117,25 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) erro
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.
//
// 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 {
opt string
gc string
panicStrategy string
printIR bool
dumpSSA bool
debug bool
@ -61,6 +62,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
GOOS: spec.GOOS,
GOARCH: spec.GOARCH,
GC: config.gc,
PanicStrategy: config.panicStrategy,
CFlags: spec.CFlags,
LDFlags: spec.LDFlags,
Debug: config.debug,
@ -507,6 +509,7 @@ func main() {
outpath := flag.String("o", "", "output filename")
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
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")
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
target := flag.String("target", "", "LLVM target")
@ -529,6 +532,7 @@ func main() {
config := &BuildConfig{
opt: *opt,
gc: *gc,
panicStrategy: *panicStrategy,
printIR: *printIR,
dumpSSA: *dumpSSA,
debug: !*nodebug,
@ -544,6 +548,12 @@ func main() {
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)
switch command {