github.com/goplus/reflectx@v1.2.2/cmd/icall_gen/icall_regabi.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  func writeRegAbi(filename string, pkgName string, size int) error {
    14  	dir, f := filepath.Split(filename)
    15  	if dir != "" {
    16  		err := os.MkdirAll(dir, 0755)
    17  		if err != nil {
    18  			return fmt.Errorf("make dir %v error: %v", dir, err)
    19  		}
    20  	}
    21  	gofile := filepath.Join(dir, strings.Replace(f, ".go", "_regabi.go", 1))
    22  	var buf bytes.Buffer
    23  	r := strings.NewReplacer("$pkgname", pkgName, "$max_size", strconv.Itoa(size))
    24  	buf.WriteString(r.Replace(icall_regabi))
    25  
    26  	var ar []string
    27  	for i := 0; i < size; i++ {
    28  		buf.WriteString(fmt.Sprintf("func f%v()\n", i))
    29  		ar = append(ar, fmt.Sprintf("f%v", i))
    30  	}
    31  	buf.WriteString(fmt.Sprintf(`
    32  var (
    33  	icall_fn = []func(){%v}
    34  )
    35  `, strings.Join(ar, ",")))
    36  
    37  	err := ioutil.WriteFile(gofile, buf.Bytes(), 0644)
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	asm_amd64_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_amd64.s", 1))
    43  	asm_arm64_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_arm64.s", 1))
    44  	asm_ppc64x_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_ppc64x.s", 1))
    45  	asm_riscv64_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_riscv64.s", 1))
    46  	asm_go121_amd64_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_go121_amd64.s", 1))
    47  	asm_go121_arm64_file := filepath.Join(dir, strings.Replace(f, ".go", "_regabi_go121_arm64.s", 1))
    48  	fnWrite := func(filename string, tmpl string, size int) error {
    49  		var buf bytes.Buffer
    50  		buf.WriteString(tmpl)
    51  		for i := 0; i < size; i++ {
    52  			buf.WriteString(fmt.Sprintf("MAKE_FUNC_FN(·f%v,%v)\n", i, i))
    53  		}
    54  		return ioutil.WriteFile(filename, buf.Bytes(), 0644)
    55  	}
    56  	err = fnWrite(asm_amd64_file, regabi_amd64, size)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	err = fnWrite(asm_arm64_file, regabi_arm64, size)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	err = fnWrite(asm_go121_amd64_file, regabi_go121_amd64, size)
    65  	if err != nil {
    66  		return err
    67  	}
    68  	err = fnWrite(asm_go121_arm64_file, regabi_go121_arm64, size)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	err = fnWrite(asm_ppc64x_file, regabi_ppc64x, size)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	err = fnWrite(asm_riscv64_file, regabi_riscv64, size)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	return nil
    81  }
    82  
    83  var icall_regabi = `//go:build ((go1.17 && goexperiment.regabireflect) || (go1.19 && goexperiment.regabiargs) || (go1.18 && amd64) || (go1.19 && arm64) || (go1.19 && ppc64) || (go1.19 && ppc64le) || (go1.20 && riscv64)) && (!js || (js && wasm))
    84  // +build go1.17,goexperiment.regabireflect go1.19,goexperiment.regabiargs go1.18,amd64 go1.19,arm64 go1.19,ppc64 go1.19,ppc64le go1.20,riscv64
    85  // +build !js js,wasm
    86  
    87  package $pkgname
    88  
    89  import (
    90  	"reflect"
    91  	"unsafe"
    92  
    93  	"github.com/goplus/reflectx/abi"
    94  )
    95  
    96  const capacity = $max_size
    97  
    98  type methodUsed struct {
    99  	fun reflect.Value
   100  	ptr unsafe.Pointer
   101  }
   102  
   103  type provider struct {
   104  	used map[int]*methodUsed
   105  }
   106  
   107  //go:linkname callReflect reflect.callReflect
   108  func callReflect(ctxt unsafe.Pointer, frame unsafe.Pointer, retValid *bool, r unsafe.Pointer)
   109  
   110  //go:linkname moveMakeFuncArgPtrs reflect.moveMakeFuncArgPtrs
   111  func moveMakeFuncArgPtrs(ctx unsafe.Pointer, r unsafe.Pointer)
   112  
   113  func i_x(c unsafe.Pointer, frame unsafe.Pointer, retValid *bool, r unsafe.Pointer, index int) {
   114  	ptr := mp.used[index].ptr
   115  	moveMakeFuncArgPtrs(ptr, r)
   116  	callReflect(ptr, frame, retValid, r)
   117  }
   118  
   119  func spillArgs()
   120  func unspillArgs()
   121  
   122  func (p *provider) Insert(info *abi.MethodInfo) (unsafe.Pointer, int) {
   123  	var index = -1
   124  	for i := 0; i < capacity; i++ {
   125  		if _, ok := p.used[i]; !ok {
   126  			index = i
   127  			break
   128  		}
   129  	}
   130  	if index == -1 {
   131  		return nil, -1
   132  	}
   133  	var fn reflect.Value
   134  	if (!info.Pointer && !info.OnePtr) || info.Indirect {
   135  		ftyp := info.Func.Type()
   136  		numIn := ftyp.NumIn()
   137  		numOut := ftyp.NumOut()
   138  		in := make([]reflect.Type, numIn, numIn)
   139  		out := make([]reflect.Type, numOut, numOut)
   140  		in[0] = reflect.PtrTo(info.Type)
   141  		for i := 1; i < numIn; i++ {
   142  			in[i] = ftyp.In(i)
   143  		}
   144  		for i := 0; i < numOut; i++ {
   145  			out[i] = ftyp.Out(i)
   146  		}
   147  		ftyp = reflect.FuncOf(in, out, info.Variadic)
   148  		if info.Variadic {
   149  			fn = reflect.MakeFunc(ftyp, func(args []reflect.Value) []reflect.Value {
   150  				args[0] = args[0].Elem()
   151  				return info.Func.CallSlice(args)
   152  			})
   153  		} else {
   154  			fn = reflect.MakeFunc(ftyp, func(args []reflect.Value) []reflect.Value {
   155  				args[0] = args[0].Elem()
   156  				return info.Func.Call(args)
   157  			})
   158  		}
   159  	} else {
   160  		fn = info.Func
   161  	}
   162  	p.used[index] = &methodUsed{
   163  		fun: fn,
   164  		ptr: (*struct{ typ, ptr unsafe.Pointer })(unsafe.Pointer(&fn)).ptr,
   165  	}
   166  	icall := icall_fn[index]
   167  	return unsafe.Pointer(reflect.ValueOf(icall).Pointer()), index
   168  }
   169  
   170  func (p *provider) Remove(indexs []int) {
   171  	for _, n := range indexs {
   172  		delete(p.used, n)
   173  	}
   174  }
   175  
   176  func (p *provider) Available() int {
   177  	return capacity - len(p.used)
   178  }
   179  
   180  func (p *provider) Used() int {
   181  	return len(p.used)
   182  }
   183  
   184  func (p *provider) Cap() int {
   185  	return capacity
   186  }
   187  
   188  func (p *provider) Clear() {
   189  	p.used = make(map[int]*methodUsed)
   190  }
   191  
   192  var (
   193  	mp = &provider{
   194  		used: make(map[int]*methodUsed),
   195  	}
   196  )
   197  
   198  func init() {
   199  	abi.AddMethodProvider(mp)
   200  }
   201  
   202  `
   203  
   204  var regabi_go121_amd64 = `//go:build go1.21
   205  // +build go1.21
   206  
   207  // Copyright 2012 The Go Authors. All rights reserved.
   208  // Use of this source code is governed by a BSD-style
   209  // license that can be found in the LICENSE file.
   210  
   211  #include "textflag.h"
   212  #include "funcdata.h"
   213  #include "go_asm.h"
   214  
   215  // The frames of each of the two functions below contain two locals, at offsets
   216  // that are known to the runtime.
   217  //
   218  // The first local is a bool called retValid with a whole pointer-word reserved
   219  // for it on the stack. The purpose of this word is so that the runtime knows
   220  // whether the stack-allocated return space contains valid values for stack
   221  // scanning.
   222  //
   223  // The second local is an abi.RegArgs value whose offset is also known to the
   224  // runtime, so that a stack map for it can be constructed, since it contains
   225  // pointers visible to the GC.
   226  #define LOCAL_RETVALID 32
   227  #define LOCAL_REGARGS 40
   228  
   229  // makeFuncStub is the code half of the function returned by MakeFunc.
   230  // See the comment on the declaration of makeFuncStub in makefunc.go
   231  // for more details.
   232  // No arg size here; runtime pulls arg map out of the func value.
   233  // This frame contains two locals. See the comment above LOCAL_RETVALID.
   234  // amd64 argframe+8(FP) offset to func from method
   235  #define MAKE_FUNC_FN(NAME,INDEX)		\
   236  TEXT NAME(SB),(NOSPLIT|WRAPPER),$312		\
   237  	NO_LOCAL_POINTERS		\
   238  	LEAQ	LOCAL_REGARGS(SP), R12		\
   239  	CALL	runtime·spillArgs(SB)		\
   240  	MOVQ	24(SP), DX		\
   241  	MOVQ	DX, 0(SP)		\
   242  	LEAQ	argframe+16(FP), CX		\
   243  	MOVQ	CX, 8(SP)		\
   244  	MOVB	$0, LOCAL_RETVALID(SP)		\
   245  	LEAQ	LOCAL_RETVALID(SP), AX		\
   246  	MOVQ	AX, 16(SP)		\
   247  	LEAQ	LOCAL_REGARGS(SP), AX		\
   248  	MOVQ	AX, 24(SP)		\
   249  	MOVQ	$INDEX, AX		\
   250  	MOVQ	AX, 32(SP)		\
   251  	CALL	·i_x(SB)		\
   252  	LEAQ	LOCAL_REGARGS(SP), R12		\
   253  	CALL	runtime·unspillArgs(SB)		\
   254  	RET
   255  
   256  `
   257  
   258  var regabi_go121_arm64 = `//go:build go1.21
   259  // +build go1.21
   260  
   261  // Copyright 2012 The Go Authors. All rights reserved.
   262  // Use of this source code is governed by a BSD-style
   263  // license that can be found in the LICENSE file.
   264  
   265  #include "textflag.h"
   266  #include "funcdata.h"
   267  
   268  // The frames of each of the two functions below contain two locals, at offsets
   269  // that are known to the runtime.
   270  //
   271  // The first local is a bool called retValid with a whole pointer-word reserved
   272  // for it on the stack. The purpose of this word is so that the runtime knows
   273  // whether the stack-allocated return space contains valid values for stack
   274  // scanning.
   275  //
   276  // The second local is an abi.RegArgs value whose offset is also known to the
   277  // runtime, so that a stack map for it can be constructed, since it contains
   278  // pointers visible to the GC.
   279  #define LOCAL_RETVALID 40
   280  #define LOCAL_REGARGS 48
   281  
   282  // The frame size of the functions below is
   283  // 32 (args of callReflect) + 8 (bool + padding) + 392 (abi.RegArgs) = 432.
   284  
   285  // makeFuncStub is the code half of the function returned by MakeFunc.
   286  // See the comment on the declaration of makeFuncStub in makefunc.go
   287  // for more details.
   288  // No arg size here, runtime pulls arg map out of the func value.
   289  #define MAKE_FUNC_FN(NAME,INDEX)		\
   290  TEXT NAME(SB),(NOSPLIT|WRAPPER),$432		\
   291  	NO_LOCAL_POINTERS		\
   292  	ADD	$LOCAL_REGARGS, RSP, R20		\
   293  	CALL	runtime·spillArgs(SB)		\
   294  	MOVD	32(RSP), R26		\
   295  	MOVD	R26, 16(RSP)		\
   296  	MOVD	$argframe+0(FP), R3		\
   297  	MOVD	R3, 16(RSP)		\
   298  	MOVB	$0, LOCAL_RETVALID(RSP)		\
   299  	ADD	$LOCAL_RETVALID, RSP, R3		\
   300  	MOVD	R3, 24(RSP)		\
   301  	ADD	$LOCAL_REGARGS, RSP, R3		\
   302  	MOVD	R3, 32(RSP)		\
   303  	MOVD	$INDEX, R3		\
   304  	MOVD	R3, 40(RSP)		\
   305  	CALL	·i_x(SB)		\
   306  	ADD	$LOCAL_REGARGS, RSP, R20		\
   307  	CALL	runtime·unspillArgs(SB)		\
   308  	RET
   309  
   310  `
   311  
   312  var regabi_amd64 = `//go:build (go1.17 && goexperiment.regabireflect) || (go1.18 && !go1.21)
   313  // +build go1.17,goexperiment.regabireflect go1.18,!go1.21
   314  
   315  // Copyright 2012 The Go Authors. All rights reserved.
   316  // Use of this source code is governed by a BSD-style
   317  // license that can be found in the LICENSE file.
   318  
   319  #include "textflag.h"
   320  #include "funcdata.h"
   321  #include "go_asm.h"
   322  
   323  // The frames of each of the two functions below contain two locals, at offsets
   324  // that are known to the runtime.
   325  //
   326  // The first local is a bool called retValid with a whole pointer-word reserved
   327  // for it on the stack. The purpose of this word is so that the runtime knows
   328  // whether the stack-allocated return space contains valid values for stack
   329  // scanning.
   330  //
   331  // The second local is an abi.RegArgs value whose offset is also known to the
   332  // runtime, so that a stack map for it can be constructed, since it contains
   333  // pointers visible to the GC.
   334  #define LOCAL_RETVALID 32
   335  #define LOCAL_REGARGS 40
   336  
   337  TEXT ·spillArgs(SB),NOSPLIT,$0-0
   338  	MOVQ AX, 0(R12)
   339  	MOVQ BX, 8(R12)
   340  	MOVQ CX, 16(R12)
   341  	MOVQ DI, 24(R12)
   342  	MOVQ SI, 32(R12)
   343  	MOVQ R8, 40(R12)
   344  	MOVQ R9, 48(R12)
   345  	MOVQ R10, 56(R12)
   346  	MOVQ R11, 64(R12)
   347  	MOVQ X0, 72(R12)
   348  	MOVQ X1, 80(R12)
   349  	MOVQ X2, 88(R12)
   350  	MOVQ X3, 96(R12)
   351  	MOVQ X4, 104(R12)
   352  	MOVQ X5, 112(R12)
   353  	MOVQ X6, 120(R12)
   354  	MOVQ X7, 128(R12)
   355  	MOVQ X8, 136(R12)
   356  	MOVQ X9, 144(R12)
   357  	MOVQ X10, 152(R12)
   358  	MOVQ X11, 160(R12)
   359  	MOVQ X12, 168(R12)
   360  	MOVQ X13, 176(R12)
   361  	MOVQ X14, 184(R12)
   362  	RET
   363  
   364  // unspillArgs loads args into registers from a *internal/abi.RegArgs in R12.
   365  TEXT ·unspillArgs(SB),NOSPLIT,$0-0
   366  	MOVQ 0(R12), AX
   367  	MOVQ 8(R12), BX
   368  	MOVQ 16(R12), CX
   369  	MOVQ 24(R12), DI
   370  	MOVQ 32(R12), SI
   371  	MOVQ 40(R12), R8
   372  	MOVQ 48(R12), R9
   373  	MOVQ 56(R12), R10
   374  	MOVQ 64(R12), R11
   375  	MOVQ 72(R12), X0
   376  	MOVQ 80(R12), X1
   377  	MOVQ 88(R12), X2
   378  	MOVQ 96(R12), X3
   379  	MOVQ 104(R12), X4
   380  	MOVQ 112(R12), X5
   381  	MOVQ 120(R12), X6
   382  	MOVQ 128(R12), X7
   383  	MOVQ 136(R12), X8
   384  	MOVQ 144(R12), X9
   385  	MOVQ 152(R12), X10
   386  	MOVQ 160(R12), X11
   387  	MOVQ 168(R12), X12
   388  	MOVQ 176(R12), X13
   389  	MOVQ 184(R12), X14
   390  	RET
   391  
   392  // makeFuncStub is the code half of the function returned by MakeFunc.
   393  // See the comment on the declaration of makeFuncStub in makefunc.go
   394  // for more details.
   395  // No arg size here; runtime pulls arg map out of the func value.
   396  // This frame contains two locals. See the comment above LOCAL_RETVALID.
   397  #define MAKE_FUNC_FN(NAME,INDEX)		\
   398  TEXT NAME(SB),(NOSPLIT|WRAPPER),$312		\
   399  	NO_LOCAL_POINTERS		\
   400  	LEAQ	LOCAL_REGARGS(SP), R12		\
   401  	CALL	·spillArgs(SB)		\
   402  	MOVQ	24(SP), DX		\
   403  	MOVQ	DX, 0(SP)		\
   404  	LEAQ	argframe+8(FP), CX		\
   405  	MOVQ	CX, 8(SP)		\
   406  	MOVB	$0, LOCAL_RETVALID(SP)		\
   407  	LEAQ	LOCAL_RETVALID(SP), AX		\
   408  	MOVQ	AX, 16(SP)		\
   409  	LEAQ	LOCAL_REGARGS(SP), AX		\
   410  	MOVQ	AX, 24(SP)		\
   411  	MOVQ	$INDEX, AX		\
   412  	MOVQ	AX, 32(SP)		\
   413  	CALL	·i_x(SB)		\
   414  	LEAQ	LOCAL_REGARGS(SP), R12		\
   415  	CALL	·unspillArgs(SB)		\
   416  	RET
   417  
   418  `
   419  
   420  var regabi_arm64 = `//go:build (go1.18 && goexperiment.regabireflect) || (go1.19 && !go1.21)
   421  // +build go1.18,goexperiment.regabireflect go1.19,!go1.21
   422  
   423  // Copyright 2012 The Go Authors. All rights reserved.
   424  // Use of this source code is governed by a BSD-style
   425  // license that can be found in the LICENSE file.
   426  
   427  #include "textflag.h"
   428  #include "funcdata.h"
   429  
   430  // The frames of each of the two functions below contain two locals, at offsets
   431  // that are known to the runtime.
   432  //
   433  // The first local is a bool called retValid with a whole pointer-word reserved
   434  // for it on the stack. The purpose of this word is so that the runtime knows
   435  // whether the stack-allocated return space contains valid values for stack
   436  // scanning.
   437  //
   438  // The second local is an abi.RegArgs value whose offset is also known to the
   439  // runtime, so that a stack map for it can be constructed, since it contains
   440  // pointers visible to the GC.
   441  #define LOCAL_RETVALID 40
   442  #define LOCAL_REGARGS 48
   443  
   444  // The frame size of the functions below is
   445  // 32 (args of callReflect) + 8 (bool + padding) + 392 (abi.RegArgs) = 432.
   446  
   447  // makeFuncStub is the code half of the function returned by MakeFunc.
   448  // See the comment on the declaration of makeFuncStub in makefunc.go
   449  // for more details.
   450  // No arg size here, runtime pulls arg map out of the func value.
   451  #define MAKE_FUNC_FN(NAME,INDEX)		\
   452  TEXT NAME(SB),(NOSPLIT|WRAPPER),$432		\
   453  	NO_LOCAL_POINTERS		\
   454  	ADD	$LOCAL_REGARGS, RSP, R20		\
   455  	CALL	runtime·spillArgs(SB)		\
   456  	MOVD	32(RSP), R26		\
   457  	MOVD	R26, 8(RSP)		\
   458  	MOVD	$argframe+0(FP), R3		\
   459  	MOVD	R3, 16(RSP)		\
   460  	MOVB	$0, LOCAL_RETVALID(RSP)		\
   461  	ADD	$LOCAL_RETVALID, RSP, R3		\
   462  	MOVD	R3, 24(RSP)		\
   463  	ADD	$LOCAL_REGARGS, RSP, R3		\
   464  	MOVD	R3, 32(RSP)		\
   465  	MOVD	$INDEX, R3		\
   466  	MOVD	R3, 40(RSP)		\
   467  	CALL	·i_x(SB)		\
   468  	ADD	$LOCAL_REGARGS, RSP, R20		\
   469  	CALL	runtime·unspillArgs(SB)		\
   470  	RET
   471  
   472  `
   473  
   474  var regabi_ppc64x = `//go:build ((go1.18 && goexperiment.regabireflect) || go1.19) && (ppc64 || ppc64le)
   475  // +build go1.18,goexperiment.regabireflect go1.19
   476  // +build ppc64 ppc64le
   477  
   478  // Copyright 2012 The Go Authors. All rights reserved.
   479  // Use of this source code is governed by a BSD-style
   480  // license that can be found in the LICENSE file.
   481  
   482  #include "textflag.h"
   483  #include "funcdata.h"
   484  #include "asm_ppc64x.h"
   485  
   486  // The frames of each of the two functions below contain two locals, at offsets
   487  // that are known to the runtime.
   488  //
   489  // The first local is a bool called retValid with a whole pointer-word reserved
   490  // for it on the stack. The purpose of this word is so that the runtime knows
   491  // whether the stack-allocated return space contains valid values for stack
   492  // scanning.
   493  //
   494  // The second local is an abi.RegArgs value whose offset is also known to the
   495  // runtime, so that a stack map for it can be constructed, since it contains
   496  // pointers visible to the GC.
   497  
   498  #define LOCAL_RETVALID 32+FIXED_FRAME
   499  #define LOCAL_REGARGS 40+FIXED_FRAME
   500  
   501  // The frame size of the functions below is
   502  // 32 (args of callReflect) + 8 (bool + padding) + 296 (abi.RegArgs) = 336.
   503  
   504  // makeFuncStub is the code half of the function returned by MakeFunc.
   505  // See the comment on the declaration of makeFuncStub in makefunc.go
   506  // for more details.
   507  // No arg size here, runtime pulls arg map out of the func value.
   508  #define MAKE_FUNC_FN(NAME,INDEX)		\
   509  TEXT NAME(SB),(NOSPLIT|WRAPPER),$336		\
   510  	NO_LOCAL_POINTERS		\
   511  	ADD	$LOCAL_REGARGS, R1, R20		\
   512  	CALL	runtime·spillArgs(SB)		\
   513  	MOVD	FIXED_FRAME+32(R1), R11			\
   514  	MOVD	R11, FIXED_FRAME+0(R1)		\
   515  	MOVD	$argframe+0(FP), R3		\
   516  	MOVD	R3, FIXED_FRAME+8(R1)		\
   517  	ADD	$LOCAL_RETVALID, R1, R3		\
   518  	MOVB	R0, (R3)		\
   519  	MOVD	R3, FIXED_FRAME+16(R1)			\
   520  	ADD     $LOCAL_REGARGS, R1, R3		\
   521  	MOVD	R3, FIXED_FRAME+24(R1)		\
   522  	MOVD	$INDEX, R3		\
   523  	MOVD	R3, FIXED_FRAME+32(R1)		\
   524  	BL	·i_x(SB)		\
   525  	ADD	$LOCAL_REGARGS, R1, R20		\
   526  	CALL	runtime·unspillArgs(SB)		\
   527  	RET
   528  
   529  `
   530  
   531  var regabi_riscv64 = `//go:build (go1.19 && goexperiment.regabiargs) || go1.20
   532  // +build go1.19,goexperiment.regabiargs go1.20
   533  
   534  // Copyright 2019 The Go Authors. All rights reserved.
   535  // Use of this source code is governed by a BSD-style
   536  // license that can be found in the LICENSE file.
   537  
   538  #include "textflag.h"
   539  #include "funcdata.h"
   540  
   541  // The frames of each of the two functions below contain two locals, at offsets
   542  // that are known to the runtime.
   543  //
   544  // The first local is a bool called retValid with a whole pointer-word reserved
   545  // for it on the stack. The purpose of this word is so that the runtime knows
   546  // whether the stack-allocated return space contains valid values for stack
   547  // scanning.
   548  //
   549  // The second local is an abi.RegArgs value whose offset is also known to the
   550  // runtime, so that a stack map for it can be constructed, since it contains
   551  // pointers visible to the GC.
   552  #define LOCAL_RETVALID 40
   553  #define LOCAL_REGARGS 48
   554  
   555  // The frame size of the functions below is
   556  // 32 (args of callReflect/callMethod) + (8 bool with padding) + 392 (abi.RegArgs) = 432.
   557  
   558  // makeFuncStub is the code half of the function returned by MakeFunc.
   559  // See the comment on the declaration of makeFuncStub in makefunc.go
   560  // for more details.
   561  // No arg size here, runtime pulls arg map out of the func value.
   562  #define MAKE_FUNC_FN(NAME,INDEX)		\
   563  TEXT NAME(SB),(NOSPLIT|WRAPPER),$432	\
   564  	NO_LOCAL_POINTERS	\
   565  	ADD	$LOCAL_REGARGS, SP, X25 	\
   566  	CALL	runtime·spillArgs(SB)	\
   567  	MOV	32(SP), CTXT 		\
   568  	MOV	CTXT, 8(SP)		\
   569  	MOV	$argframe+0(FP), T0		\
   570  	MOV	T0, 16(SP)		\
   571  	MOV	ZERO, LOCAL_RETVALID(SP)		\
   572  	ADD	$LOCAL_RETVALID, SP, T1		\
   573  	MOV	T1, 24(SP)		\
   574  	ADD	$LOCAL_REGARGS, SP, T1		\
   575  	MOV	T1, 32(SP)		\
   576  	MOV	$INDEX, T1		\
   577  	MOV	T1, 40(SP)		\
   578  	CALL	·i_x(SB)		\
   579  	ADD	$LOCAL_REGARGS, SP, X25 		\
   580  	CALL	runtime·unspillArgs(SB)		\
   581  	RET
   582  
   583  `