1
0
mirror of https://github.com/golang/go synced 2024-11-15 01:40:25 -07:00
go/test/nilptr3.go
Clément Chigot 9fe9853ae5 cmd/compile: fix nilcheck for AIX
This commit adapts compile tool to create correct nilchecks for AIX.

AIX allows to load a nil pointer. Therefore, the default nilcheck
which issues a load must be replaced by a CMP instruction followed by a
store at 0x0 if the value is nil. The store will trigger a SIGSEGV as on
others OS.

The nilcheck algorithm must be adapted to do not remove nilcheck if it's
only a read. Stores are detected with v.Type.IsMemory().

Tests related to nilptr must be adapted to the previous changements.
nilptr.go cannot be used as it's because the AIX address space starts at
1<<32.

Change-Id: I9f5aaf0b7e185d736a9b119c0ed2fe4e5bd1e7af
Reviewed-on: https://go-review.googlesource.com/c/144538
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-11-26 14:13:53 +00:00

252 lines
5.6 KiB
Go

// errorcheck -0 -d=nil
// +build !wasm
// +build !aix
// Copyright 2013 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.
// Test that nil checks are removed.
// Optimization is enabled.
package p
type Struct struct {
X int
Y float64
}
type BigStruct struct {
X int
Y float64
A [1 << 20]int
Z string
}
type Empty struct {
}
type Empty1 struct {
Empty
}
var (
intp *int
arrayp *[10]int
array0p *[0]int
bigarrayp *[1 << 26]int
structp *Struct
bigstructp *BigStruct
emptyp *Empty
empty1p *Empty1
)
func f1() {
_ = *intp // ERROR "generated nil check"
// This one should be removed but the block copy needs
// to be turned into its own pseudo-op in order to see
// the indirect.
_ = *arrayp // ERROR "generated nil check"
// 0-byte indirect doesn't suffice.
// we don't registerize globals, so there are no removed.* nil checks.
_ = *array0p // ERROR "generated nil check"
_ = *array0p // ERROR "removed nil check"
_ = *intp // ERROR "removed nil check"
_ = *arrayp // ERROR "removed nil check"
_ = *structp // ERROR "generated nil check"
_ = *emptyp // ERROR "generated nil check"
_ = *arrayp // ERROR "removed nil check"
}
func f2() {
var (
intp *int
arrayp *[10]int
array0p *[0]int
bigarrayp *[1 << 20]int
structp *Struct
bigstructp *BigStruct
emptyp *Empty
empty1p *Empty1
)
_ = *intp // ERROR "generated nil check"
_ = *arrayp // ERROR "generated nil check"
_ = *array0p // ERROR "generated nil check"
_ = *array0p // ERROR "removed.* nil check"
_ = *intp // ERROR "removed.* nil check"
_ = *arrayp // ERROR "removed.* nil check"
_ = *structp // ERROR "generated nil check"
_ = *emptyp // ERROR "generated nil check"
_ = *arrayp // ERROR "removed.* nil check"
_ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
_ = *bigstructp // ERROR "generated nil check"
_ = *empty1p // ERROR "generated nil check"
}
func fx10k() *[10000]int
var b bool
func f3(x *[10000]int) {
// Using a huge type and huge offsets so the compiler
// does not expect the memory hardware to fault.
_ = x[9999] // ERROR "generated nil check"
for {
if x[9999] != 0 { // ERROR "removed nil check"
break
}
}
x = fx10k()
_ = x[9999] // ERROR "generated nil check"
if b {
_ = x[9999] // ERROR "removed.* nil check"
} else {
_ = x[9999] // ERROR "removed.* nil check"
}
_ = x[9999] // ERROR "removed nil check"
x = fx10k()
if b {
_ = x[9999] // ERROR "generated nil check"
} else {
_ = x[9999] // ERROR "generated nil check"
}
_ = x[9999] // ERROR "generated nil check"
fx10k()
// This one is a bit redundant, if we figured out that
// x wasn't going to change across the function call.
// But it's a little complex to do and in practice doesn't
// matter enough.
_ = x[9999] // ERROR "removed nil check"
}
func f3a() {
x := fx10k()
y := fx10k()
z := fx10k()
_ = &x[9] // ERROR "generated nil check"
y = z
_ = &x[9] // ERROR "removed.* nil check"
x = y
_ = &x[9] // ERROR "generated nil check"
}
func f3b() {
x := fx10k()
y := fx10k()
_ = &x[9] // ERROR "generated nil check"
y = x
_ = &x[9] // ERROR "removed.* nil check"
x = y
_ = &x[9] // ERROR "removed.* nil check"
}
func fx10() *[10]int
func f4(x *[10]int) {
// Most of these have no checks because a real memory reference follows,
// and the offset is small enough that if x is nil, the address will still be
// in the first unmapped page of memory.
_ = x[9] // ERROR "generated nil check" // bug: would like to remove this check (but nilcheck and load are in different blocks)
for {
if x[9] != 0 { // ERROR "removed nil check"
break
}
}
x = fx10()
_ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
if b {
_ = x[9] // ERROR "removed nil check"
} else {
_ = x[9] // ERROR "removed nil check"
}
_ = x[9] // ERROR "removed nil check"
x = fx10()
if b {
_ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
} else {
_ = &x[9] // ERROR "generated nil check"
}
_ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
fx10()
_ = x[9] // ERROR "removed nil check"
x = fx10()
y := fx10()
_ = &x[9] // ERROR "generated nil check"
y = x
_ = &x[9] // ERROR "removed[a-z ]* nil check"
x = y
_ = &x[9] // ERROR "removed[a-z ]* nil check"
}
func m1(m map[int][80]byte) byte {
v := m[3] // ERROR "removed nil check"
return v[5]
}
func m2(m map[int][800]byte) byte {
v := m[3] // ERROR "removed nil check"
return v[5]
}
func m3(m map[int][80]byte) (byte, bool) {
v, ok := m[3] // ERROR "removed nil check"
return v[5], ok
}
func m4(m map[int][800]byte) (byte, bool) {
v, ok := m[3] // ERROR "removed nil check"
return v[5], ok
}
func p1() byte {
p := new([100]byte)
return p[5] // ERROR "removed nil check"
}
// make sure not to do nil check for access of PAUTOHEAP
//go:noinline
func (p *Struct) m() {}
func c1() {
var x Struct
func() { x.m() }() // ERROR "removed nil check"
}
type SS struct {
x byte
}
type TT struct {
SS
}
func f(t *TT) *byte {
// See issue 17242.
s := &t.SS // ERROR "generated nil check"
return &s.x // ERROR "removed nil check"
}
// make sure not to do nil check for newobject
func f7() (*Struct, float64) {
t := new(Struct)
p := &t.Y // ERROR "removed nil check"
return t, *p // ERROR "removed nil check"
}
func f9() []int {
x := new([1]int)
x[0] = 1 // ERROR "removed nil check"
y := x[:] // ERROR "removed nil check"
return y
}