github.com/AndrienkoAleksandr/go@v0.0.19/src/intern/abi/type.go (about)

     1  // Copyright 2023 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 abi
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  // Type is the runtime representation of a Go type.
    12  //
    13  // Type is also referenced implicitly
    14  // (in the form of expressions involving constants and arch.PtrSize)
    15  // in cmd/compile/internal/reflectdata/reflect.go
    16  // and cmd/link/internal/ld/decodesym.go
    17  // (e.g. data[2*arch.PtrSize+4] references the TFlag field)
    18  // unsafe.OffsetOf(Type{}.TFlag) cannot be used directly in those
    19  // places because it varies with cross compilation and experiments.
    20  type Type struct {
    21  	Size_       uintptr
    22  	PtrBytes    uintptr // number of (prefix) bytes in the type that can contain pointers
    23  	Hash        uint32  // hash of type; avoids computation in hash tables
    24  	TFlag       TFlag   // extra type information flags
    25  	Align_      uint8   // alignment of variable with this type
    26  	FieldAlign_ uint8   // alignment of struct field with this type
    27  	Kind_       uint8   // enumeration for C
    28  	// function for comparing objects of this type
    29  	// (ptr to object A, ptr to object B) -> ==?
    30  	Equal func(unsafe.Pointer, unsafe.Pointer) bool
    31  	// GCData stores the GC type data for the garbage collector.
    32  	// If the KindGCProg bit is set in kind, GCData is a GC program.
    33  	// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    34  	GCData    *byte
    35  	Str       NameOff // string form
    36  	PtrToThis TypeOff // type for pointer to this type, may be zero
    37  }
    38  
    39  // A Kind represents the specific kind of type that a Type represents.
    40  // The zero Kind is not a valid kind.
    41  type Kind uint
    42  
    43  const (
    44  	Invalid Kind = iota
    45  	Bool
    46  	Int
    47  	Int8
    48  	Int16
    49  	Int32
    50  	Int64
    51  	Uint
    52  	Uint8
    53  	Uint16
    54  	Uint32
    55  	Uint64
    56  	Uintptr
    57  	Float32
    58  	Float64
    59  	Complex64
    60  	Complex128
    61  	Array
    62  	Chan
    63  	Func
    64  	Interface
    65  	Map
    66  	Pointer
    67  	Slice
    68  	String
    69  	Struct
    70  	UnsafePointer
    71  )
    72  
    73  const (
    74  	// TODO (khr, drchase) why aren't these in TFlag?  Investigate, fix if possible.
    75  	KindDirectIface = 1 << 5
    76  	KindGCProg      = 1 << 6 // Type.gc points to GC program
    77  	KindMask        = (1 << 5) - 1
    78  )
    79  
    80  // TFlag is used by a Type to signal what extra type information is
    81  // available in the memory directly following the Type value.
    82  type TFlag uint8
    83  
    84  const (
    85  	// TFlagUncommon means that there is a data with a type, UncommonType,
    86  	// just beyond the shared-per-type common data.  That is, the data
    87  	// for struct types will store their UncommonType at one offset, the
    88  	// data for interface types will store their UncommonType at a different
    89  	// offset.  UncommonType is always accessed via a pointer that is computed
    90  	// using trust-us-we-are-the-implementors pointer arithmetic.
    91  	//
    92  	// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
    93  	// then t has UncommonType data and it can be accessed as:
    94  	//
    95  	//	type structTypeUncommon struct {
    96  	//		structType
    97  	//		u UncommonType
    98  	//	}
    99  	//	u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
   100  	TFlagUncommon TFlag = 1 << 0
   101  
   102  	// TFlagExtraStar means the name in the str field has an
   103  	// extraneous '*' prefix. This is because for most types T in
   104  	// a program, the type *T also exists and reusing the str data
   105  	// saves binary size.
   106  	TFlagExtraStar TFlag = 1 << 1
   107  
   108  	// TFlagNamed means the type has a name.
   109  	TFlagNamed TFlag = 1 << 2
   110  
   111  	// TFlagRegularMemory means that equal and hash functions can treat
   112  	// this type as a single region of t.size bytes.
   113  	TFlagRegularMemory TFlag = 1 << 3
   114  )
   115  
   116  // NameOff is the offset to a name from moduledata.types.  See resolveNameOff in runtime.
   117  type NameOff int32
   118  
   119  // TypeOff is the offset to a type from moduledata.types.  See resolveTypeOff in runtime.
   120  type TypeOff int32
   121  
   122  // TextOff is an offset from the top of a text section.  See (rtype).textOff in runtime.
   123  type TextOff int32
   124  
   125  // String returns the name of k.
   126  func (k Kind) String() string {
   127  	if int(k) < len(kindNames) {
   128  		return kindNames[k]
   129  	}
   130  	return kindNames[0]
   131  }
   132  
   133  var kindNames = []string{
   134  	Invalid:       "invalid",
   135  	Bool:          "bool",
   136  	Int:           "int",
   137  	Int8:          "int8",
   138  	Int16:         "int16",
   139  	Int32:         "int32",
   140  	Int64:         "int64",
   141  	Uint:          "uint",
   142  	Uint8:         "uint8",
   143  	Uint16:        "uint16",
   144  	Uint32:        "uint32",
   145  	Uint64:        "uint64",
   146  	Uintptr:       "uintptr",
   147  	Float32:       "float32",
   148  	Float64:       "float64",
   149  	Complex64:     "complex64",
   150  	Complex128:    "complex128",
   151  	Array:         "array",
   152  	Chan:          "chan",
   153  	Func:          "func",
   154  	Interface:     "interface",
   155  	Map:           "map",
   156  	Pointer:       "ptr",
   157  	Slice:         "slice",
   158  	String:        "string",
   159  	Struct:        "struct",
   160  	UnsafePointer: "unsafe.Pointer",
   161  }
   162  
   163  func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
   164  
   165  func (t *Type) HasName() bool {
   166  	return t.TFlag&TFlagNamed != 0
   167  }
   168  
   169  func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
   170  
   171  // IfaceIndir reports whether t is stored indirectly in an interface value.
   172  func (t *Type) IfaceIndir() bool {
   173  	return t.Kind_&KindDirectIface == 0
   174  }
   175  
   176  // isDirectIface reports whether t is stored directly in an interface value.
   177  func (t *Type) IsDirectIface() bool {
   178  	return t.Kind_&KindDirectIface != 0
   179  }
   180  
   181  func (t *Type) GcSlice(begin, end uintptr) []byte {
   182  	return unsafeSliceFor(t.GCData, int(end))[begin:]
   183  }
   184  
   185  // Method on non-interface type
   186  type Method struct {
   187  	Name NameOff // name of method
   188  	Mtyp TypeOff // method type (without receiver)
   189  	Ifn  TextOff // fn used in interface call (one-word receiver)
   190  	Tfn  TextOff // fn used for normal method call
   191  }
   192  
   193  // UncommonType is present only for defined types or types with methods
   194  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   195  // Using a pointer to this struct reduces the overall size required
   196  // to describe a non-defined type with no methods.
   197  type UncommonType struct {
   198  	PkgPath NameOff // import path; empty for built-in types like int, string
   199  	Mcount  uint16  // number of methods
   200  	Xcount  uint16  // number of exported methods
   201  	Moff    uint32  // offset from this uncommontype to [mcount]Method
   202  	_       uint32  // unused
   203  }
   204  
   205  func (t *UncommonType) Methods() []Method {
   206  	if t.Mcount == 0 {
   207  		return nil
   208  	}
   209  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
   210  }
   211  
   212  func (t *UncommonType) ExportedMethods() []Method {
   213  	if t.Xcount == 0 {
   214  		return nil
   215  	}
   216  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
   217  }
   218  
   219  // addChecked returns p+x.
   220  //
   221  // The whySafe string is ignored, so that the function still inlines
   222  // as efficiently as p+x, but all call sites should use the string to
   223  // record why the addition is safe, which is to say why the addition
   224  // does not cause x to advance to the very end of p's allocation
   225  // and therefore point incorrectly at the next block in memory.
   226  func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   227  	return unsafe.Pointer(uintptr(p) + x)
   228  }
   229  
   230  // Imethod represents a method on an interface type
   231  type Imethod struct {
   232  	Name NameOff // name of method
   233  	Typ  TypeOff // .(*FuncType) underneath
   234  }
   235  
   236  // ArrayType represents a fixed array type.
   237  type ArrayType struct {
   238  	Type
   239  	Elem  *Type // array element type
   240  	Slice *Type // slice type
   241  	Len   uintptr
   242  }
   243  
   244  // Len returns the length of t if t is an array type, otherwise 0
   245  func (t *Type) Len() int {
   246  	if t.Kind() == Array {
   247  		return int((*ArrayType)(unsafe.Pointer(t)).Len)
   248  	}
   249  	return 0
   250  }
   251  
   252  func (t *Type) Common() *Type {
   253  	return t
   254  }
   255  
   256  type ChanDir int
   257  
   258  const (
   259  	RecvDir    ChanDir = 1 << iota         // <-chan
   260  	SendDir                                // chan<-
   261  	BothDir            = RecvDir | SendDir // chan
   262  	InvalidDir ChanDir = 0
   263  )
   264  
   265  // ChanType represents a channel type
   266  type ChanType struct {
   267  	Type
   268  	Elem *Type
   269  	Dir  ChanDir
   270  }
   271  
   272  type structTypeUncommon struct {
   273  	StructType
   274  	u UncommonType
   275  }
   276  
   277  // ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
   278  func (t *Type) ChanDir() ChanDir {
   279  	if t.Kind() == Chan {
   280  		ch := (*ChanType)(unsafe.Pointer(t))
   281  		return ch.Dir
   282  	}
   283  	return InvalidDir
   284  }
   285  
   286  // Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
   287  func (t *Type) Uncommon() *UncommonType {
   288  	if t.TFlag&TFlagUncommon == 0 {
   289  		return nil
   290  	}
   291  	switch t.Kind() {
   292  	case Struct:
   293  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   294  	case Pointer:
   295  		type u struct {
   296  			PtrType
   297  			u UncommonType
   298  		}
   299  		return &(*u)(unsafe.Pointer(t)).u
   300  	case Func:
   301  		type u struct {
   302  			FuncType
   303  			u UncommonType
   304  		}
   305  		return &(*u)(unsafe.Pointer(t)).u
   306  	case Slice:
   307  		type u struct {
   308  			SliceType
   309  			u UncommonType
   310  		}
   311  		return &(*u)(unsafe.Pointer(t)).u
   312  	case Array:
   313  		type u struct {
   314  			ArrayType
   315  			u UncommonType
   316  		}
   317  		return &(*u)(unsafe.Pointer(t)).u
   318  	case Chan:
   319  		type u struct {
   320  			ChanType
   321  			u UncommonType
   322  		}
   323  		return &(*u)(unsafe.Pointer(t)).u
   324  	case Map:
   325  		type u struct {
   326  			MapType
   327  			u UncommonType
   328  		}
   329  		return &(*u)(unsafe.Pointer(t)).u
   330  	case Interface:
   331  		type u struct {
   332  			InterfaceType
   333  			u UncommonType
   334  		}
   335  		return &(*u)(unsafe.Pointer(t)).u
   336  	default:
   337  		type u struct {
   338  			Type
   339  			u UncommonType
   340  		}
   341  		return &(*u)(unsafe.Pointer(t)).u
   342  	}
   343  }
   344  
   345  // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
   346  func (t *Type) Elem() *Type {
   347  	switch t.Kind() {
   348  	case Array:
   349  		tt := (*ArrayType)(unsafe.Pointer(t))
   350  		return tt.Elem
   351  	case Chan:
   352  		tt := (*ChanType)(unsafe.Pointer(t))
   353  		return tt.Elem
   354  	case Map:
   355  		tt := (*MapType)(unsafe.Pointer(t))
   356  		return tt.Elem
   357  	case Pointer:
   358  		tt := (*PtrType)(unsafe.Pointer(t))
   359  		return tt.Elem
   360  	case Slice:
   361  		tt := (*SliceType)(unsafe.Pointer(t))
   362  		return tt.Elem
   363  	}
   364  	return nil
   365  }
   366  
   367  // StructType returns t cast to a *StructType, or nil if its tag does not match.
   368  func (t *Type) StructType() *StructType {
   369  	if t.Kind() != Struct {
   370  		return nil
   371  	}
   372  	return (*StructType)(unsafe.Pointer(t))
   373  }
   374  
   375  // MapType returns t cast to a *MapType, or nil if its tag does not match.
   376  func (t *Type) MapType() *MapType {
   377  	if t.Kind() != Map {
   378  		return nil
   379  	}
   380  	return (*MapType)(unsafe.Pointer(t))
   381  }
   382  
   383  // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
   384  func (t *Type) ArrayType() *ArrayType {
   385  	if t.Kind() != Array {
   386  		return nil
   387  	}
   388  	return (*ArrayType)(unsafe.Pointer(t))
   389  }
   390  
   391  // FuncType returns t cast to a *FuncType, or nil if its tag does not match.
   392  func (t *Type) FuncType() *FuncType {
   393  	if t.Kind() != Func {
   394  		return nil
   395  	}
   396  	return (*FuncType)(unsafe.Pointer(t))
   397  }
   398  
   399  // InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
   400  func (t *Type) InterfaceType() *InterfaceType {
   401  	if t.Kind() != Interface {
   402  		return nil
   403  	}
   404  	return (*InterfaceType)(unsafe.Pointer(t))
   405  }
   406  
   407  // Size returns the size of data with type t.
   408  func (t *Type) Size() uintptr { return t.Size_ }
   409  
   410  // Align returns the alignment of data with type t.
   411  func (t *Type) Align() int { return int(t.Align_) }
   412  
   413  func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
   414  
   415  type InterfaceType struct {
   416  	Type
   417  	PkgPath Name      // import path
   418  	Methods []Imethod // sorted by hash
   419  }
   420  
   421  func (t *Type) ExportedMethods() []Method {
   422  	ut := t.Uncommon()
   423  	if ut == nil {
   424  		return nil
   425  	}
   426  	return ut.ExportedMethods()
   427  }
   428  
   429  func (t *Type) NumMethod() int {
   430  	if t.Kind() == Interface {
   431  		tt := (*InterfaceType)(unsafe.Pointer(t))
   432  		return tt.NumMethod()
   433  	}
   434  	return len(t.ExportedMethods())
   435  }
   436  
   437  // NumMethod returns the number of interface methods in the type's method set.
   438  func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
   439  
   440  type MapType struct {
   441  	Type
   442  	Key    *Type
   443  	Elem   *Type
   444  	Bucket *Type // internal type representing a hash bucket
   445  	// function for hashing keys (ptr to key, seed) -> hash
   446  	Hasher     func(unsafe.Pointer, uintptr) uintptr
   447  	KeySize    uint8  // size of key slot
   448  	ValueSize  uint8  // size of elem slot
   449  	BucketSize uint16 // size of bucket
   450  	Flags      uint32
   451  }
   452  
   453  // Note: flag values must match those used in the TMAP case
   454  // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
   455  func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
   456  	return mt.Flags&1 != 0
   457  }
   458  func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
   459  	return mt.Flags&2 != 0
   460  }
   461  func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
   462  	return mt.Flags&4 != 0
   463  }
   464  func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
   465  	return mt.Flags&8 != 0
   466  }
   467  func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
   468  	return mt.Flags&16 != 0
   469  }
   470  
   471  func (t *Type) Key() *Type {
   472  	if t.Kind() == Map {
   473  		return (*MapType)(unsafe.Pointer(t)).Key
   474  	}
   475  	return nil
   476  }
   477  
   478  type SliceType struct {
   479  	Type
   480  	Elem *Type // slice element type
   481  }
   482  
   483  // funcType represents a function type.
   484  //
   485  // A *Type for each in and out parameter is stored in an array that
   486  // directly follows the funcType (and possibly its uncommonType). So
   487  // a function type with one method, one input, and one output is:
   488  //
   489  //	struct {
   490  //		funcType
   491  //		uncommonType
   492  //		[2]*rtype    // [0] is in, [1] is out
   493  //	}
   494  type FuncType struct {
   495  	Type
   496  	InCount  uint16
   497  	OutCount uint16 // top bit is set if last input parameter is ...
   498  }
   499  
   500  func (t *FuncType) In(i int) *Type {
   501  	return t.InSlice()[i]
   502  }
   503  
   504  func (t *FuncType) NumIn() int {
   505  	return int(t.InCount)
   506  }
   507  
   508  func (t *FuncType) NumOut() int {
   509  	return int(t.OutCount & (1<<15 - 1))
   510  }
   511  
   512  func (t *FuncType) Out(i int) *Type {
   513  	return (t.OutSlice()[i])
   514  }
   515  
   516  func (t *FuncType) InSlice() []*Type {
   517  	uadd := unsafe.Sizeof(*t)
   518  	if t.TFlag&TFlagUncommon != 0 {
   519  		uadd += unsafe.Sizeof(UncommonType{})
   520  	}
   521  	if t.InCount == 0 {
   522  		return nil
   523  	}
   524  	return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
   525  }
   526  func (t *FuncType) OutSlice() []*Type {
   527  	outCount := uint16(t.NumOut())
   528  	if outCount == 0 {
   529  		return nil
   530  	}
   531  	uadd := unsafe.Sizeof(*t)
   532  	if t.TFlag&TFlagUncommon != 0 {
   533  		uadd += unsafe.Sizeof(UncommonType{})
   534  	}
   535  	return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
   536  }
   537  
   538  func (t *FuncType) IsVariadic() bool {
   539  	return t.OutCount&(1<<15) != 0
   540  }
   541  
   542  type PtrType struct {
   543  	Type
   544  	Elem *Type // pointer element (pointed at) type
   545  }
   546  
   547  type StructField struct {
   548  	Name   Name    // name is always non-empty
   549  	Typ    *Type   // type of field
   550  	Offset uintptr // byte offset of field
   551  }
   552  
   553  func (f *StructField) Embedded() bool {
   554  	return f.Name.IsEmbedded()
   555  }
   556  
   557  type StructType struct {
   558  	Type
   559  	PkgPath Name
   560  	Fields  []StructField
   561  }
   562  
   563  // Name is an encoded type Name with optional extra data.
   564  //
   565  // The first byte is a bit field containing:
   566  //
   567  //	1<<0 the name is exported
   568  //	1<<1 tag data follows the name
   569  //	1<<2 pkgPath nameOff follows the name and tag
   570  //	1<<3 the name is of an embedded (a.k.a. anonymous) field
   571  //
   572  // Following that, there is a varint-encoded length of the name,
   573  // followed by the name itself.
   574  //
   575  // If tag data is present, it also has a varint-encoded length
   576  // followed by the tag itself.
   577  //
   578  // If the import path follows, then 4 bytes at the end of
   579  // the data form a nameOff. The import path is only set for concrete
   580  // methods that are defined in a different package than their type.
   581  //
   582  // If a name starts with "*", then the exported bit represents
   583  // whether the pointed to type is exported.
   584  //
   585  // Note: this encoding must match here and in:
   586  //   cmd/compile/internal/reflectdata/reflect.go
   587  //   cmd/link/internal/ld/decodesym.go
   588  
   589  type Name struct {
   590  	Bytes *byte
   591  }
   592  
   593  // DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   594  // be safe for the reason in whySafe (which can appear in a backtrace, etc.)
   595  func (n Name) DataChecked(off int, whySafe string) *byte {
   596  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
   597  }
   598  
   599  // Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   600  // be safe because the runtime made the call (other packages use DataChecked)
   601  func (n Name) Data(off int) *byte {
   602  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
   603  }
   604  
   605  // IsExported returns "is n exported?"
   606  func (n Name) IsExported() bool {
   607  	return (*n.Bytes)&(1<<0) != 0
   608  }
   609  
   610  // HasTag returns true iff there is tag data following this name
   611  func (n Name) HasTag() bool {
   612  	return (*n.Bytes)&(1<<1) != 0
   613  }
   614  
   615  // IsEmbedded returns true iff n is embedded (an anonymous field).
   616  func (n Name) IsEmbedded() bool {
   617  	return (*n.Bytes)&(1<<3) != 0
   618  }
   619  
   620  // ReadVarint parses a varint as encoded by encoding/binary.
   621  // It returns the number of encoded bytes and the encoded value.
   622  func (n Name) ReadVarint(off int) (int, int) {
   623  	v := 0
   624  	for i := 0; ; i++ {
   625  		x := *n.DataChecked(off+i, "read varint")
   626  		v += int(x&0x7f) << (7 * i)
   627  		if x&0x80 == 0 {
   628  			return i + 1, v
   629  		}
   630  	}
   631  }
   632  
   633  // IsBlank indicates whether n is "_".
   634  func (n Name) IsBlank() bool {
   635  	if n.Bytes == nil {
   636  		return false
   637  	}
   638  	_, l := n.ReadVarint(1)
   639  	return l == 1 && *n.Data(2) == '_'
   640  }
   641  
   642  // writeVarint writes n to buf in varint form. Returns the
   643  // number of bytes written. n must be nonnegative.
   644  // Writes at most 10 bytes.
   645  func writeVarint(buf []byte, n int) int {
   646  	for i := 0; ; i++ {
   647  		b := byte(n & 0x7f)
   648  		n >>= 7
   649  		if n == 0 {
   650  			buf[i] = b
   651  			return i + 1
   652  		}
   653  		buf[i] = b | 0x80
   654  	}
   655  }
   656  
   657  // Name returns the tag string for n, or empty if there is none.
   658  func (n Name) Name() string {
   659  	if n.Bytes == nil {
   660  		return ""
   661  	}
   662  	i, l := n.ReadVarint(1)
   663  	return unsafeStringFor(n.DataChecked(1+i, "non-empty string"), l)
   664  }
   665  
   666  // Tag returns the tag string for n, or empty if there is none.
   667  func (n Name) Tag() string {
   668  	if !n.HasTag() {
   669  		return ""
   670  	}
   671  	i, l := n.ReadVarint(1)
   672  	i2, l2 := n.ReadVarint(1 + i + l)
   673  	return unsafeStringFor(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
   674  }
   675  
   676  func NewName(n, tag string, exported, embedded bool) Name {
   677  	if len(n) >= 1<<29 {
   678  		panic("abi.NewName: name too long: " + n[:1024] + "...")
   679  	}
   680  	if len(tag) >= 1<<29 {
   681  		panic("abi.NewName: tag too long: " + tag[:1024] + "...")
   682  	}
   683  	var nameLen [10]byte
   684  	var tagLen [10]byte
   685  	nameLenLen := writeVarint(nameLen[:], len(n))
   686  	tagLenLen := writeVarint(tagLen[:], len(tag))
   687  
   688  	var bits byte
   689  	l := 1 + nameLenLen + len(n)
   690  	if exported {
   691  		bits |= 1 << 0
   692  	}
   693  	if len(tag) > 0 {
   694  		l += tagLenLen + len(tag)
   695  		bits |= 1 << 1
   696  	}
   697  	if embedded {
   698  		bits |= 1 << 3
   699  	}
   700  
   701  	b := make([]byte, l)
   702  	b[0] = bits
   703  	copy(b[1:], nameLen[:nameLenLen])
   704  	copy(b[1+nameLenLen:], n)
   705  	if len(tag) > 0 {
   706  		tb := b[1+nameLenLen+len(n):]
   707  		copy(tb, tagLen[:tagLenLen])
   708  		copy(tb[tagLenLen:], tag)
   709  	}
   710  
   711  	return Name{Bytes: &b[0]}
   712  }