1
0
mirror of https://github.com/golang/go synced 2024-11-26 06:47:58 -07:00

[dev.regabi] cmd/compile: always use a Field for ODOTPTR expressions

During walk, we create ODOTPTR expressions to access runtime struct
fields. But rather than using an actual Field for the selection, we
were just directly setting the ODOTPTR's Offset field.

This CL changes walk to create proper struct fields (albeit without
the rest of their enclosing struct type) and use them for creating the
ODOTPTR expressions.

Passes toolstash -cmp.

Change-Id: I08dbac3ed29141587feb0905d15adbcbcc4ca49e
Reviewed-on: https://go-review.googlesource.com/c/go/+/280432
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Matthew Dempsky 2020-12-26 17:51:16 -08:00
parent e4f293d853
commit a4f335f420
2 changed files with 52 additions and 15 deletions

View File

@ -318,15 +318,7 @@ func walkSwitchType(sw *ir.SwitchStmt) {
sw.Compiled.Append(ifNil)
// Load hash from type or itab.
dotHash := ir.NewSelectorExpr(base.Pos, ir.ODOTPTR, itab, nil)
dotHash.SetType(types.Types[types.TUINT32])
dotHash.SetTypecheck(1)
if s.facename.Type().IsEmptyInterface() {
dotHash.Offset = int64(2 * types.PtrSize) // offset of hash in runtime._type
} else {
dotHash.Offset = int64(2 * types.PtrSize) // offset of hash in runtime.itab
}
dotHash.SetBounded(true) // guaranteed not to fault
dotHash := typeHashFieldOf(base.Pos, itab)
s.hashname = copyExpr(dotHash, dotHash.Type(), &sw.Compiled)
br := ir.NewBranchStmt(base.Pos, ir.OBREAK, nil)
@ -409,6 +401,32 @@ func walkSwitchType(sw *ir.SwitchStmt) {
walkStmtList(sw.Compiled)
}
// typeHashFieldOf returns an expression to select the type hash field
// from an interface's descriptor word (whether a *runtime._type or
// *runtime.itab pointer).
func typeHashFieldOf(pos src.XPos, itab *ir.UnaryExpr) *ir.SelectorExpr {
if itab.Op() != ir.OITAB {
base.Fatalf("expected OITAB, got %v", itab.Op())
}
var hashField *types.Field
if itab.X.Type().IsEmptyInterface() {
// runtime._type's hash field
if rtypeHashField == nil {
rtypeHashField = runtimeField("hash", int64(2*types.PtrSize), types.Types[types.TUINT32])
}
hashField = rtypeHashField
} else {
// runtime.itab's hash field
if itabHashField == nil {
itabHashField = runtimeField("hash", int64(2*types.PtrSize), types.Types[types.TUINT32])
}
hashField = itabHashField
}
return boundedDotPtr(pos, itab, hashField)
}
var rtypeHashField, itabHashField *types.Field
// A typeSwitch walks a type switch.
type typeSwitch struct {
// Temporary variables (i.e., ONAMEs) used by type switch dispatch logic:

View File

@ -539,12 +539,31 @@ func calcHasCall(n ir.Node) bool {
// itabType loads the _type field from a runtime.itab struct.
func itabType(itab ir.Node) ir.Node {
typ := ir.NewSelectorExpr(base.Pos, ir.ODOTPTR, itab, nil)
typ.SetType(types.NewPtr(types.Types[types.TUINT8]))
typ.SetTypecheck(1)
typ.Offset = int64(types.PtrSize) // offset of _type in runtime.itab
typ.SetBounded(true) // guaranteed not to fault
return typ
if itabTypeField == nil {
// runtime.itab's _type field
itabTypeField = runtimeField("_type", int64(types.PtrSize), types.NewPtr(types.Types[types.TUINT8]))
}
return boundedDotPtr(base.Pos, itab, itabTypeField)
}
var itabTypeField *types.Field
// boundedDotPtr returns a selector expression representing ptr.field
// and omits nil-pointer checks for ptr.
func boundedDotPtr(pos src.XPos, ptr ir.Node, field *types.Field) *ir.SelectorExpr {
sel := ir.NewSelectorExpr(pos, ir.ODOTPTR, ptr, field.Sym)
sel.Selection = field
sel.Offset = field.Offset
sel.SetType(field.Type)
sel.SetTypecheck(1)
sel.SetBounded(true) // guaranteed not to fault
return sel
}
func runtimeField(name string, offset int64, typ *types.Type) *types.Field {
f := types.NewField(src.NoXPos, ir.Pkgs.Runtime.Lookup(name), typ)
f.Offset = offset
return f
}
// ifaceData loads the data field from an interface.