cmd/compile: remove go:notinheap pragma

Updates #46731

Change-Id: I247fa9c7ca97feb9053665da7ff56e7f5b571f74
Reviewed-on: https://go-review.googlesource.com/c/go/+/422815
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Joedian Reid <joedian@golang.org>
This commit is contained in:
Cuong Manh Le 2022-08-10 20:01:48 +07:00
parent 0ee0bb1003
commit 8bbb362f4c
9 changed files with 7 additions and 54 deletions

View file

@ -454,9 +454,6 @@ const (
Nowritebarrierrec // error on write barrier in this or recursive callees
Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees
// Runtime and cgo type pragmas
NotInHeap // values of this type must not be heap allocated
// Go command pragmas
GoBuildPragma

View file

@ -212,33 +212,9 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
ntyp.SetVargen()
}
pragmas := g.pragmaFlags(decl.Pragma, typePragmas)
pragmas := g.pragmaFlags(decl.Pragma, 0)
name.SetPragma(pragmas) // TODO(mdempsky): Is this still needed?
if pragmas&ir.NotInHeap != 0 {
ntyp.SetNotInHeap(true)
}
// We need to use g.typeExpr(decl.Type) here to ensure that for
// chained, defined-type declarations like:
//
// type T U
//
// //go:notinheap
// type U struct { … }
//
// we mark both T and U as NotInHeap. If we instead used just
// g.typ(otyp.Underlying()), then we'd instead set T's underlying
// type directly to the struct type (which is not marked NotInHeap)
// and fail to mark T as NotInHeap.
//
// Also, we rely here on Type.SetUnderlying allowing passing a
// defined type and handling forward references like from T to U
// above. Contrast with go/types's Named.SetUnderlying, which
// disallows this.
//
// [mdempsky: Subtleties like these are why I always vehemently
// object to new type pragmas.]
ntyp.SetUnderlying(g.typeExpr(decl.Type))
tparams := otyp.(*types2.Named).TypeParams()

View file

@ -36,8 +36,6 @@ const (
ir.Nowritebarrier |
ir.Nowritebarrierrec |
ir.Yeswritebarrierrec
typePragmas = ir.NotInHeap
)
func pragmaFlag(verb string) ir.PragmaFlag {
@ -77,8 +75,6 @@ func pragmaFlag(verb string) ir.PragmaFlag {
return ir.UintptrEscapes | ir.UintptrKeepAlive // implies UintptrKeepAlive
case "go:registerparams": // TODO(register args) remove after register abi is working
return ir.RegisterParams
case "go:notinheap":
return ir.NotInHeap
}
return 0
}

View file

@ -344,9 +344,6 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
}
if flag == ir.NotInHeap && *base.Flag.LowerP != "runtime/internal/sys" {
p.error(syntax.Error{Pos: pos, Msg: "//go:notinheap only allowed in runtime/internal/sys"})
}
pragma.Flag |= flag
pragma.Pos = append(pragma.Pos, pragmaPos{flag, pos})
}

View file

@ -1096,9 +1096,6 @@ func (r *reader) typeExt(name *ir.Name) {
}
name.SetPragma(r.pragmaFlag())
if name.Pragma()&ir.NotInHeap != 0 {
typ.SetNotInHeap(true)
}
typecheck.SetBaseTypeIndex(typ, r.Int64(), r.Int64())
}
@ -2440,16 +2437,6 @@ func (r *reader) expr() (res ir.Node) {
// TODO(mdempsky): Stop constructing expressions of untyped type.
x = typecheck.DefaultLit(x, typ)
if op, why := typecheck.Convertop(x.Op() == ir.OLITERAL, x.Type(), typ); op == ir.OXXX {
// types2 ensured that x is convertable to typ under standard Go
// semantics, but cmd/compile also disallows some conversions
// involving //go:notinheap.
//
// TODO(mdempsky): This can be removed after #46731 is implemented.
base.ErrorfAt(pos, "cannot convert %L to type %v%v", x, typ, why)
base.ErrorExit() // harsh, but prevents constructing invalid IR
}
ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
ce.TypeWord, ce.SrcRType = typeWord, srcRType
if implicit {

View file

@ -2355,7 +2355,7 @@ func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
if n.Alias {
pw.checkPragmas(n.Pragma, 0, false)
} else {
pw.checkPragmas(n.Pragma, typePragmas, false)
pw.checkPragmas(n.Pragma, 0, false)
// Assign a unique ID to function-scoped defined types.
if c.withinFunc {

View file

@ -18,7 +18,7 @@ func Set(t *types.Type, off int64, bv bitvec.BitVec) {
base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
}
if !t.HasPointers() {
// Note: this case ensures that pointers to go:notinheap types
// Note: this case ensures that pointers to not-in-heap types
// are not considered pointers by garbage collection and stack copying.
return
}

View file

@ -901,7 +901,7 @@ func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
} else if t.Elem().NotInHeap() {
// TODO(mdempsky): This can be relaxed, but should only affect the
// Go runtime itself. End users should only see //go:notinheap
// Go runtime itself. End users should only see not-in-heap
// types due to incomplete C structs in cgo, and those types don't
// have a meaningful size anyway.
base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")

View file

@ -471,15 +471,15 @@ func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
return ir.OXXX, ""
}
// Conversions from regular to go:notinheap are not allowed
// Conversions from regular to not-in-heap are not allowed
// (unless it's unsafe.Pointer). These are runtime-specific
// rules.
// (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
// (a) Disallow (*T) to (*U) where T is not-in-heap but U isn't.
if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
return ir.OXXX, why
}
// (b) Disallow string to []T where T is go:notinheap.
// (b) Disallow string to []T where T is not-in-heap.
if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
return ir.OXXX, why