github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/reflect/abi.go (about)

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