cmplen = tlen
}
- fn := typecheck.LookupRuntime("memequal")
- fn = typecheck.SubstArgTypes(fn, types.Types[types.TUINT8], types.Types[types.TUINT8])
+ fn := typecheck.LookupRuntime("memequal", types.Types[types.TUINT8], types.Types[types.TUINT8])
call := typecheck.Call(base.Pos, fn, []ir.Node{sptr, tptr, ir.Copy(cmplen)}, false).(*ir.CallExpr)
cmp := ir.NewBinaryExpr(base.Pos, ir.OEQ, slen, tlen)
func eqmemfunc(size int64, t *types.Type) (fn *ir.Name, needsize bool) {
switch size {
- default:
- fn = typecheck.LookupRuntime("memequal")
- needsize = true
case 1, 2, 4, 8, 16:
buf := fmt.Sprintf("memequal%d", int(size)*8)
- fn = typecheck.LookupRuntime(buf)
+ return typecheck.LookupRuntime(buf, t, t), false
}
- fn = typecheck.SubstArgTypes(fn, t, t)
- return fn, needsize
+ return typecheck.LookupRuntime("memequal", t, t), true
}
}
func runtimeHashFor(name string, t *types.Type) *ir.Name {
- n := typecheck.LookupRuntime(name)
- n = typecheck.SubstArgTypes(n, t)
- return n
+ return typecheck.LookupRuntime(name, t)
}
// hashfor returns the function to compute the hash of a value of type t.
func EqFor(t *types.Type) (ir.Node, bool) {
switch a, _ := types.AlgType(t); a {
case types.AMEM:
- n := typecheck.LookupRuntime("memequal")
- n = typecheck.SubstArgTypes(n, t, t)
- return n, true
+ return typecheck.LookupRuntime("memequal", t, t), true
case types.ASPECIAL:
fn := eqFunc(t)
return fn.Nname, false
}
func hashmem(t *types.Type) ir.Node {
- n := typecheck.LookupRuntime("memhash")
- n = typecheck.SubstArgTypes(n, t)
- return n
+ return typecheck.LookupRuntime("memhash", t)
}
"cmd/internal/obj"
)
-func LookupRuntime(name string) *ir.Name {
+// LookupRuntime returns a function or variable declared in
+// _builtin/runtime.go. If types_ is non-empty, successive occurrences
+// of the "any" placeholder type will be substituted.
+func LookupRuntime(name string, types_ ...*types.Type) *ir.Name {
s := ir.Pkgs.Runtime.Lookup(name)
if s == nil || s.Def == nil {
base.Fatalf("LookupRuntime: can't find runtime.%s", name)
}
- return s.Def.(*ir.Name)
+ n := s.Def.(*ir.Name)
+ if len(types_) != 0 {
+ n = substArgTypes(n, types_...)
+ }
+ return n
}
// SubstArgTypes substitutes the given list of types for
// successive occurrences of the "any" placeholder in the
// type syntax expression n.Type.
-// The result of SubstArgTypes MUST be assigned back to old, e.g.
-//
-// n.Left = SubstArgTypes(n.Left, t1, t2)
-func SubstArgTypes(old *ir.Name, types_ ...*types.Type) *ir.Name {
+func substArgTypes(old *ir.Name, types_ ...*types.Type) *ir.Name {
for _, t := range types_ {
types.CalcSize(t)
}
nif.Body = []ir.Node{ir.NewAssignStmt(base.Pos, s, slice)}
// func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) []T
- fn := typecheck.LookupRuntime("growslice")
- fn = typecheck.SubstArgTypes(fn, elemtype, elemtype)
+ fn := typecheck.LookupRuntime("growslice", elemtype, elemtype)
// else { s = growslice(oldPtr, newLen, oldCap, num, T) }
call := mkcall1(fn, s.Type(), nif.PtrInit(), oldPtr, newLen, oldCap, num, reflectdata.TypePtrAt(base.Pos, elemtype))
ir.CurFunc.SetWBPos(n.Pos())
// instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int
- fn := typecheck.LookupRuntime("typedslicecopy")
- fn = typecheck.SubstArgTypes(fn, l1.Type().Elem(), l2.Type().Elem())
+ fn := typecheck.LookupRuntime("typedslicecopy", l1.Type().Elem(), l2.Type().Elem())
ptr1, len1 := backingArrayPtrLen(cheapExpr(slice, &nodes))
ptr2, len2 := backingArrayPtrLen(l2)
ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, reflectdata.AppendElemRType(base.Pos, n), ptr1, len1, ptr2, len2)
ptr1, len1 := backingArrayPtrLen(cheapExpr(slice, &nodes))
ptr2, len2 := backingArrayPtrLen(l2)
- fn := typecheck.LookupRuntime("slicecopy")
- fn = typecheck.SubstArgTypes(fn, ptr1.Type().Elem(), ptr2.Type().Elem())
+ fn := typecheck.LookupRuntime("slicecopy", ptr1.Type().Elem(), ptr2.Type().Elem())
ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, ptr1, len1, ptr2, len2, ir.NewInt(base.Pos, elemtype.Size()))
} else {
// memmove(&s[idx], &l2[0], len(l2)*sizeof(T))
nwid = ir.NewBinaryExpr(base.Pos, ir.OMUL, nwid, ir.NewInt(base.Pos, elemtype.Size()))
// instantiate func memmove(to *any, frm *any, length uintptr)
- fn := typecheck.LookupRuntime("memmove")
- fn = typecheck.SubstArgTypes(fn, elemtype, elemtype)
+ fn := typecheck.LookupRuntime("memmove", elemtype, elemtype)
ncopy = mkcall1(fn, nil, &nodes, addr, sptr, nwid)
}
ln := append(nodes, ncopy)
nif.Body = []ir.Node{ir.NewAssignStmt(base.Pos, s, nt)}
// instantiate growslice(oldPtr *any, newLen, oldCap, num int, typ *type) []any
- fn := typecheck.LookupRuntime("growslice")
- fn = typecheck.SubstArgTypes(fn, elemtype, elemtype)
+ fn := typecheck.LookupRuntime("growslice", elemtype, elemtype)
// else { s = growslice(s.ptr, n, s.cap, l2, T) }
nif.Else = []ir.Node{
ir.NewAssignStmt(base.Pos, s, slice),
}
- fn := typecheck.LookupRuntime("growslice") // growslice(ptr *T, newLen, oldCap, num int, <type>) (ret []T)
- fn = typecheck.SubstArgTypes(fn, s.Type().Elem(), s.Type().Elem())
+ // growslice(ptr *T, newLen, oldCap, num int, <type>) (ret []T)
+ fn := typecheck.LookupRuntime("growslice", s.Type().Elem(), s.Type().Elem())
// else { s = growslice(s.ptr, n, s.cap, a, T) }
nif.Else = []ir.Node{
// walkClose walks an OCLOSE node.
func walkClose(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
// cannot use chanfn - closechan takes any, not chan any
- fn := typecheck.LookupRuntime("closechan")
- fn = typecheck.SubstArgTypes(fn, n.X.Type())
+ fn := typecheck.LookupRuntime("closechan", n.X.Type())
return mkcall1(fn, nil, init, n.X)
}
n.Y = cheapExpr(n.Y, init)
ptrR, lenR := backingArrayPtrLen(n.Y)
- fn := typecheck.LookupRuntime("slicecopy")
- fn = typecheck.SubstArgTypes(fn, ptrL.Type().Elem(), ptrR.Type().Elem())
+ fn := typecheck.LookupRuntime("slicecopy", ptrL.Type().Elem(), ptrR.Type().Elem())
return mkcall1(fn, n.Type(), init, ptrL, lenL, ptrR, lenR, ir.NewInt(base.Pos, n.X.Type().Elem().Size()))
}
ne.Likely = true
l = append(l, ne)
- fn := typecheck.LookupRuntime("memmove")
- fn = typecheck.SubstArgTypes(fn, nl.Type().Elem(), nl.Type().Elem())
+ fn := typecheck.LookupRuntime("memmove", nl.Type().Elem(), nl.Type().Elem())
nwid := ir.Node(typecheck.TempAt(base.Pos, ir.CurFunc, types.Types[types.TUINTPTR]))
setwid := ir.NewAssignStmt(base.Pos, nwid, typecheck.Conv(nlen, types.Types[types.TUINTPTR]))
ne.Body.Append(setwid)
}
// Call runtime.makehmap to allocate an
// hmap on the heap and initialize hmap's hash0 field.
- fn := typecheck.LookupRuntime("makemap_small")
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem())
+ fn := typecheck.LookupRuntime("makemap_small", t.Key(), t.Elem())
return mkcall1(fn, n.Type(), init)
}
argtype = types.Types[types.TINT]
}
- fn := typecheck.LookupRuntime(fnname)
- fn = typecheck.SubstArgTypes(fn, hmapType, t.Key(), t.Elem())
+ fn := typecheck.LookupRuntime(fnname, hmapType, t.Key(), t.Elem())
return mkcall1(fn, n.Type(), init, reflectdata.MakeMapRType(base.Pos, n), typecheck.Conv(hint, argtype), h)
}
init.Append(r)
// instantiate memmove(to *any, frm *any, size uintptr)
- fn = typecheck.LookupRuntime("memmove")
- fn = typecheck.SubstArgTypes(fn, t.Elem(), t.Elem())
+ fn = typecheck.LookupRuntime("memmove", t.Elem(), t.Elem())
ncopy := mkcall1(fn, nil, init, ir.NewUnaryExpr(base.Pos, ir.OSPTR, s), copyptr, size)
init.Append(walkExpr(typecheck.Stmt(ncopy), init))
switch n.Type().Kind() {
case types.TINTER:
if n.Type().IsEmptyInterface() {
- on = typecheck.LookupRuntime("printeface")
+ on = typecheck.LookupRuntime("printeface", n.Type())
} else {
- on = typecheck.LookupRuntime("printiface")
+ on = typecheck.LookupRuntime("printiface", n.Type())
}
- on = typecheck.SubstArgTypes(on, n.Type()) // any-1
case types.TPTR:
if n.Type().Elem().NotInHeap() {
on = typecheck.LookupRuntime("printuintptr")
}
fallthrough
case types.TCHAN, types.TMAP, types.TFUNC, types.TUNSAFEPTR:
- on = typecheck.LookupRuntime("printpointer")
- on = typecheck.SubstArgTypes(on, n.Type()) // any-1
+ on = typecheck.LookupRuntime("printpointer", n.Type())
case types.TSLICE:
- on = typecheck.LookupRuntime("printslice")
- on = typecheck.SubstArgTypes(on, n.Type()) // any-1
+ on = typecheck.LookupRuntime("printslice", n.Type())
case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
if types.RuntimeSymName(n.Type().Sym()) == "hex" {
on = typecheck.LookupRuntime("printhex")
}
func writebarrierfn(name string, l *types.Type, r *types.Type) ir.Node {
- fn := typecheck.LookupRuntime(name)
- fn = typecheck.SubstArgTypes(fn, l, r)
- return fn
+ return typecheck.LookupRuntime(name, l, r)
}
// isRuneCount reports whether n is of the form len([]rune(string)).
// Time to do an allocation. We'll call into the runtime for that.
fnname, argType, needsaddr := dataWordFuncName(fromType)
- fn := typecheck.LookupRuntime(fnname)
+ var fn *ir.Name
var args []ir.Node
if needsaddr {
if !ir.IsAddressable(n) {
n = copyExpr(n, fromType, init)
}
- fn = typecheck.SubstArgTypes(fn, fromType)
+ fn = typecheck.LookupRuntime(fnname, fromType)
args = []ir.Node{reflectdata.ConvIfaceSrcRType(base.Pos, conv), typecheck.NodAddr(n)}
} else {
// Use a specialized conversion routine that takes the type being
// converted by value, not by pointer.
+ fn = typecheck.LookupRuntime(fnname)
var arg ir.Node
switch {
case fromType == argType:
keysym := th.Field(0).Sym
elemsym := th.Field(1).Sym // ditto
- fn := typecheck.LookupRuntime("mapiterinit")
-
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem(), th)
+ fn := typecheck.LookupRuntime("mapiterinit", t.Key(), t.Elem(), th)
init = append(init, mkcallstmt1(fn, reflectdata.RangeMapRType(base.Pos, nrange), ha, typecheck.NodAddr(hit)))
nfor.Cond = ir.NewBinaryExpr(base.Pos, ir.ONE, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, keysym), typecheck.NodNil())
- fn = typecheck.LookupRuntime("mapiternext")
- fn = typecheck.SubstArgTypes(fn, th)
+ fn = typecheck.LookupRuntime("mapiternext", th)
nfor.Post = mkcallstmt1(fn, typecheck.NodAddr(hit))
key := ir.NewStarExpr(base.Pos, typecheck.ConvNop(ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, keysym), types.NewPtr(t.Key())))
t := m.Type()
// instantiate mapclear(typ *type, hmap map[any]any)
- fn := typecheck.LookupRuntime("mapclear")
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem())
+ fn := typecheck.LookupRuntime("mapclear", t.Key(), t.Elem())
n := mkcallstmt1(fn, rtyp, m)
return walkStmt(typecheck.Stmt(n))
}
if !t.IsChan() {
base.Fatalf("chanfn %v", t)
}
- fn := typecheck.LookupRuntime(name)
switch n {
- default:
- base.Fatalf("chanfn %d", n)
case 1:
- fn = typecheck.SubstArgTypes(fn, t.Elem())
+ return typecheck.LookupRuntime(name, t.Elem())
case 2:
- fn = typecheck.SubstArgTypes(fn, t.Elem(), t.Elem())
+ return typecheck.LookupRuntime(name, t.Elem(), t.Elem())
}
- return fn
+ base.Fatalf("chanfn %d", n)
+ return nil
}
func mapfn(name string, t *types.Type, isfat bool) ir.Node {
if !t.IsMap() {
base.Fatalf("mapfn %v", t)
}
- fn := typecheck.LookupRuntime(name)
if mapfast(t) == mapslow || isfat {
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem(), t.Key(), t.Elem())
- } else {
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem(), t.Elem())
+ return typecheck.LookupRuntime(name, t.Key(), t.Elem(), t.Key(), t.Elem())
}
- return fn
+ return typecheck.LookupRuntime(name, t.Key(), t.Elem(), t.Elem())
}
func mapfndel(name string, t *types.Type) ir.Node {
if !t.IsMap() {
base.Fatalf("mapfn %v", t)
}
- fn := typecheck.LookupRuntime(name)
if mapfast(t) == mapslow {
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem(), t.Key())
- } else {
- fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem())
+ return typecheck.LookupRuntime(name, t.Key(), t.Elem(), t.Key())
}
- return fn
+ return typecheck.LookupRuntime(name, t.Key(), t.Elem())
}
const (