1// Copyright 2021 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	"unsafe"
11)
12
13// These variables are used by the register assignment
14// algorithm in this file.
15//
16// They should be modified with care (no other reflect code
17// may be executing) and are generally only modified
18// when testing this package.
19//
20// They should never be set higher than their internal/abi
21// constant counterparts, because the system relies on a
22// structure that is at least large enough to hold the
23// registers the system supports.
24//
25// Currently they're set to zero because using the actual
26// constants will break every part of the toolchain that
27// uses reflect to call functions (e.g. go test, or anything
28// that uses text/template). The values that are currently
29// commented out there should be the actual values once
30// we're ready to use the register ABI everywhere.
31var (
32	intArgRegs   = abi.IntArgRegs
33	floatArgRegs = abi.FloatArgRegs
34	floatRegSize = uintptr(abi.EffectiveFloatRegSize)
35)
36
37// abiStep represents an ABI "instruction." Each instruction
38// describes one part of how to translate between a Go value
39// in memory and a call frame.
40type abiStep struct {
41	kind abiStepKind
42
43	// offset and size together describe a part of a Go value
44	// in memory.
45	offset uintptr
46	size   uintptr // size in bytes of the part
47
48	// These fields describe the ABI side of the translation.
49	stkOff uintptr // stack offset, used if kind == abiStepStack
50	ireg   int     // integer register index, used if kind == abiStepIntReg or kind == abiStepPointer
51	freg   int     // FP register index, used if kind == abiStepFloatReg
52}
53
54// abiStepKind is the "op-code" for an abiStep instruction.
55type abiStepKind int
56
57const (
58	abiStepBad      abiStepKind = iota
59	abiStepStack                // copy to/from stack
60	abiStepIntReg               // copy to/from integer register
61	abiStepPointer              // copy pointer to/from integer register
62	abiStepFloatReg             // copy to/from FP register
63)
64
65// abiSeq represents a sequence of ABI instructions for copying
66// from a series of reflect.Values to a call frame (for call arguments)
67// or vice-versa (for call results).
68//
69// An abiSeq should be populated by calling its addArg method.
70type abiSeq struct {
71	// steps is the set of instructions.
72	//
73	// The instructions are grouped together by whole arguments,
74	// with the starting index for the instructions
75	// of the i'th Go value available in valueStart.
76	//
77	// For instance, if this abiSeq represents 3 arguments
78	// passed to a function, then the 2nd argument's steps
79	// begin at steps[valueStart[1]].
80	//
81	// Because reflect accepts Go arguments in distinct
82	// Values and each Value is stored separately, each abiStep
83	// that begins a new argument will have its offset
84	// field == 0.
85	steps      []abiStep
86	valueStart []int
87
88	stackBytes   uintptr // stack space used
89	iregs, fregs int     // registers used
90}
91
92func (a *abiSeq) dump() {
93	for i, p := range a.steps {
94		println("part", i, p.kind, p.offset, p.size, p.stkOff, p.ireg, p.freg)
95	}
96	print("values ")
97	for _, i := range a.valueStart {
98		print(i, " ")
99	}
100	println()
101	println("stack", a.stackBytes)
102	println("iregs", a.iregs)
103	println("fregs", a.fregs)
104}
105
106// stepsForValue returns the ABI instructions for translating
107// the i'th Go argument or return value represented by this
108// abiSeq to the Go ABI.
109func (a *abiSeq) stepsForValue(i int) []abiStep {
110	s := a.valueStart[i]
111	var e int
112	if i == len(a.valueStart)-1 {
113		e = len(a.steps)
114	} else {
115		e = a.valueStart[i+1]
116	}
117	return a.steps[s:e]
118}
119
120// addArg extends the abiSeq with a new Go value of type t.
121//
122// If the value was stack-assigned, returns the single
123// abiStep describing that translation, and nil otherwise.
124func (a *abiSeq) addArg(t *abi.Type) *abiStep {
125	// We'll always be adding a new value, so do that first.
126	pStart := len(a.steps)
127	a.valueStart = append(a.valueStart, pStart)
128	if t.Size() == 0 {
129		// If the size of the argument type is zero, then
130		// in order to degrade gracefully into ABI0, we need
131		// to stack-assign this type. The reason is that
132		// although zero-sized types take up no space on the
133		// stack, they do cause the next argument to be aligned.
134		// So just do that here, but don't bother actually
135		// generating a new ABI step for it (there's nothing to
136		// actually copy).
137		//
138		// We cannot handle this in the recursive case of
139		// regAssign because zero-sized *fields* of a
140		// non-zero-sized struct do not cause it to be
141		// stack-assigned. So we need a special case here
142		// at the top.
143		a.stackBytes = align(a.stackBytes, uintptr(t.Align()))
144		return nil
145	}
146	// Hold a copy of "a" so that we can roll back if
147	// register assignment fails.
148	aOld := *a
149	if !a.regAssign(t, 0) {
150		// Register assignment failed. Roll back any changes
151		// and stack-assign.
152		*a = aOld
153		a.stackAssign(t.Size(), uintptr(t.Align()))
154		return &a.steps[len(a.steps)-1]
155	}
156	return nil
157}
158
159// addRcvr extends the abiSeq with a new method call
160// receiver according to the interface calling convention.
161//
162// If the receiver was stack-assigned, returns the single
163// abiStep describing that translation, and nil otherwise.
164// Returns true if the receiver is a pointer.
165func (a *abiSeq) addRcvr(rcvr *abi.Type) (*abiStep, bool) {
166	// The receiver is always one word.
167	a.valueStart = append(a.valueStart, len(a.steps))
168	var ok, ptr bool
169	if rcvr.IfaceIndir() || rcvr.Pointers() {
170		ok = a.assignIntN(0, goarch.PtrSize, 1, 0b1)
171		ptr = true
172	} else {
173		// TODO(mknyszek): Is this case even possible?
174		// The interface data work never contains a non-pointer
175		// value. This case was copied over from older code
176		// in the reflect package which only conditionally added
177		// a pointer bit to the reflect.(Value).Call stack frame's
178		// GC bitmap.
179		ok = a.assignIntN(0, goarch.PtrSize, 1, 0b0)
180		ptr = false
181	}
182	if !ok {
183		a.stackAssign(goarch.PtrSize, goarch.PtrSize)
184		return &a.steps[len(a.steps)-1], ptr
185	}
186	return nil, ptr
187}
188
189// regAssign attempts to reserve argument registers for a value of
190// type t, stored at some offset.
191//
192// It returns whether or not the assignment succeeded, but
193// leaves any changes it made to a.steps behind, so the caller
194// must undo that work by adjusting a.steps if it fails.
195//
196// This method along with the assign* methods represent the
197// complete register-assignment algorithm for the Go ABI.
198func (a *abiSeq) regAssign(t *abi.Type, offset uintptr) bool {
199	switch Kind(t.Kind()) {
200	case UnsafePointer, Pointer, Chan, Map, Func:
201		return a.assignIntN(offset, t.Size(), 1, 0b1)
202	case Bool, Int, Uint, Int8, Uint8, Int16, Uint16, Int32, Uint32, Uintptr:
203		return a.assignIntN(offset, t.Size(), 1, 0b0)
204	case Int64, Uint64:
205		switch goarch.PtrSize {
206		case 4:
207			return a.assignIntN(offset, 4, 2, 0b0)
208		case 8:
209			return a.assignIntN(offset, 8, 1, 0b0)
210		}
211	case Float32, Float64:
212		return a.assignFloatN(offset, t.Size(), 1)
213	case Complex64:
214		return a.assignFloatN(offset, 4, 2)
215	case Complex128:
216		return a.assignFloatN(offset, 8, 2)
217	case String:
218		return a.assignIntN(offset, goarch.PtrSize, 2, 0b01)
219	case Interface:
220		return a.assignIntN(offset, goarch.PtrSize, 2, 0b10)
221	case Slice:
222		return a.assignIntN(offset, goarch.PtrSize, 3, 0b001)
223	case Array:
224		tt := (*arrayType)(unsafe.Pointer(t))
225		switch tt.Len {
226		case 0:
227			// There's nothing to assign, so don't modify
228			// a.steps but succeed so the caller doesn't
229			// try to stack-assign this value.
230			return true
231		case 1:
232			return a.regAssign(tt.Elem, offset)
233		default:
234			return false
235		}
236	case Struct:
237		st := (*structType)(unsafe.Pointer(t))
238		for i := range st.Fields {
239			f := &st.Fields[i]
240			if !a.regAssign(f.Typ, offset+f.Offset) {
241				return false
242			}
243		}
244		return true
245	default:
246		print("t.Kind == ", t.Kind(), "\n")
247		panic("unknown type kind")
248	}
249	panic("unhandled register assignment path")
250}
251
252// assignIntN assigns n values to registers, each "size" bytes large,
253// from the data at [offset, offset+n*size) in memory. Each value at
254// [offset+i*size, offset+(i+1)*size) for i < n is assigned to the
255// next n integer registers.
256//
257// Bit i in ptrMap indicates whether the i'th value is a pointer.
258// n must be <= 8.
259//
260// Returns whether assignment succeeded.
261func (a *abiSeq) assignIntN(offset, size uintptr, n int, ptrMap uint8) bool {
262	if n > 8 || n < 0 {
263		panic("invalid n")
264	}
265	if ptrMap != 0 && size != goarch.PtrSize {
266		panic("non-empty pointer map passed for non-pointer-size values")
267	}
268	if a.iregs+n > intArgRegs {
269		return false
270	}
271	for i := 0; i < n; i++ {
272		kind := abiStepIntReg
273		if ptrMap&(uint8(1)<<i) != 0 {
274			kind = abiStepPointer
275		}
276		a.steps = append(a.steps, abiStep{
277			kind:   kind,
278			offset: offset + uintptr(i)*size,
279			size:   size,
280			ireg:   a.iregs,
281		})
282		a.iregs++
283	}
284	return true
285}
286
287// assignFloatN assigns n values to registers, each "size" bytes large,
288// from the data at [offset, offset+n*size) in memory. Each value at
289// [offset+i*size, offset+(i+1)*size) for i < n is assigned to the
290// next n floating-point registers.
291//
292// Returns whether assignment succeeded.
293func (a *abiSeq) assignFloatN(offset, size uintptr, n int) bool {
294	if n < 0 {
295		panic("invalid n")
296	}
297	if a.fregs+n > floatArgRegs || floatRegSize < size {
298		return false
299	}
300	for i := 0; i < n; i++ {
301		a.steps = append(a.steps, abiStep{
302			kind:   abiStepFloatReg,
303			offset: offset + uintptr(i)*size,
304			size:   size,
305			freg:   a.fregs,
306		})
307		a.fregs++
308	}
309	return true
310}
311
312// stackAssign reserves space for one value that is "size" bytes
313// large with alignment "alignment" to the stack.
314//
315// Should not be called directly; use addArg instead.
316func (a *abiSeq) stackAssign(size, alignment uintptr) {
317	a.stackBytes = align(a.stackBytes, alignment)
318	a.steps = append(a.steps, abiStep{
319		kind:   abiStepStack,
320		offset: 0, // Only used for whole arguments, so the memory offset is 0.
321		size:   size,
322		stkOff: a.stackBytes,
323	})
324	a.stackBytes += size
325}
326
327// abiDesc describes the ABI for a function or method.
328type abiDesc struct {
329	// call and ret represent the translation steps for
330	// the call and return paths of a Go function.
331	call, ret abiSeq
332
333	// These fields describe the stack space allocated
334	// for the call. stackCallArgsSize is the amount of space
335	// reserved for arguments but not return values. retOffset
336	// is the offset at which return values begin, and
337	// spill is the size in bytes of additional space reserved
338	// to spill argument registers into in case of preemption in
339	// reflectcall's stack frame.
340	stackCallArgsSize, retOffset, spill uintptr
341
342	// stackPtrs is a bitmap that indicates whether
343	// each word in the ABI stack space (stack-assigned
344	// args + return values) is a pointer. Used
345	// as the heap pointer bitmap for stack space
346	// passed to reflectcall.
347	stackPtrs *bitVector
348
349	// inRegPtrs is a bitmap whose i'th bit indicates
350	// whether the i'th integer argument register contains
351	// a pointer. Used by makeFuncStub and methodValueCall
352	// to make result pointers visible to the GC.
353	//
354	// outRegPtrs is the same, but for result values.
355	// Used by reflectcall to make result pointers visible
356	// to the GC.
357	inRegPtrs, outRegPtrs abi.IntArgRegBitmap
358}
359
360func (a *abiDesc) dump() {
361	println("ABI")
362	println("call")
363	a.call.dump()
364	println("ret")
365	a.ret.dump()
366	println("stackCallArgsSize", a.stackCallArgsSize)
367	println("retOffset", a.retOffset)
368	println("spill", a.spill)
369	print("inRegPtrs:")
370	dumpPtrBitMap(a.inRegPtrs)
371	println()
372	print("outRegPtrs:")
373	dumpPtrBitMap(a.outRegPtrs)
374	println()
375}
376
377func dumpPtrBitMap(b abi.IntArgRegBitmap) {
378	for i := 0; i < intArgRegs; i++ {
379		x := 0
380		if b.Get(i) {
381			x = 1
382		}
383		print(" ", x)
384	}
385}
386
387func newAbiDesc(t *funcType, rcvr *abi.Type) abiDesc {
388	// We need to add space for this argument to
389	// the frame so that it can spill args into it.
390	//
391	// The size of this space is just the sum of the sizes
392	// of each register-allocated type.
393	//
394	// TODO(mknyszek): Remove this when we no longer have
395	// caller reserved spill space.
396	spill := uintptr(0)
397
398	// Compute gc program & stack bitmap for stack arguments
399	stackPtrs := new(bitVector)
400
401	// Compute the stack frame pointer bitmap and register
402	// pointer bitmap for arguments.
403	inRegPtrs := abi.IntArgRegBitmap{}
404
405	// Compute abiSeq for input parameters.
406	var in abiSeq
407	if rcvr != nil {
408		stkStep, isPtr := in.addRcvr(rcvr)
409		if stkStep != nil {
410			if isPtr {
411				stackPtrs.append(1)
412			} else {
413				stackPtrs.append(0)
414			}
415		} else {
416			spill += goarch.PtrSize
417		}
418	}
419	for i, arg := range t.InSlice() {
420		stkStep := in.addArg(arg)
421		if stkStep != nil {
422			addTypeBits(stackPtrs, stkStep.stkOff, arg)
423		} else {
424			spill = align(spill, uintptr(arg.Align()))
425			spill += arg.Size()
426			for _, st := range in.stepsForValue(i) {
427				if st.kind == abiStepPointer {
428					inRegPtrs.Set(st.ireg)
429				}
430			}
431		}
432	}
433	spill = align(spill, goarch.PtrSize)
434
435	// From the input parameters alone, we now know
436	// the stackCallArgsSize and retOffset.
437	stackCallArgsSize := in.stackBytes
438	retOffset := align(in.stackBytes, goarch.PtrSize)
439
440	// Compute the stack frame pointer bitmap and register
441	// pointer bitmap for return values.
442	outRegPtrs := abi.IntArgRegBitmap{}
443
444	// Compute abiSeq for output parameters.
445	var out abiSeq
446	// Stack-assigned return values do not share
447	// space with arguments like they do with registers,
448	// so we need to inject a stack offset here.
449	// Fake it by artificially extending stackBytes by
450	// the return offset.
451	out.stackBytes = retOffset
452	for i, res := range t.OutSlice() {
453		stkStep := out.addArg(res)
454		if stkStep != nil {
455			addTypeBits(stackPtrs, stkStep.stkOff, res)
456		} else {
457			for _, st := range out.stepsForValue(i) {
458				if st.kind == abiStepPointer {
459					outRegPtrs.Set(st.ireg)
460				}
461			}
462		}
463	}
464	// Undo the faking from earlier so that stackBytes
465	// is accurate.
466	out.stackBytes -= retOffset
467	return abiDesc{in, out, stackCallArgsSize, retOffset, spill, stackPtrs, inRegPtrs, outRegPtrs}
468}
469
470// intFromReg loads an argSize sized integer from reg and places it at to.
471//
472// argSize must be non-zero, fit in a register, and a power-of-two.
473func intFromReg(r *abi.RegArgs, reg int, argSize uintptr, to unsafe.Pointer) {
474	memmove(to, r.IntRegArgAddr(reg, argSize), argSize)
475}
476
477// intToReg loads an argSize sized integer and stores it into reg.
478//
479// argSize must be non-zero, fit in a register, and a power-of-two.
480func intToReg(r *abi.RegArgs, reg int, argSize uintptr, from unsafe.Pointer) {
481	memmove(r.IntRegArgAddr(reg, argSize), from, argSize)
482}
483
484// floatFromReg loads a float value from its register representation in r.
485//
486// argSize must be 4 or 8.
487func floatFromReg(r *abi.RegArgs, reg int, argSize uintptr, to unsafe.Pointer) {
488	switch argSize {
489	case 4:
490		*(*float32)(to) = archFloat32FromReg(r.Floats[reg])
491	case 8:
492		*(*float64)(to) = *(*float64)(unsafe.Pointer(&r.Floats[reg]))
493	default:
494		panic("bad argSize")
495	}
496}
497
498// floatToReg stores a float value in its register representation in r.
499//
500// argSize must be either 4 or 8.
501func floatToReg(r *abi.RegArgs, reg int, argSize uintptr, from unsafe.Pointer) {
502	switch argSize {
503	case 4:
504		r.Floats[reg] = archFloat32ToReg(*(*float32)(from))
505	case 8:
506		r.Floats[reg] = *(*uint64)(from)
507	default:
508		panic("bad argSize")
509	}
510}
511