]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: implement more panic stuff
authorKeith Randall <khr@golang.org>
Tue, 18 Aug 2015 22:25:40 +0000 (15:25 -0700)
committerKeith Randall <khr@golang.org>
Wed, 19 Aug 2015 23:17:48 +0000 (23:17 +0000)
Implement index check panics (and slice check panics, for when
we need those).

Clean up nil check.  Now that the new regalloc is in we can use
the register we just tested as the address 0 destination.

Remove jumps after panic calls, they are unreachable.

Change-Id: Ifee6e510cdea49cc7c7056887e4f06c67488d491
Reviewed-on: https://go-review.googlesource.com/13687
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/AMD64Ops.go
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteAMD64.go

index 6a5ecbf04d569598c82385e6fd4653584f27e08b..1fb5485183cddac4908c3fbbce9b188e6eda5781 100644 (file)
@@ -1617,6 +1617,9 @@ func (s *state) nilCheck(ptr *ssa.Value) {
 // boundsCheck generates bounds checking code.  Checks if 0 <= idx < len, branches to exit if not.
 // Starts a new block on return.
 func (s *state) boundsCheck(idx, len *ssa.Value) {
+       if Debug['B'] != 0 {
+               return
+       }
        // TODO: convert index to full width?
        // TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero.
 
@@ -1627,9 +1630,15 @@ func (s *state) boundsCheck(idx, len *ssa.Value) {
        b.Control = cmp
        b.Likely = ssa.BranchLikely
        bNext := s.f.NewBlock(ssa.BlockPlain)
+       bPanic := s.f.NewBlock(ssa.BlockPlain)
        addEdge(b, bNext)
-       addEdge(b, s.exit)
-       // TODO: don't go directly to s.exit.  Go to a stub that calls panicindex first.
+       addEdge(b, bPanic)
+       addEdge(bPanic, s.exit)
+       s.startBlock(bPanic)
+       // The panic check takes/returns memory to ensure that the right
+       // memory state is observed if the panic happens.
+       s.vars[&memvar] = s.newValue1(ssa.OpPanicIndexCheck, ssa.TypeMem, s.mem())
+       s.endBlock()
        s.startBlock(bNext)
 }
 
@@ -2416,20 +2425,26 @@ func genValue(v *ssa.Value) {
                        Warnl(int(v.Line), "generated nil check")
                }
                // Write to memory address 0. It doesn't matter what we write; use AX.
-               // XORL AX, AX; MOVL AX, (AX) is shorter than MOVL AX, 0.
-               // TODO: If we had the pointer (v.Args[0]) in a register r,
-               // we could use MOVL AX, (r) instead of having to zero AX.
-               // But it isn't worth loading r just to accomplish that.
-               p := Prog(x86.AXORL)
-               p.From.Type = obj.TYPE_REG
-               p.From.Reg = x86.REG_AX
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = x86.REG_AX
+               // Input 0 is the pointer we just checked, use it as the destination.
+               r := regnum(v.Args[0])
                q := Prog(x86.AMOVL)
                q.From.Type = obj.TYPE_REG
                q.From.Reg = x86.REG_AX
                q.To.Type = obj.TYPE_MEM
-               q.To.Reg = x86.REG_AX
+               q.To.Reg = r
+               // TODO: need AUNDEF here?
+       case ssa.OpAMD64LoweredPanicIndexCheck:
+               p := Prog(obj.ACALL)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = Linksym(Panicindex.Sym)
+               // TODO: need AUNDEF here?
+       case ssa.OpAMD64LoweredPanicSliceCheck:
+               p := Prog(obj.ACALL)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = Linksym(panicslice.Sym)
+               // TODO: need AUNDEF here?
        case ssa.OpAMD64LoweredGetG:
                r := regnum(v)
                // See the comments in cmd/internal/obj/x86/obj6.go
@@ -2545,6 +2560,17 @@ var blockJump = [...]struct{ asm, invasm int }{
 
 func genBlock(b, next *ssa.Block, branches []branch) []branch {
        lineno = b.Line
+
+       // after a panic call, don't emit any branch code
+       if len(b.Values) > 0 {
+               switch b.Values[len(b.Values)-1].Op {
+               case ssa.OpAMD64LoweredPanicNilCheck,
+                       ssa.OpAMD64LoweredPanicIndexCheck,
+                       ssa.OpAMD64LoweredPanicSliceCheck:
+                       return branches
+               }
+       }
+
        switch b.Kind {
        case ssa.BlockPlain:
                if b.Succs[0] != next {
index 21f4d012964b0ba5baaa3e5385a823bb987c184a..919336e8699bdcf8e8aebc01c85c5a35f7dcf27f 100644 (file)
 (IsInBounds idx len) -> (SETB (CMPQ <TypeFlags> idx len))
 
 (PanicNilCheck ptr mem) -> (LoweredPanicNilCheck ptr mem)
+(PanicIndexCheck mem) -> (LoweredPanicIndexCheck mem)
+(PanicSliceCheck mem) -> (LoweredPanicSliceCheck mem)
 (GetG) -> (LoweredGetG)
 
 (Move [size] dst src mem) -> (REPMOVSB dst src (MOVQconst <config.Frontend().TypeUInt64()> [size]) mem)
index 24c8a199b53a6e2ec2662d85cb9862847955d249..e633f82348bf34d56815012dddf8e61aaa399d14 100644 (file)
@@ -103,6 +103,7 @@ func init() {
                        clobbers: dx | flags}
                gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx},
                        clobbers: ax | flags}
+               gp10 = regInfo{inputs: []regMask{gp}}
 
                gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly}
                gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly}
@@ -353,7 +354,9 @@ func init() {
                {name: "InvertFlags"}, // reverse direction of arg0
 
                // Pseudo-ops
-               {name: "LoweredPanicNilCheck"},
+               {name: "LoweredPanicNilCheck", reg: gp10},
+               {name: "LoweredPanicIndexCheck"},
+               {name: "LoweredPanicSliceCheck"},
                {name: "LoweredGetG", reg: gp01},
        }
 
index 44eed6aeba5d8d09fe88ff75e1d78a47bcca45d3..2024788c5d52fd4c60b4112dc3b90c8bb5240c62 100644 (file)
@@ -282,8 +282,10 @@ var genericOps = []opData{
        {name: "IsInBounds"}, // 0 <= arg0 < arg1
 
        // Pseudo-ops
-       {name: "PanicNilCheck"}, // trigger a dereference fault; arg0=nil ptr, arg1=mem
-       {name: "GetG"},          // runtime.getg() (read g pointer)
+       {name: "PanicNilCheck"},   // trigger a dereference fault; arg0=nil ptr, arg1=mem, returns mem
+       {name: "PanicIndexCheck"}, // trigger a bounds check failure, arg0=mem, returns mem
+       {name: "PanicSliceCheck"}, // trigger a slice bounds check failure, arg0=mem, returns mem
+       {name: "GetG"},            // runtime.getg() (read g pointer)
 
        // Indexing operations
        {name: "ArrayIndex"},   // arg0=array, arg1=index.  Returns a[i]
index f8e5e623b6f695e7012ed74adebafb13c6b59589..003aacffbb661a4678228ef65a5780c00687f287 100644 (file)
@@ -227,6 +227,8 @@ const (
        OpAMD64REPMOVSB
        OpAMD64InvertFlags
        OpAMD64LoweredPanicNilCheck
+       OpAMD64LoweredPanicIndexCheck
+       OpAMD64LoweredPanicSliceCheck
        OpAMD64LoweredGetG
 
        OpAdd8
@@ -426,6 +428,8 @@ const (
        OpIsNonNil
        OpIsInBounds
        OpPanicNilCheck
+       OpPanicIndexCheck
+       OpPanicSliceCheck
        OpGetG
        OpArrayIndex
        OpPtrIndex
@@ -2686,6 +2690,18 @@ var opcodeTable = [...]opInfo{
        },
        {
                name: "LoweredPanicNilCheck",
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+                       },
+               },
+       },
+       {
+               name: "LoweredPanicIndexCheck",
+               reg:  regInfo{},
+       },
+       {
+               name: "LoweredPanicSliceCheck",
                reg:  regInfo{},
        },
        {
@@ -3486,6 +3502,14 @@ var opcodeTable = [...]opInfo{
                name:    "PanicNilCheck",
                generic: true,
        },
+       {
+               name:    "PanicIndexCheck",
+               generic: true,
+       },
+       {
+               name:    "PanicSliceCheck",
+               generic: true,
+       },
        {
                name:    "GetG",
                generic: true,
index 4013611b8875e8f181c1ac073802e33a409bebd4..4265cfcb8426f10c7bd4fc08706a457b7853e59f 100644 (file)
@@ -5789,6 +5789,22 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
                goto end6f8a8c559a167d1f0a5901d09a1fb248
        end6f8a8c559a167d1f0a5901d09a1fb248:
                ;
+       case OpPanicIndexCheck:
+               // match: (PanicIndexCheck mem)
+               // cond:
+               // result: (LoweredPanicIndexCheck mem)
+               {
+                       mem := v.Args[0]
+                       v.Op = OpAMD64LoweredPanicIndexCheck
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v.AddArg(mem)
+                       return true
+               }
+               goto enda5014ba73d3550a5b66424044395c70f
+       enda5014ba73d3550a5b66424044395c70f:
+               ;
        case OpPanicNilCheck:
                // match: (PanicNilCheck ptr mem)
                // cond:
@@ -5807,6 +5823,22 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
                goto enda02b1ad5a6f929b782190145f2c8628b
        enda02b1ad5a6f929b782190145f2c8628b:
                ;
+       case OpPanicSliceCheck:
+               // match: (PanicSliceCheck mem)
+               // cond:
+               // result: (LoweredPanicSliceCheck mem)
+               {
+                       mem := v.Args[0]
+                       v.Op = OpAMD64LoweredPanicSliceCheck
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v.AddArg(mem)
+                       return true
+               }
+               goto end238ed0074810b55bd2bba7b45cdeed68
+       end238ed0074810b55bd2bba7b45cdeed68:
+               ;
        case OpRsh16Ux16:
                // match: (Rsh16Ux16 <t> x y)
                // cond: