aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/typecheck/typecheck.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/typecheck/typecheck.go')
-rw-r--r--src/cmd/compile/internal/typecheck/typecheck.go243
1 files changed, 1 insertions, 242 deletions
diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go
index 4b5c3198ca..4c6ac21fc6 100644
--- a/src/cmd/compile/internal/typecheck/typecheck.go
+++ b/src/cmd/compile/internal/typecheck/typecheck.go
@@ -35,110 +35,7 @@ func Init() {
initUniverse()
DeclContext = ir.PEXTERN
base.Timer.Start("fe", "loadsys")
- loadsys()
-}
-
-func Package() {
- declareUniverse()
-
- TypecheckAllowed = true
-
- // Process top-level declarations in phases.
-
- // Phase 1: const, type, and names and types of funcs.
- // This will gather all the information about types
- // and methods but doesn't depend on any of it.
- //
- // We also defer type alias declarations until phase 2
- // to avoid cycles like #18640.
- // TODO(gri) Remove this again once we have a fix for #25838.
-
- // Don't use range--typecheck can add closures to Target.Decls.
- base.Timer.Start("fe", "typecheck", "top1")
- for i := 0; i < len(Target.Decls); i++ {
- n := Target.Decls[i]
- if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).X.Alias()) {
- Target.Decls[i] = Stmt(n)
- }
- }
-
- // Phase 2: Variable assignments.
- // To check interface assignments, depends on phase 1.
-
- // Don't use range--typecheck can add closures to Target.Decls.
- base.Timer.Start("fe", "typecheck", "top2")
- for i := 0; i < len(Target.Decls); i++ {
- n := Target.Decls[i]
- if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() {
- Target.Decls[i] = Stmt(n)
- }
- }
-
- // Phase 3: Type check function bodies.
- // Don't use range--typecheck can add closures to Target.Decls.
- base.Timer.Start("fe", "typecheck", "func")
- var fcount int64
- for i := 0; i < len(Target.Decls); i++ {
- n := Target.Decls[i]
- if n.Op() == ir.ODCLFUNC {
- FuncBody(n.(*ir.Func))
- fcount++
- }
- }
-
- // Phase 4: Check external declarations.
- // TODO(mdempsky): This should be handled when type checking their
- // corresponding ODCL nodes.
- base.Timer.Start("fe", "typecheck", "externdcls")
- for i, n := range Target.Externs {
- if n.Op() == ir.ONAME {
- Target.Externs[i] = Expr(Target.Externs[i])
- }
- }
-
- // Phase 5: With all user code type-checked, it's now safe to verify map keys.
- CheckMapKeys()
-
- // Phase 6: Compute Addrtaken for names.
- // We need to wait until typechecking is done so that when we see &x[i]
- // we know that x has its address taken if x is an array, but not if x is a slice.
- // We compute Addrtaken in bulk here.
- // After this phase, we maintain Addrtaken incrementally.
- if dirtyAddrtaken {
- computeAddrtaken(Target.Decls)
- dirtyAddrtaken = false
- }
- incrementalAddrtaken = true
-
- // Phase 7: Eliminate some obviously dead code.
- // Must happen after typechecking.
- for _, n := range Target.Decls {
- if n.Op() == ir.ODCLFUNC {
- deadcode(n.(*ir.Func))
- }
- }
-
- // Phase 8: Decide how to capture closed variables.
- // This needs to run before escape analysis,
- // because variables captured by value do not escape.
- base.Timer.Start("fe", "capturevars")
- for _, n := range Target.Decls {
- if n.Op() == ir.ODCLFUNC {
- n := n.(*ir.Func)
- if n.OClosure != nil {
- ir.CurFunc = n
- CaptureVars(n)
- }
- }
- }
- CaptureVarsComplete = true
- ir.CurFunc = nil
-
- if base.Debug.TypecheckInl != 0 {
- // Typecheck imported function bodies if Debug.l > 1,
- // otherwise lazily when used or re-exported.
- AllImportedBodies()
- }
+ InitRuntime()
}
func AssignExpr(n ir.Node) ir.Node { return typecheck(n, ctxExpr|ctxAssign) }
@@ -2247,144 +2144,6 @@ func CheckReturn(fn *ir.Func) {
}
}
-func deadcode(fn *ir.Func) {
- deadcodeslice(&fn.Body)
-
- if len(fn.Body) == 0 {
- return
- }
-
- for _, n := range fn.Body {
- if len(n.Init()) > 0 {
- return
- }
- switch n.Op() {
- case ir.OIF:
- n := n.(*ir.IfStmt)
- if !ir.IsConst(n.Cond, constant.Bool) || len(n.Body) > 0 || len(n.Else) > 0 {
- return
- }
- case ir.OFOR:
- n := n.(*ir.ForStmt)
- if !ir.IsConst(n.Cond, constant.Bool) || ir.BoolVal(n.Cond) {
- return
- }
- default:
- return
- }
- }
-
- fn.Body.Set([]ir.Node{ir.NewBlockStmt(base.Pos, nil)})
-}
-
-func deadcodeslice(nn *ir.Nodes) {
- var lastLabel = -1
- for i, n := range *nn {
- if n != nil && n.Op() == ir.OLABEL {
- lastLabel = i
- }
- }
- for i, n := range *nn {
- // Cut is set to true when all nodes after i'th position
- // should be removed.
- // In other words, it marks whole slice "tail" as dead.
- cut := false
- if n == nil {
- continue
- }
- if n.Op() == ir.OIF {
- n := n.(*ir.IfStmt)
- n.Cond = deadcodeexpr(n.Cond)
- if ir.IsConst(n.Cond, constant.Bool) {
- var body ir.Nodes
- if ir.BoolVal(n.Cond) {
- n.Else = ir.Nodes{}
- body = n.Body
- } else {
- n.Body = ir.Nodes{}
- body = n.Else
- }
- // If "then" or "else" branch ends with panic or return statement,
- // it is safe to remove all statements after this node.
- // isterminating is not used to avoid goto-related complications.
- // We must be careful not to deadcode-remove labels, as they
- // might be the target of a goto. See issue 28616.
- if body := body; len(body) != 0 {
- switch body[(len(body) - 1)].Op() {
- case ir.ORETURN, ir.ORETJMP, ir.OPANIC:
- if i > lastLabel {
- cut = true
- }
- }
- }
- }
- }
-
- deadcodeslice(n.PtrInit())
- switch n.Op() {
- case ir.OBLOCK:
- n := n.(*ir.BlockStmt)
- deadcodeslice(&n.List)
- case ir.OFOR:
- n := n.(*ir.ForStmt)
- deadcodeslice(&n.Body)
- case ir.OIF:
- n := n.(*ir.IfStmt)
- deadcodeslice(&n.Body)
- deadcodeslice(&n.Else)
- case ir.ORANGE:
- n := n.(*ir.RangeStmt)
- deadcodeslice(&n.Body)
- case ir.OSELECT:
- n := n.(*ir.SelectStmt)
- for _, cas := range n.Cases {
- deadcodeslice(&cas.Body)
- }
- case ir.OSWITCH:
- n := n.(*ir.SwitchStmt)
- for _, cas := range n.Cases {
- deadcodeslice(&cas.Body)
- }
- }
-
- if cut {
- nn.Set((*nn)[:i+1])
- break
- }
- }
-}
-
-func deadcodeexpr(n ir.Node) ir.Node {
- // Perform dead-code elimination on short-circuited boolean
- // expressions involving constants with the intent of
- // producing a constant 'if' condition.
- switch n.Op() {
- case ir.OANDAND:
- n := n.(*ir.LogicalExpr)
- n.X = deadcodeexpr(n.X)
- n.Y = deadcodeexpr(n.Y)
- if ir.IsConst(n.X, constant.Bool) {
- if ir.BoolVal(n.X) {
- return n.Y // true && x => x
- } else {
- return n.X // false && x => false
- }
- }
- case ir.OOROR:
- n := n.(*ir.LogicalExpr)
- n.X = deadcodeexpr(n.X)
- n.Y = deadcodeexpr(n.Y)
- if ir.IsConst(n.X, constant.Bool) {
- if ir.BoolVal(n.X) {
- return n.X // true || x => true
- } else {
- return n.Y // false || x => x
- }
- }
- }
- return n
-}
-
// getIotaValue returns the current value for "iota",
// or -1 if not within a ConstSpec.
func getIotaValue() int64 {