blob: c1f79567915d2935de16752d2bda1044233c309f [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa
import (
"fmt"
"log"
)
// Compile is the main entry point for this package.
// Compile modifies f so that on return:
// · all Values in f map to 0 or 1 assembly instructions of the target architecture
// · the order of f.Blocks is the order to emit the Blocks
// · the order of b.Values is the order to emit the Values in each Block
// · f has a non-nil regAlloc field
func Compile(f *Func) {
// TODO: debugging - set flags to control verbosity of compiler,
// which phases to dump IR before/after, etc.
fmt.Printf("compiling %s\n", f.Name)
// hook to print function & phase if panic happens
phaseName := "init"
defer func() {
if phaseName != "" {
fmt.Printf("panic during %s while compiling %s\n", phaseName, f.Name)
}
}()
// Run all the passes
printFunc(f)
checkFunc(f)
for _, p := range passes {
phaseName = p.name
fmt.Printf(" pass %s begin\n", p.name)
p.fn(f)
fmt.Printf(" pass %s end\n", p.name)
printFunc(f)
checkFunc(f)
}
// Squash error printing defer
phaseName = ""
}
type pass struct {
name string
fn func(*Func)
}
// list of passes for the compiler
var passes = [...]pass{
{"phielim", phielim},
{"copyelim", copyelim},
{"opt", opt},
{"generic cse", cse},
{"generic deadcode", deadcode},
{"fuse", fuse},
{"lower", lower},
{"lowered cse", cse},
{"lowered deadcode", deadcode},
{"critical", critical}, // remove critical edges
{"layout", layout}, // schedule blocks
{"schedule", schedule}, // schedule values
{"regalloc", regalloc},
{"stackalloc", stackalloc},
{"cgen", cgen},
}
// Double-check phase ordering constraints.
// This code is intended to document the ordering requirements
// between different phases. It does not override the passes
// list above.
type constraint struct {
a, b string // a must come before b
}
var passOrder = [...]constraint{
// don't layout blocks until critical edges have been removed
{"critical", "layout"},
// regalloc requires the removal of all critical edges
{"critical", "regalloc"},
// regalloc requires all the values in a block to be scheduled
{"schedule", "regalloc"},
// stack allocation requires register allocation
{"regalloc", "stackalloc"},
// code generation requires stack allocation
{"stackalloc", "cgen"},
}
func init() {
for _, c := range passOrder {
a, b := c.a, c.b
i := -1
j := -1
for k, p := range passes {
if p.name == a {
i = k
}
if p.name == b {
j = k
}
}
if i < 0 {
log.Panicf("pass %s not found", a)
}
if j < 0 {
log.Panicf("pass %s not found", b)
}
if i >= j {
log.Panicf("passes %s and %s out of order", a, b)
}
}
}