1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package reflect
6
7import (
8	"internal/abi"
9	"internal/goarch"
10	"sync"
11	"unsafe"
12)
13
14// MakeRO returns a copy of v with the read-only flag set.
15func MakeRO(v Value) Value {
16	v.flag |= flagStickyRO
17	return v
18}
19
20// IsRO reports whether v's read-only flag is set.
21func IsRO(v Value) bool {
22	return v.flag&flagStickyRO != 0
23}
24
25var CallGC = &callGC
26
27// FuncLayout calls funcLayout and returns a subset of the results for testing.
28//
29// Bitmaps like stack, gc, inReg, and outReg are expanded such that each bit
30// takes up one byte, so that writing out test cases is a little clearer.
31// If ptrs is false, gc will be nil.
32func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, stack, gc, inReg, outReg []byte, ptrs bool) {
33	var ft *abi.Type
34	var abid abiDesc
35	if rcvr != nil {
36		ft, _, abid = funcLayout((*funcType)(unsafe.Pointer(t.common())), rcvr.common())
37	} else {
38		ft, _, abid = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), nil)
39	}
40	// Extract size information.
41	argSize = abid.stackCallArgsSize
42	retOffset = abid.retOffset
43	frametype = toType(ft)
44
45	// Expand stack pointer bitmap into byte-map.
46	for i := uint32(0); i < abid.stackPtrs.n; i++ {
47		stack = append(stack, abid.stackPtrs.data[i/8]>>(i%8)&1)
48	}
49
50	// Expand register pointer bitmaps into byte-maps.
51	bool2byte := func(b bool) byte {
52		if b {
53			return 1
54		}
55		return 0
56	}
57	for i := 0; i < intArgRegs; i++ {
58		inReg = append(inReg, bool2byte(abid.inRegPtrs.Get(i)))
59		outReg = append(outReg, bool2byte(abid.outRegPtrs.Get(i)))
60	}
61	if ft.Kind_&abi.KindGCProg != 0 {
62		panic("can't handle gc programs")
63	}
64
65	// Expand frame type's GC bitmap into byte-map.
66	ptrs = ft.Pointers()
67	if ptrs {
68		nptrs := ft.PtrBytes / goarch.PtrSize
69		gcdata := ft.GcSlice(0, (nptrs+7)/8)
70		for i := uintptr(0); i < nptrs; i++ {
71			gc = append(gc, gcdata[i/8]>>(i%8)&1)
72		}
73	}
74	return
75}
76
77func TypeLinks() []string {
78	var r []string
79	sections, offset := typelinks()
80	for i, offs := range offset {
81		rodata := sections[i]
82		for _, off := range offs {
83			typ := (*rtype)(resolveTypeOff(rodata, off))
84			r = append(r, typ.String())
85		}
86	}
87	return r
88}
89
90var GCBits = gcbits
91
92func gcbits(any) []byte // provided by runtime
93
94func MapBucketOf(x, y Type) Type {
95	return toType(bucketOf(x.common(), y.common()))
96}
97
98func CachedBucketOf(m Type) Type {
99	t := m.(*rtype)
100	if Kind(t.t.Kind_&abi.KindMask) != Map {
101		panic("not map")
102	}
103	tt := (*mapType)(unsafe.Pointer(t))
104	return toType(tt.Bucket)
105}
106
107type EmbedWithUnexpMeth struct{}
108
109func (EmbedWithUnexpMeth) f() {}
110
111type pinUnexpMeth interface {
112	f()
113}
114
115var pinUnexpMethI = pinUnexpMeth(EmbedWithUnexpMeth{})
116
117func FirstMethodNameBytes(t Type) *byte {
118	_ = pinUnexpMethI
119
120	ut := t.uncommon()
121	if ut == nil {
122		panic("type has no methods")
123	}
124	m := ut.Methods()[0]
125	mname := t.(*rtype).nameOff(m.Name)
126	if *mname.DataChecked(0, "name flag field")&(1<<2) == 0 {
127		panic("method name does not have pkgPath *string")
128	}
129	return mname.Bytes
130}
131
132type OtherPkgFields struct {
133	OtherExported   int
134	otherUnexported int
135}
136
137func IsExported(t Type) bool {
138	typ := t.(*rtype)
139	n := typ.nameOff(typ.t.Str)
140	return n.IsExported()
141}
142
143func ResolveReflectName(s string) {
144	resolveReflectName(newName(s, "", false, false))
145}
146
147type Buffer struct {
148	buf []byte
149}
150
151func clearLayoutCache() {
152	layoutCache = sync.Map{}
153}
154
155func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, oldFloatSize uintptr) {
156	oldInts = intArgRegs
157	oldFloats = floatArgRegs
158	oldFloatSize = floatRegSize
159	intArgRegs = ints
160	floatArgRegs = floats
161	floatRegSize = floatSize
162	clearLayoutCache()
163	return
164}
165
166var MethodValueCallCodePtr = methodValueCallCodePtr
167
168var InternalIsZero = isZero
169
170var IsRegularMemory = isRegularMemory
171