mirror of
https://github.com/golang/go
synced 2024-11-22 18:54:44 -07:00
[dev.regabi] cmd/compile: cleanup for concrete types - mop-up
An automated rewrite will add concrete type assertions after a test of n.Op(), when n can be safely type-asserted (meaning, n is not reassigned a different type, n is not reassigned and then used outside the scope of the type assertion, and so on). This sequence of CLs handles the code that the automated rewrite does not: adding specific types to function arguments, adjusting code not to call n.Left() etc when n may have multiple representations, and so on. This CL handles all the little files that are left. Passes buildall w/ toolstash -cmp. Change-Id: I6588c92dbbdd37342a77b365d70e02134a033d2a Reviewed-on: https://go-review.googlesource.com/c/go/+/277932 Trust: Russ Cox <rsc@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
be64c8bece
commit
9c384e881e
@ -119,6 +119,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
|
|||||||
}
|
}
|
||||||
f.Offset = o
|
f.Offset = o
|
||||||
if n := ir.AsNode(f.Nname); n != nil {
|
if n := ir.AsNode(f.Nname); n != nil {
|
||||||
|
n := n.Name()
|
||||||
// addrescapes has similar code to update these offsets.
|
// addrescapes has similar code to update these offsets.
|
||||||
// Usually addrescapes runs after widstruct,
|
// Usually addrescapes runs after widstruct,
|
||||||
// in which case we could drop this,
|
// in which case we could drop this,
|
||||||
|
@ -192,7 +192,7 @@ func capturevars(fn *ir.Func) {
|
|||||||
|
|
||||||
var outer ir.Node
|
var outer ir.Node
|
||||||
outer = v.Outer
|
outer = v.Outer
|
||||||
outermost := v.Defn
|
outermost := v.Defn.(*ir.Name)
|
||||||
|
|
||||||
// out parameters will be assigned to implicitly upon return.
|
// out parameters will be assigned to implicitly upon return.
|
||||||
if outermost.Class() != ir.PPARAMOUT && !outermost.Name().Addrtaken() && !outermost.Name().Assigned() && v.Type().Width <= 128 {
|
if outermost.Class() != ir.PPARAMOUT && !outermost.Name().Addrtaken() && !outermost.Name().Assigned() && v.Type().Width <= 128 {
|
||||||
@ -414,25 +414,26 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
return walkexpr(cfn, init)
|
return walkexpr(cfn, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr {
|
func typecheckpartialcall(n ir.Node, sym *types.Sym) *ir.CallPartExpr {
|
||||||
switch dot.Op() {
|
switch n.Op() {
|
||||||
case ir.ODOTINTER, ir.ODOTMETH:
|
case ir.ODOTINTER, ir.ODOTMETH:
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
base.Fatalf("invalid typecheckpartialcall")
|
base.Fatalf("invalid typecheckpartialcall")
|
||||||
}
|
}
|
||||||
|
dot := n.(*ir.SelectorExpr)
|
||||||
|
|
||||||
// Create top-level function.
|
// Create top-level function.
|
||||||
fn := makepartialcall(dot, dot.Type(), sym)
|
fn := makepartialcall(dot, dot.Type(), sym)
|
||||||
fn.SetWrapper(true)
|
fn.SetWrapper(true)
|
||||||
|
|
||||||
return ir.NewCallPartExpr(dot.Pos(), dot.Left(), dot.(*ir.SelectorExpr).Selection, fn)
|
return ir.NewCallPartExpr(dot.Pos(), dot.Left(), dot.Selection, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
|
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
|
||||||
// for partial calls.
|
// for partial calls.
|
||||||
func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func {
|
func makepartialcall(dot *ir.SelectorExpr, t0 *types.Type, meth *types.Sym) *ir.Func {
|
||||||
rcvrtype := dot.Left().Type()
|
rcvrtype := dot.Left().Type()
|
||||||
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
||||||
|
|
||||||
@ -508,7 +509,7 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func {
|
|||||||
// partialCallType returns the struct type used to hold all the information
|
// partialCallType returns the struct type used to hold all the information
|
||||||
// needed in the closure for n (n must be a OCALLPART node).
|
// needed in the closure for n (n must be a OCALLPART node).
|
||||||
// The address of a variable of the returned type can be cast to a func.
|
// The address of a variable of the returned type can be cast to a func.
|
||||||
func partialCallType(n ir.Node) *types.Type {
|
func partialCallType(n *ir.CallPartExpr) *types.Type {
|
||||||
t := tostruct([]*ir.Field{
|
t := tostruct([]*ir.Field{
|
||||||
namedfield("F", types.Types[types.TUINTPTR]),
|
namedfield("F", types.Types[types.TUINTPTR]),
|
||||||
namedfield("R", n.Left().Type()),
|
namedfield("R", n.Left().Type()),
|
||||||
|
@ -165,10 +165,10 @@ func variter(vl []ir.Node, t ir.Ntype, el []ir.Node) []ir.Node {
|
|||||||
if Curfn != nil {
|
if Curfn != nil {
|
||||||
init = append(init, ir.Nod(ir.ODCL, v, nil))
|
init = append(init, ir.Nod(ir.ODCL, v, nil))
|
||||||
}
|
}
|
||||||
e = ir.Nod(ir.OAS, v, e)
|
as := ir.Nod(ir.OAS, v, e)
|
||||||
init = append(init, e)
|
init = append(init, as)
|
||||||
if e.Right() != nil {
|
if e != nil {
|
||||||
v.Defn = e
|
v.Defn = as
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -799,7 +799,7 @@ func makefuncsym(s *types.Sym) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setNodeNameFunc marks a node as a function.
|
// setNodeNameFunc marks a node as a function.
|
||||||
func setNodeNameFunc(n ir.Node) {
|
func setNodeNameFunc(n *ir.Name) {
|
||||||
if n.Op() != ir.ONAME || n.Class() != ir.Pxxx {
|
if n.Op() != ir.ONAME || n.Class() != ir.Pxxx {
|
||||||
base.Fatalf("expected ONAME/Pxxx node, got %v", n)
|
base.Fatalf("expected ONAME/Pxxx node, got %v", n)
|
||||||
}
|
}
|
||||||
@ -861,12 +861,16 @@ func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nowritebarrierrecChecker) findExtraCalls(n ir.Node) {
|
func (c *nowritebarrierrecChecker) findExtraCalls(nn ir.Node) {
|
||||||
if n.Op() != ir.OCALLFUNC {
|
if nn.Op() != ir.OCALLFUNC {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fn := n.Left()
|
n := nn.(*ir.CallExpr)
|
||||||
if fn == nil || fn.Op() != ir.ONAME || fn.Class() != ir.PFUNC || fn.Name().Defn == nil {
|
if n.Left() == nil || n.Left().Op() != ir.ONAME {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fn := n.Left().(*ir.Name)
|
||||||
|
if fn.Class() != ir.PFUNC || fn.Name().Defn == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !isRuntimePkg(fn.Sym().Pkg) || fn.Sym().Name != "systemstack" {
|
if !isRuntimePkg(fn.Sym().Pkg) || fn.Sym().Name != "systemstack" {
|
||||||
|
@ -110,7 +110,7 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v := names[0]
|
v := names[0].(*ir.Name)
|
||||||
if dclcontext != ir.PEXTERN {
|
if dclcontext != ir.PEXTERN {
|
||||||
numLocalEmbed++
|
numLocalEmbed++
|
||||||
v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
|
v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
|
||||||
|
@ -74,7 +74,7 @@ func dumpexport(bout *bio.Writer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node {
|
func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) *ir.Name {
|
||||||
n := ir.AsNode(s.PkgDef())
|
n := ir.AsNode(s.PkgDef())
|
||||||
if n == nil {
|
if n == nil {
|
||||||
// iimport should have created a stub ONONAME
|
// iimport should have created a stub ONONAME
|
||||||
@ -92,7 +92,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node {
|
|||||||
if n.Op() != ir.ONONAME && n.Op() != op {
|
if n.Op() != ir.ONONAME && n.Op() != op {
|
||||||
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
|
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
|
||||||
}
|
}
|
||||||
return n
|
return n.(*ir.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// importtype returns the named type declared by symbol s.
|
// importtype returns the named type declared by symbol s.
|
||||||
@ -102,7 +102,6 @@ func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
|||||||
n := importsym(ipkg, s, ir.OTYPE)
|
n := importsym(ipkg, s, ir.OTYPE)
|
||||||
if n.Op() != ir.OTYPE {
|
if n.Op() != ir.OTYPE {
|
||||||
t := types.NewNamed(n)
|
t := types.NewNamed(n)
|
||||||
|
|
||||||
n.SetOp(ir.OTYPE)
|
n.SetOp(ir.OTYPE)
|
||||||
n.SetPos(pos)
|
n.SetPos(pos)
|
||||||
n.SetType(t)
|
n.SetType(t)
|
||||||
@ -121,7 +120,7 @@ func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
|||||||
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) ir.Node {
|
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) ir.Node {
|
||||||
n := importsym(ipkg, s, op)
|
n := importsym(ipkg, s, op)
|
||||||
if n.Op() != ir.ONONAME {
|
if n.Op() != ir.ONONAME {
|
||||||
if n.Op() == op && (n.Class() != ctxt || !types.Identical(n.Type(), t)) {
|
if n.Op() == op && (op == ir.ONAME && n.Class() != ctxt || !types.Identical(n.Type(), t)) {
|
||||||
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
|
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -31,13 +31,21 @@ func sysvar(name string) *obj.LSym {
|
|||||||
// isParamStackCopy reports whether this is the on-stack copy of a
|
// isParamStackCopy reports whether this is the on-stack copy of a
|
||||||
// function parameter that moved to the heap.
|
// function parameter that moved to the heap.
|
||||||
func isParamStackCopy(n ir.Node) bool {
|
func isParamStackCopy(n ir.Node) bool {
|
||||||
return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Heapaddr != nil
|
if n.Op() != ir.ONAME {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
name := n.(*ir.Name)
|
||||||
|
return (name.Class() == ir.PPARAM || name.Class() == ir.PPARAMOUT) && name.Heapaddr != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isParamHeapCopy reports whether this is the on-heap copy of
|
// isParamHeapCopy reports whether this is the on-heap copy of
|
||||||
// a function parameter that moved to the heap.
|
// a function parameter that moved to the heap.
|
||||||
func isParamHeapCopy(n ir.Node) bool {
|
func isParamHeapCopy(n ir.Node) bool {
|
||||||
return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy != nil
|
if n.Op() != ir.ONAME {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
name := n.(*ir.Name)
|
||||||
|
return name.Class() == ir.PAUTOHEAP && name.Name().Stackcopy != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// autotmpname returns the name for an autotmp variable numbered n.
|
// autotmpname returns the name for an autotmp variable numbered n.
|
||||||
|
@ -48,10 +48,10 @@ func fninit(n []ir.Node) {
|
|||||||
if n.Op() == ir.ONONAME {
|
if n.Op() == ir.ONONAME {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if n.Op() != ir.ONAME || n.Class() != ir.PEXTERN {
|
if n.Op() != ir.ONAME || n.(*ir.Name).Class() != ir.PEXTERN {
|
||||||
base.Fatalf("bad inittask: %v", n)
|
base.Fatalf("bad inittask: %v", n)
|
||||||
}
|
}
|
||||||
deps = append(deps, n.Sym().Linksym())
|
deps = append(deps, n.(*ir.Name).Sym().Linksym())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a function that contains all the initialization statements.
|
// Make a function that contains all the initialization statements.
|
||||||
@ -86,10 +86,10 @@ func fninit(n []ir.Node) {
|
|||||||
// Record user init functions.
|
// Record user init functions.
|
||||||
for i := 0; i < renameinitgen; i++ {
|
for i := 0; i < renameinitgen; i++ {
|
||||||
s := lookupN("init.", i)
|
s := lookupN("init.", i)
|
||||||
fn := ir.AsNode(s.Def).Name().Defn
|
fn := ir.AsNode(s.Def).Name().Defn.(*ir.Func)
|
||||||
// Skip init functions with empty bodies.
|
// Skip init functions with empty bodies.
|
||||||
if fn.Body().Len() == 1 {
|
if fn.Body().Len() == 1 {
|
||||||
if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.List().Len() == 0 {
|
if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.(*ir.BlockStmt).List().Len() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ func (d *initDeps) foundDep(n *ir.Name) {
|
|||||||
}
|
}
|
||||||
d.seen.Add(n)
|
d.seen.Add(n)
|
||||||
if d.transitive && n.Class() == ir.PFUNC {
|
if d.transitive && n.Class() == ir.PFUNC {
|
||||||
d.inspectList(n.Defn.Body())
|
d.inspectList(n.Defn.(*ir.Func).Body())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ func Main(archInit func(*Arch)) {
|
|||||||
timings.Start("fe", "typecheck", "top1")
|
timings.Start("fe", "typecheck", "top1")
|
||||||
for i := 0; i < len(xtop); i++ {
|
for i := 0; i < len(xtop); i++ {
|
||||||
n := xtop[i]
|
n := xtop[i]
|
||||||
if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Alias()) {
|
if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).Left().Name().Alias()) {
|
||||||
xtop[i] = typecheck(n, ctxStmt)
|
xtop[i] = typecheck(n, ctxStmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ func Main(archInit func(*Arch)) {
|
|||||||
timings.Start("fe", "typecheck", "top2")
|
timings.Start("fe", "typecheck", "top2")
|
||||||
for i := 0; i < len(xtop); i++ {
|
for i := 0; i < len(xtop); i++ {
|
||||||
n := xtop[i]
|
n := xtop[i]
|
||||||
if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Alias() {
|
if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).Left().Name().Alias() {
|
||||||
xtop[i] = typecheck(n, ctxStmt)
|
xtop[i] = typecheck(n, ctxStmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -986,7 +986,7 @@ func typenamesym(t *types.Type) *types.Sym {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func typename(t *types.Type) ir.Node {
|
func typename(t *types.Type) *ir.AddrExpr {
|
||||||
s := typenamesym(t)
|
s := typenamesym(t)
|
||||||
if s.Def == nil {
|
if s.Def == nil {
|
||||||
n := ir.NewNameAt(src.NoXPos, s)
|
n := ir.NewNameAt(src.NoXPos, s)
|
||||||
@ -1002,7 +1002,7 @@ func typename(t *types.Type) ir.Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func itabname(t, itype *types.Type) ir.Node {
|
func itabname(t, itype *types.Type) *ir.AddrExpr {
|
||||||
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() {
|
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() {
|
||||||
base.Fatalf("itabname(%v, %v)", t, itype)
|
base.Fatalf("itabname(%v, %v)", t, itype)
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,11 @@ func (v *bottomUpVisitor) visit(n *ir.Func) uint32 {
|
|||||||
}
|
}
|
||||||
case ir.OCALLPART:
|
case ir.OCALLPART:
|
||||||
fn := ir.AsNode(callpartMethod(n).Nname)
|
fn := ir.AsNode(callpartMethod(n).Nname)
|
||||||
if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name().Defn != nil {
|
if fn != nil && fn.Op() == ir.ONAME {
|
||||||
if m := v.visit(fn.Name().Defn.(*ir.Func)); m < min {
|
if fn := fn.(*ir.Name); fn.Class() == ir.PFUNC && fn.Name().Defn != nil {
|
||||||
min = m
|
if m := v.visit(fn.Name().Defn.(*ir.Func)); m < min {
|
||||||
|
min = m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ir.OCLOSURE:
|
case ir.OCLOSURE:
|
||||||
|
@ -1234,7 +1234,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
|||||||
left := dot.Left() // skip final .M
|
left := dot.Left() // skip final .M
|
||||||
// TODO(mdempsky): Remove dependency on dotlist.
|
// TODO(mdempsky): Remove dependency on dotlist.
|
||||||
if !dotlist[0].field.Type.IsPtr() {
|
if !dotlist[0].field.Type.IsPtr() {
|
||||||
left = ir.Nod(ir.OADDR, left, nil)
|
left = nodAddr(left)
|
||||||
}
|
}
|
||||||
as := ir.Nod(ir.OAS, nthis, convnop(left, rcvr))
|
as := ir.Nod(ir.OAS, nthis, convnop(left, rcvr))
|
||||||
fn.PtrBody().Append(as)
|
fn.PtrBody().Append(as)
|
||||||
|
@ -2791,7 +2791,7 @@ func pushtype(nn ir.Node, t *types.Type) ir.Node {
|
|||||||
// For *T, return &T{...}.
|
// For *T, return &T{...}.
|
||||||
n.SetRight(ir.TypeNode(t.Elem()))
|
n.SetRight(ir.TypeNode(t.Elem()))
|
||||||
|
|
||||||
addr := ir.NodAt(n.Pos(), ir.OADDR, n, nil)
|
addr := nodAddrAt(n.Pos(), n)
|
||||||
addr.SetImplicit(true)
|
addr.SetImplicit(true)
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
@ -152,23 +152,27 @@ func initUniverse() {
|
|||||||
|
|
||||||
for _, s := range &builtinFuncs {
|
for _, s := range &builtinFuncs {
|
||||||
s2 := types.BuiltinPkg.Lookup(s.name)
|
s2 := types.BuiltinPkg.Lookup(s.name)
|
||||||
s2.Def = NewName(s2)
|
def := NewName(s2)
|
||||||
ir.AsNode(s2.Def).SetSubOp(s.op)
|
def.SetSubOp(s.op)
|
||||||
|
s2.Def = def
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range &unsafeFuncs {
|
for _, s := range &unsafeFuncs {
|
||||||
s2 := unsafepkg.Lookup(s.name)
|
s2 := unsafepkg.Lookup(s.name)
|
||||||
s2.Def = NewName(s2)
|
def := NewName(s2)
|
||||||
ir.AsNode(s2.Def).SetSubOp(s.op)
|
def.SetSubOp(s.op)
|
||||||
|
s2.Def = def
|
||||||
}
|
}
|
||||||
|
|
||||||
s = types.BuiltinPkg.Lookup("true")
|
s = types.BuiltinPkg.Lookup("true")
|
||||||
s.Def = nodbool(true)
|
b := nodbool(true)
|
||||||
ir.AsNode(s.Def).SetSym(lookup("true"))
|
b.(*ir.Name).SetSym(lookup("true"))
|
||||||
|
s.Def = b
|
||||||
|
|
||||||
s = types.BuiltinPkg.Lookup("false")
|
s = types.BuiltinPkg.Lookup("false")
|
||||||
s.Def = nodbool(false)
|
b = nodbool(false)
|
||||||
ir.AsNode(s.Def).SetSym(lookup("false"))
|
b.(*ir.Name).SetSym(lookup("false"))
|
||||||
|
s.Def = b
|
||||||
|
|
||||||
s = lookup("_")
|
s = lookup("_")
|
||||||
types.BlankSym = s
|
types.BlankSym = s
|
||||||
@ -187,8 +191,9 @@ func initUniverse() {
|
|||||||
|
|
||||||
types.Types[types.TNIL] = types.New(types.TNIL)
|
types.Types[types.TNIL] = types.New(types.TNIL)
|
||||||
s = types.BuiltinPkg.Lookup("nil")
|
s = types.BuiltinPkg.Lookup("nil")
|
||||||
s.Def = nodnil()
|
nnil := nodnil()
|
||||||
ir.AsNode(s.Def).SetSym(s)
|
nnil.(*ir.NilExpr).SetSym(s)
|
||||||
|
s.Def = nnil
|
||||||
|
|
||||||
s = types.BuiltinPkg.Lookup("iota")
|
s = types.BuiltinPkg.Lookup("iota")
|
||||||
s.Def = ir.NewIota(base.Pos, s)
|
s.Def = ir.NewIota(base.Pos, s)
|
||||||
|
@ -31,18 +31,20 @@ func evalunsafe(n ir.Node) int64 {
|
|||||||
base.Errorf("invalid expression %v", n)
|
base.Errorf("invalid expression %v", n)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
sel := n.Left().(*ir.SelectorExpr)
|
||||||
|
|
||||||
// Remember base of selector to find it back after dot insertion.
|
// Remember base of selector to find it back after dot insertion.
|
||||||
// Since r->left may be mutated by typechecking, check it explicitly
|
// Since r->left may be mutated by typechecking, check it explicitly
|
||||||
// first to track it correctly.
|
// first to track it correctly.
|
||||||
n.Left().SetLeft(typecheck(n.Left().Left(), ctxExpr))
|
sel.SetLeft(typecheck(sel.Left(), ctxExpr))
|
||||||
sbase := n.Left().Left()
|
sbase := sel.Left()
|
||||||
|
|
||||||
n.SetLeft(typecheck(n.Left(), ctxExpr))
|
tsel := typecheck(sel, ctxExpr)
|
||||||
if n.Left().Type() == nil {
|
n.SetLeft(tsel)
|
||||||
|
if tsel.Type() == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
switch n.Left().Op() {
|
switch tsel.Op() {
|
||||||
case ir.ODOT, ir.ODOTPTR:
|
case ir.ODOT, ir.ODOTPTR:
|
||||||
break
|
break
|
||||||
case ir.OCALLPART:
|
case ir.OCALLPART:
|
||||||
@ -55,7 +57,8 @@ func evalunsafe(n ir.Node) int64 {
|
|||||||
|
|
||||||
// Sum offsets for dots until we reach sbase.
|
// Sum offsets for dots until we reach sbase.
|
||||||
var v int64
|
var v int64
|
||||||
for r := n.Left(); r != sbase; r = r.Left() {
|
var next ir.Node
|
||||||
|
for r := tsel; r != sbase; r = next {
|
||||||
switch r.Op() {
|
switch r.Op() {
|
||||||
case ir.ODOTPTR:
|
case ir.ODOTPTR:
|
||||||
// For Offsetof(s.f), s may itself be a pointer,
|
// For Offsetof(s.f), s may itself be a pointer,
|
||||||
@ -68,8 +71,9 @@ func evalunsafe(n ir.Node) int64 {
|
|||||||
fallthrough
|
fallthrough
|
||||||
case ir.ODOT:
|
case ir.ODOT:
|
||||||
v += r.Offset()
|
v += r.Offset()
|
||||||
|
next = r.Left()
|
||||||
default:
|
default:
|
||||||
ir.Dump("unsafenmagic", n.Left())
|
ir.Dump("unsafenmagic", tsel)
|
||||||
base.Fatalf("impossible %v node after dot insertion", r.Op())
|
base.Fatalf("impossible %v node after dot insertion", r.Op())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user