return r
}
-func subtype(stp **Type, t *Type, d int) bool {
-loop:
- st := *stp
- if st == nil {
- return false
+// substArgTypes substitutes the given list of types for
+// successive occurrences of the "any" placeholder in the
+// type syntax expression n.Type.
+func substArgTypes(n *Node, types ...*Type) {
+ for _, t := range types {
+ dowidth(t)
}
-
- d++
- if d >= 10 {
- return false
+ substAny(&n.Type, &types)
+ if len(types) > 0 {
+ Fatal("substArgTypes: too many argument types")
}
+}
- switch st.Etype {
- default:
- return false
-
- case TPTR32,
- TPTR64,
- TCHAN,
- TARRAY:
- stp = &st.Type
- goto loop
-
- case TANY:
- if st.Copyany == 0 {
- return false
- }
- *stp = t
-
- case TMAP:
- if subtype(&st.Down, t, d) {
- break
+// substAny walks *tp, replacing instances of "any" with successive
+// elements removed from types.
+func substAny(tp **Type, types *[]*Type) {
+ for {
+ t := *tp
+ if t == nil {
+ return
}
- stp = &st.Type
- goto loop
-
- case TFUNC:
- for {
- if subtype(&st.Type, t, d) {
- break
- }
- if subtype(&st.Type.Down.Down, t, d) {
- break
+ if t.Etype == TANY && t.Copyany != 0 {
+ if len(*types) == 0 {
+ Fatal("substArgTypes: not enough argument types")
}
- if subtype(&st.Type.Down, t, d) {
- break
- }
- return false
+ *tp = (*types)[0]
+ *types = (*types)[1:]
}
- case TSTRUCT:
- for st = st.Type; st != nil; st = st.Down {
- if subtype(&st.Type, t, d) {
- return true
+ switch t.Etype {
+ case TPTR32, TPTR64, TCHAN, TARRAY:
+ tp = &t.Type
+ continue
+
+ case TMAP:
+ substAny(&t.Down, types)
+ tp = &t.Type
+ continue
+
+ case TFUNC:
+ substAny(&t.Type, types)
+ substAny(&t.Type.Down.Down, types)
+ substAny(&t.Type.Down, types)
+
+ case TSTRUCT:
+ for t = t.Type; t != nil; t = t.Down {
+ substAny(&t.Type, types)
}
}
- return false
+ return
}
-
- return true
}
/*
return false
}
-func argtype(on *Node, t *Type) {
- dowidth(t)
- if !subtype(&on.Type, t, 0) {
- Fatal("argtype: failed %v %v\n", Nconv(on, 0), Tconv(t, 0))
- }
-}
-
func shallow(t *Type) *Type {
if t == nil {
return nil
fn = syslook("memequal", 1)
*needsize = 1
- case 1,
- 2,
- 4,
- 8,
- 16:
+ case 1, 2, 4, 8, 16:
buf := fmt.Sprintf("memequal%d", int(size)*8)
fn = syslook(buf, 1)
*needsize = 0
}
- argtype(fn, type_)
- argtype(fn, type_)
+ substArgTypes(fn, type_, type_)
return fn
}
buf := fmt.Sprintf("assert%s2%s", from, to)
fn := syslook(buf, 1)
- argtype(fn, r.Left.Type)
- argtype(fn, r.Type)
+ substArgTypes(fn, r.Left.Type, r.Type)
n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
walkexpr(&n, init)
buf := fmt.Sprintf("assert%s2%s2", from, to)
fn := syslook(buf, 1)
- argtype(fn, r.Left.Type)
- argtype(fn, r.Type)
+ substArgTypes(fn, r.Left.Type, r.Type)
t := Types[TBOOL]
ok := n.List.Next.N
}
}
- argtype(fn, n.Left.Type)
- argtype(fn, n.Type)
+ substArgTypes(fn, n.Left.Type, n.Type)
dowidth(fn.Type)
n = Nod(OCALL, fn, nil)
n.List = ll
case OCLOSE:
fn := syslook("closechan", 1)
- argtype(fn, n.Left.Type)
+ substArgTypes(fn, n.Left.Type)
n = mkcall1(fn, nil, init, n.Left)
goto ret
r = Nod(OADDR, var_, nil)
}
- argtype(fn, hmap(t)) // hmap buffer
- argtype(fn, mapbucket(t)) // bucket buffer
- argtype(fn, t.Down) // key type
- argtype(fn, t.Type) // value type
+ substArgTypes(fn, hmap(t), mapbucket(t), t.Down, t.Type)
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
goto ret
// makeslice(t *Type, nel int64, max int64) (ary []any)
fn := syslook("makeslice", 1)
- argtype(fn, t.Type) // any-1
+ substArgTypes(fn, t.Type) // any-1
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
}
n.Right = cheapexpr(n.Right, init)
n.Left = cheapexpr(n.Left, init)
- argtype(fn, n.Right.Type)
- argtype(fn, n.Left.Type)
+ substArgTypes(fn, n.Right.Type, n.Left.Type)
r := mkcall1(fn, n.Type, init, n.Left, n.Right)
if n.Etype == ONE {
r = Nod(ONOT, r, nil)
} else {
on = syslook("printiface", 1)
}
- argtype(on, n.Type) // any-1
+ substArgTypes(on, n.Type) // any-1
} else if Isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR {
on = syslook("printpointer", 1)
- argtype(on, n.Type) // any-1
+ substArgTypes(on, n.Type) // any-1
} else if Isslice(n.Type) {
on = syslook("printslice", 1)
- argtype(on, n.Type) // any-1
+ substArgTypes(on, n.Type) // any-1
} else if Isint[et] {
if et == TUINT64 {
if (t.Sym.Pkg == Runtimepkg || compiling_runtime != 0) && t.Sym.Name == "hex" {
func callnew(t *Type) *Node {
dowidth(t)
fn := syslook("newobject", 1)
- argtype(fn, t)
+ substArgTypes(fn, t)
return mkcall1(fn, Ptrto(t), nil, typename(t))
}
Fatal("chanfn %v", Tconv(t, 0))
}
fn := syslook(name, 1)
- for i := 0; i < n; i++ {
- argtype(fn, t.Type)
+ switch n {
+ default:
+ Fatal("chanfn %d", n)
+ case 1:
+ substArgTypes(fn, t.Type)
+ case 2:
+ substArgTypes(fn, t.Type, t.Type)
}
return fn
}
Fatal("mapfn %v", Tconv(t, 0))
}
fn := syslook(name, 1)
- argtype(fn, t.Down)
- argtype(fn, t.Type)
- argtype(fn, t.Down)
- argtype(fn, t.Type)
+ substArgTypes(fn, t.Down, t.Type, t.Down, t.Type)
return fn
}
Fatal("mapfn %v", Tconv(t, 0))
}
fn := syslook(name, 1)
- argtype(fn, t.Down)
- argtype(fn, t.Type)
- argtype(fn, t.Down)
+ substArgTypes(fn, t.Down, t.Type, t.Down)
return fn
}
func writebarrierfn(name string, l *Type, r *Type) *Node {
fn := syslook(name, 1)
- argtype(fn, l)
- argtype(fn, r)
+ substArgTypes(fn, l, r)
return fn
}
// instantiate growslice(Type*, []any, int) []any
fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
- argtype(fn, s.Type.Type) // 1 old []any
- argtype(fn, s.Type.Type) // 2 ret []any
+ substArgTypes(fn, s.Type.Type, s.Type.Type)
// s = growslice(T, s, n)
nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
nptr1.Etype = 1
nptr2 := l2
fn := syslook("typedslicecopy", 1)
- argtype(fn, l1.Type)
- argtype(fn, l2.Type)
+ substArgTypes(fn, l1.Type, l2.Type)
nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2)
l = list(l, nt)
} else if flag_race != 0 {
} else {
fn = syslook("slicecopy", 1)
}
- argtype(fn, l1.Type)
- argtype(fn, l2.Type)
+ substArgTypes(fn, l1.Type, l2.Type)
nt := mkcall1(fn, Types[TINT], &l, nptr1, nptr2, Nodintconst(s.Type.Type.Width))
l = list(l, nt)
} else {
nptr2 := Nod(OSPTR, l2, nil)
fn := syslook("memmove", 1)
- argtype(fn, s.Type.Type) // 1 old []any
- argtype(fn, s.Type.Type) // 2 ret []any
+ substArgTypes(fn, s.Type.Type, s.Type.Type)
nwid := cheapexpr(conv(Nod(OLEN, l2, nil), Types[TUINTPTR]), &l)
nx.Ntest = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
fn := syslook("growslice", 1) // growslice(<type>, old []T, n int) (ret []T)
- argtype(fn, ns.Type.Type) // 1 old []any
- argtype(fn, ns.Type.Type) // 2 ret []any
+ substArgTypes(fn, ns.Type.Type, ns.Type.Type)
nx.Nbody = list1(Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, na)))
} else {
fn = syslook("slicecopy", 1)
}
- argtype(fn, n.Left.Type)
- argtype(fn, n.Right.Type)
+ substArgTypes(fn, n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width))
}
// Call memmove.
fn := syslook("memmove", 1)
- argtype(fn, nl.Type.Type)
- argtype(fn, nl.Type.Type)
+ substArgTypes(fn, nl.Type.Type, nl.Type.Type)
nwid := temp(Types[TUINTPTR])
l = list(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR])))
nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width))
if a == AMEM {
n := syslook("memequal", 1)
- argtype(n, t)
- argtype(n, t)
+ substArgTypes(n, t, t)
*needsize = 1
return n
}