Skip to content

Commit

Permalink
cmd/compile: add unsafe.Unreachable
Browse files Browse the repository at this point in the history
DO NOT SUBMIT

This is a rudimentary implementation,
so that I can experiment with it.

Updates golang#30582

Change-Id: I2e3a9e776490a9b01d4f166014b133625e419418
  • Loading branch information
josharian committed Mar 9, 2019
1 parent abda60d commit 8d5a1cb
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/gc/op_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cmd/compile/internal/gc/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ func (o *Order) stmt(n *Node) {
default:
Fatalf("orderstmt %v", n.Op)

case OVARKILL, OVARLIVE, OINLMARK:
case OVARKILL, OVARLIVE, OINLMARK, OUNREACHABLE:
o.out = append(o.out, n)

case OAS:
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/compile/internal/gc/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,12 @@ func (s *state) stmt(n *Node) {
// go through SSA.
}
}
case OUNREACHABLE:
m := s.mem()
b := s.endBlock()
b.Kind = ssa.BlockExit
b.Aux = "unreachable" // TODO: new block kind instead of this hack
b.SetControl(m)
case ODEFER:
s.call(n.Left, callDefer)
case OGO:
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/compile/internal/gc/syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,8 @@ const (
OSWITCH // switch Ninit; Left { List } (List is a list of OXCASE or OCASE)
OTYPESW // Left = Right.(type) (appears as .Left of OSWITCH)

OUNREACHABLE // unsafe.Unreachable()

// types
OTCHAN // chan int
OTMAP // map[string]int
Expand Down
15 changes: 15 additions & 0 deletions src/cmd/compile/internal/gc/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,13 @@ func typecheck1(n *Node, top int) (res *Node) {
// any side effects disappear; ignore init
setintconst(n, evalunsafe(n))

case OUNREACHABLE:
ok |= ctxStmt
if !zeroargs(n, "unsafe.Unreachable") {
n.Type = nil
return n
}

case OCAP, OLEN:
ok |= ctxExpr
if !onearg(n, "%v", n.Op) {
Expand Down Expand Up @@ -2369,6 +2376,14 @@ func implicitstar(n *Node) *Node {
return n
}

func zeroargs(n *Node, f string) bool {
if n.List.Len() != 0 {
yyerror("too many arguments to %s: %v", f, n)
return false
}
return true
}

func onearg(n *Node, f string, args ...interface{}) bool {
if n.Left != nil {
return true
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/gc/universe.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ var unsafeFuncs = [...]struct {
{"Alignof", OALIGNOF},
{"Offsetof", OOFFSETOF},
{"Sizeof", OSIZEOF},
{"Unreachable", OUNREACHABLE},
}

// initUniverse initializes the universe block.
Expand Down
9 changes: 5 additions & 4 deletions src/cmd/compile/internal/gc/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ func walkstmt(n *Node) *Node {

switch n.Op {
default:
Dump("nottop", n)
if n.Op == ONAME {
yyerror("%v is not a top level statement", n.Sym)
Fatalf("%v is not a top level statement", n.Sym)
} else {
yyerror("%v is not a top level statement", n.Op)
Fatalf("%v is not a top level statement", n.Op)
}
Dump("nottop", n)

case OAS,
OASOP,
Expand Down Expand Up @@ -187,7 +187,8 @@ func walkstmt(n *Node) *Node {
OCHECKNIL,
OVARDEF,
OVARKILL,
OVARLIVE:
OVARLIVE,
OUNREACHABLE:
break

case ODCL:
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/compile/internal/ssa/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ var passes = [...]pass{
{name: "phiopt", fn: phiopt},
{name: "nilcheckelim", fn: nilcheckelim},
{name: "prove", fn: prove},
{name: "unreachable", fn: unreachable}, // TODO: is this in the right place? TODO: flag to disable?
{name: "fuse plain", fn: fusePlain},
{name: "decompose builtin", fn: decomposeBuiltIn, required: true},
{name: "softfloat", fn: softfloat, required: true},
Expand Down Expand Up @@ -447,6 +448,8 @@ var passOrder = [...]constraint{
{"generic cse", "prove"},
// deadcode after prove to eliminate all new dead blocks.
{"prove", "generic deadcode"},
// unreachable after prove so that prove can use unreachability information
{"prove", "unreachable"},
// common-subexpression before dead-store elim, so that we recognize
// when two address expressions are the same.
{"generic cse", "dse"},
Expand Down
46 changes: 46 additions & 0 deletions src/cmd/compile/internal/ssa/unreachable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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

// unreachable removes blocks generated by unsafe.Unreachable.
func unreachable(f *Func) {
// if os.Getenv("J") == "" {
// return
// }
changed := false
for _, b := range f.Blocks {
// TODO: this is a hack.
// We should probably explicitly represent unsafe.Unreachable
// with its own block kind.
if b.Aux != "unreachable" {
continue
}
if b == f.Entry {
// TODO: what here?
continue
}
for _, e := range b.Preds {
p := e.b
if len(p.Succs) != 2 {
// TODO: is this possible? if so, handle.
continue
}
p.removeSucc(e.i)
p.Kind = BlockPlain
p.Likely = BranchUnknown
p.SetControl(nil)

// trash b, just in case
b.Kind = BlockInvalid
b.Values = nil
b.Preds = nil
b.Succs = nil
changed = true
}
}
if changed {
f.invalidateCFG()
}
}
3 changes: 3 additions & 0 deletions src/go/types/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
x.typ = Typ[Uintptr]
// result is constant - no need to record signature

case _Unreachable:
x.mode = novalue

case _Sizeof:
// unsafe.Sizeof(x T) uintptr
check.assignment(x, nil, "argument to unsafe.Sizeof")
Expand Down
2 changes: 2 additions & 0 deletions src/go/types/builtins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ var builtinCalls = []struct {
{"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant
{"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant

{"Unreachable", `unsafe.Unreachable()`, `invalid type`},

{"assert", `assert(true)`, `invalid type`}, // constant
{"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant

Expand Down
8 changes: 5 additions & 3 deletions src/go/types/universe.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const (
_Alignof
_Offsetof
_Sizeof
_Unreachable

// testing support
_Assert
Expand Down Expand Up @@ -158,9 +159,10 @@ var predeclaredFuncs = [...]struct {
_Real: {"real", 1, false, expression},
_Recover: {"recover", 0, false, statement},

_Alignof: {"Alignof", 1, false, expression},
_Offsetof: {"Offsetof", 1, false, expression},
_Sizeof: {"Sizeof", 1, false, expression},
_Alignof: {"Alignof", 1, false, expression},
_Offsetof: {"Offsetof", 1, false, expression},
_Sizeof: {"Sizeof", 1, false, expression},
_Unreachable: {"Unreachable", 0, false, statement},

_Assert: {"assert", 1, false, statement},
_Trace: {"trace", 0, true, statement},
Expand Down

0 comments on commit 8d5a1cb

Please sign in to comment.