diff options
Diffstat (limited to 'src/cmd/compile')
-rw-r--r-- | src/cmd/compile/internal/gc/ssa.go | 3 | ||||
-rw-r--r-- | src/cmd/compile/internal/ppc64/ssa.go | 46 | ||||
-rw-r--r-- | src/cmd/compile/internal/ssa/nilcheck.go | 12 |
3 files changed, 51 insertions, 10 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 27af607d6f..e0b4b40323 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3651,7 +3651,8 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { break } closure = s.expr(fn) - if thearch.LinkArch.Family == sys.Wasm { + if thearch.LinkArch.Family == sys.Wasm || objabi.GOOS == "aix" && k != callGo { + // On AIX, the closure needs to be verified as fn can be nil, except if it's a call go. This needs to be handled by the runtime to have the "go of nil func value" error. // TODO(neelance): On other architectures this should be eliminated by the optimization steps s.nilCheck(closure) } diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index a6dd8cab5f..3b37c797a9 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -10,6 +10,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/obj/ppc64" + "cmd/internal/objabi" "math" "strings" ) @@ -1183,13 +1184,44 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.To.Sym = v.Aux.(*obj.LSym) case ssa.OpPPC64LoweredNilCheck: - // Issue a load which will fault if arg is nil. - p := s.Prog(ppc64.AMOVBZ) - p.From.Type = obj.TYPE_MEM - p.From.Reg = v.Args[0].Reg() - gc.AddAux(&p.From, v) - p.To.Type = obj.TYPE_REG - p.To.Reg = ppc64.REGTMP + if objabi.GOOS == "aix" { + // CMP Rarg0, R0 + // BNE 2(PC) + // STW R0, 0(R0) + // NOP (so the BNE has somewhere to land) + + // CMP Rarg0, R0 + p := s.Prog(ppc64.ACMP) + p.From.Type = obj.TYPE_REG + p.From.Reg = v.Args[0].Reg() + p.To.Type = obj.TYPE_REG + p.To.Reg = ppc64.REG_R0 + + // BNE 2(PC) + p2 := s.Prog(ppc64.ABNE) + p2.To.Type = obj.TYPE_BRANCH + + // STW R0, 0(R0) + // Write at 0 is forbidden and will trigger a SIGSEGV + p = s.Prog(ppc64.AMOVW) + p.From.Type = obj.TYPE_REG + p.From.Reg = ppc64.REG_R0 + p.To.Type = obj.TYPE_MEM + p.To.Reg = ppc64.REG_R0 + + // NOP (so the BNE has somewhere to land) + nop := s.Prog(obj.ANOP) + gc.Patch(p2, nop) + + } else { + // Issue a load which will fault if arg is nil. + p := s.Prog(ppc64.AMOVBZ) + p.From.Type = obj.TYPE_MEM + p.From.Reg = v.Args[0].Reg() + gc.AddAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = ppc64.REGTMP + } if gc.Debug_checknil != 0 && v.Pos.Line() > 1 { // v.Pos.Line()==1 in generated wrappers gc.Warnl(v.Pos, "generated nil check") } diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index fca4f0bfc4..e0669cf80c 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -5,6 +5,7 @@ package ssa import ( + "cmd/internal/objabi" "cmd/internal/src" ) @@ -183,6 +184,9 @@ func nilcheckelim(f *Func) { // This should agree with minLegalPointer in the runtime. const minZeroPage = 4096 +// faultOnLoad is true if a load to an address below minZeroPage will trigger a SIGSEGV. +var faultOnLoad = objabi.GOOS != "aix" + // nilcheckelim2 eliminates unnecessary nil checks. // Runs after lowering and scheduling. func nilcheckelim2(f *Func) { @@ -225,12 +229,16 @@ func nilcheckelim2(f *Func) { // Find any pointers that this op is guaranteed to fault on if nil. var ptrstore [2]*Value ptrs := ptrstore[:0] - if opcodeTable[v.Op].faultOnNilArg0 { + if opcodeTable[v.Op].faultOnNilArg0 && (faultOnLoad || v.Type.IsMemory()) { + // On AIX, only writing will fault. ptrs = append(ptrs, v.Args[0]) } - if opcodeTable[v.Op].faultOnNilArg1 { + if opcodeTable[v.Op].faultOnNilArg1 && (faultOnLoad || (v.Type.IsMemory() && v.Op != OpPPC64LoweredMove)) { + // On AIX, only writing will fault. + // LoweredMove is a special case because it's considered as a "mem" as it stores on arg0 but arg1 is accessed as a load and should be checked. ptrs = append(ptrs, v.Args[1]) } + for _, ptr := range ptrs { // Check to make sure the offset is small. switch opcodeTable[v.Op].auxType { |