github.com/llir/llvm@v0.3.6/ir/types/types.go (about)

     1  // Package types declares the data types of LLVM IR.
     2  package types
     3  
     4  import (
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/llir/llvm/internal/enc"
     9  )
    10  
    11  // === [ Types ] ===============================================================
    12  
    13  // Convenience types.
    14  var (
    15  	// Basic types.
    16  	Void     = &VoidType{}     // void
    17  	MMX      = &MMXType{}      // x86_mmx
    18  	Label    = &LabelType{}    // label
    19  	Token    = &TokenType{}    // token
    20  	Metadata = &MetadataType{} // metadata
    21  	// Integer types.
    22  	I1    = &IntType{BitSize: 1}    // i1
    23  	I2    = &IntType{BitSize: 2}    // i2
    24  	I3    = &IntType{BitSize: 3}    // i3
    25  	I4    = &IntType{BitSize: 4}    // i4
    26  	I5    = &IntType{BitSize: 5}    // i5
    27  	I6    = &IntType{BitSize: 6}    // i6
    28  	I7    = &IntType{BitSize: 7}    // i7
    29  	I8    = &IntType{BitSize: 8}    // i8
    30  	I16   = &IntType{BitSize: 16}   // i16
    31  	I32   = &IntType{BitSize: 32}   // i32
    32  	I64   = &IntType{BitSize: 64}   // i64
    33  	I128  = &IntType{BitSize: 128}  // i128
    34  	I256  = &IntType{BitSize: 256}  // i256
    35  	I512  = &IntType{BitSize: 512}  // i512
    36  	I1024 = &IntType{BitSize: 1024} // i1024
    37  	// Floating-point types.
    38  	Half      = &FloatType{Kind: FloatKindHalf}      // half
    39  	Float     = &FloatType{Kind: FloatKindFloat}     // float
    40  	Double    = &FloatType{Kind: FloatKindDouble}    // double
    41  	X86_FP80  = &FloatType{Kind: FloatKindX86_FP80}  // x86_fp80
    42  	FP128     = &FloatType{Kind: FloatKindFP128}     // fp128
    43  	PPC_FP128 = &FloatType{Kind: FloatKindPPC_FP128} // ppc_fp128
    44  	// Integer pointer types.
    45  	I1Ptr   = &PointerType{ElemType: I1}   // i1*
    46  	I8Ptr   = &PointerType{ElemType: I8}   // i8*
    47  	I16Ptr  = &PointerType{ElemType: I16}  // i16*
    48  	I32Ptr  = &PointerType{ElemType: I32}  // i32*
    49  	I64Ptr  = &PointerType{ElemType: I64}  // i64*
    50  	I128Ptr = &PointerType{ElemType: I128} // i128*
    51  )
    52  
    53  // Convenience functions.
    54  
    55  // IsVoid reports whether the given type is a void type.
    56  func IsVoid(t Type) bool {
    57  	_, ok := t.(*VoidType)
    58  	return ok
    59  }
    60  
    61  // IsFunc reports whether the given type is a function type.
    62  func IsFunc(t Type) bool {
    63  	_, ok := t.(*FuncType)
    64  	return ok
    65  }
    66  
    67  // IsInt reports whether the given type is an integer type.
    68  func IsInt(t Type) bool {
    69  	_, ok := t.(*IntType)
    70  	return ok
    71  }
    72  
    73  // IsFloat reports whether the given type is a floating-point type.
    74  func IsFloat(t Type) bool {
    75  	_, ok := t.(*FloatType)
    76  	return ok
    77  }
    78  
    79  // IsMMX reports whether the given type is an MMX type.
    80  func IsMMX(t Type) bool {
    81  	_, ok := t.(*MMXType)
    82  	return ok
    83  }
    84  
    85  // IsPointer reports whether the given type is a pointer type.
    86  func IsPointer(t Type) bool {
    87  	_, ok := t.(*PointerType)
    88  	return ok
    89  }
    90  
    91  // IsVector reports whether the given type is a vector type.
    92  func IsVector(t Type) bool {
    93  	_, ok := t.(*VectorType)
    94  	return ok
    95  }
    96  
    97  // IsLabel reports whether the given type is a label type.
    98  func IsLabel(t Type) bool {
    99  	_, ok := t.(*LabelType)
   100  	return ok
   101  }
   102  
   103  // IsToken reports whether the given type is a token type.
   104  func IsToken(t Type) bool {
   105  	_, ok := t.(*TokenType)
   106  	return ok
   107  }
   108  
   109  // IsMetadata reports whether the given type is a metadata type.
   110  func IsMetadata(t Type) bool {
   111  	_, ok := t.(*MetadataType)
   112  	return ok
   113  }
   114  
   115  // IsArray reports whether the given type is an array type.
   116  func IsArray(t Type) bool {
   117  	_, ok := t.(*ArrayType)
   118  	return ok
   119  }
   120  
   121  // IsStruct reports whether the given type is a struct type.
   122  func IsStruct(t Type) bool {
   123  	_, ok := t.(*StructType)
   124  	return ok
   125  }
   126  
   127  // Equal reports whether t and u are of equal type.
   128  func Equal(t, u Type) bool {
   129  	return t.Equal(u)
   130  }
   131  
   132  // Type is an LLVM IR type.
   133  //
   134  // A Type has one of the following underlying types.
   135  //
   136  //    *types.VoidType       // https://pkg.go.dev/github.com/llir/llvm/ir/types#VoidType
   137  //    *types.FuncType       // https://pkg.go.dev/github.com/llir/llvm/ir/types#FuncType
   138  //    *types.IntType        // https://pkg.go.dev/github.com/llir/llvm/ir/types#IntType
   139  //    *types.FloatType      // https://pkg.go.dev/github.com/llir/llvm/ir/types#FloatType
   140  //    *types.MMXType        // https://pkg.go.dev/github.com/llir/llvm/ir/types#MMXType
   141  //    *types.PointerType    // https://pkg.go.dev/github.com/llir/llvm/ir/types#PointerType
   142  //    *types.VectorType     // https://pkg.go.dev/github.com/llir/llvm/ir/types#VectorType
   143  //    *types.LabelType      // https://pkg.go.dev/github.com/llir/llvm/ir/types#LabelType
   144  //    *types.TokenType      // https://pkg.go.dev/github.com/llir/llvm/ir/types#TokenType
   145  //    *types.MetadataType   // https://pkg.go.dev/github.com/llir/llvm/ir/types#MetadataType
   146  //    *types.ArrayType      // https://pkg.go.dev/github.com/llir/llvm/ir/types#ArrayType
   147  //    *types.StructType     // https://pkg.go.dev/github.com/llir/llvm/ir/types#StructType
   148  type Type interface {
   149  	fmt.Stringer
   150  	// LLString returns the LLVM syntax representation of the definition of the
   151  	// type.
   152  	LLString() string
   153  	// Equal reports whether t and u are of equal type.
   154  	Equal(u Type) bool
   155  	// Name returns the type name of the type.
   156  	Name() string
   157  	// SetName sets the type name of the type.
   158  	SetName(name string)
   159  }
   160  
   161  // --- [ Void types ] ----------------------------------------------------------
   162  
   163  // VoidType is an LLVM IR void type.
   164  type VoidType struct {
   165  	// Type name; or empty if not present.
   166  	TypeName string
   167  }
   168  
   169  // Equal reports whether t and u are of equal type.
   170  func (t *VoidType) Equal(u Type) bool {
   171  	if _, ok := u.(*VoidType); ok {
   172  		return true
   173  	}
   174  	return false
   175  }
   176  
   177  // String returns the string representation of the void type.
   178  func (t *VoidType) String() string {
   179  	if len(t.TypeName) > 0 {
   180  		return enc.TypeName(t.TypeName)
   181  	}
   182  	return t.LLString()
   183  }
   184  
   185  // LLString returns the LLVM syntax representation of the definition of the
   186  // type.
   187  //
   188  // 'void'
   189  func (t *VoidType) LLString() string {
   190  	return "void"
   191  }
   192  
   193  // Name returns the type name of the type.
   194  func (t *VoidType) Name() string {
   195  	return t.TypeName
   196  }
   197  
   198  // SetName sets the type name of the type.
   199  func (t *VoidType) SetName(name string) {
   200  	t.TypeName = name
   201  }
   202  
   203  // --- [ Function types ] ------------------------------------------------------
   204  
   205  // FuncType is an LLVM IR function type.
   206  type FuncType struct {
   207  	// Type name; or empty if not present.
   208  	TypeName string
   209  	// Return type.
   210  	RetType Type
   211  	// Function parameters.
   212  	Params []Type
   213  	// Variable number of function arguments.
   214  	Variadic bool
   215  }
   216  
   217  // NewFunc returns a new function type based on the given return type and
   218  // function parameter types.
   219  func NewFunc(retType Type, params ...Type) *FuncType {
   220  	return &FuncType{
   221  		RetType: retType,
   222  		Params:  params,
   223  	}
   224  }
   225  
   226  // Equal reports whether t and u are of equal type.
   227  func (t *FuncType) Equal(u Type) bool {
   228  	if u, ok := u.(*FuncType); ok {
   229  		if !t.RetType.Equal(u.RetType) {
   230  			return false
   231  		}
   232  		if len(t.Params) != len(u.Params) {
   233  			return false
   234  		}
   235  		for i := range t.Params {
   236  			if !t.Params[i].Equal(u.Params[i]) {
   237  				return false
   238  			}
   239  		}
   240  		return t.Variadic == u.Variadic
   241  	}
   242  	return false
   243  }
   244  
   245  // String returns the string representation of the function type.
   246  func (t *FuncType) String() string {
   247  	if len(t.TypeName) > 0 {
   248  		return enc.TypeName(t.TypeName)
   249  	}
   250  	return t.LLString()
   251  }
   252  
   253  // LLString returns the LLVM syntax representation of the definition of the
   254  // type.
   255  //
   256  // RetType=Type '(' Params ')'
   257  func (t *FuncType) LLString() string {
   258  	buf := &strings.Builder{}
   259  	fmt.Fprintf(buf, "%s (", t.RetType)
   260  	for i, param := range t.Params {
   261  		if i != 0 {
   262  			buf.WriteString(", ")
   263  		}
   264  		buf.WriteString(param.String())
   265  	}
   266  	if t.Variadic {
   267  		if len(t.Params) > 0 {
   268  			buf.WriteString(", ")
   269  		}
   270  		buf.WriteString("...")
   271  	}
   272  	buf.WriteString(")")
   273  	return buf.String()
   274  }
   275  
   276  // Name returns the type name of the type.
   277  func (t *FuncType) Name() string {
   278  	return t.TypeName
   279  }
   280  
   281  // SetName sets the type name of the type.
   282  func (t *FuncType) SetName(name string) {
   283  	t.TypeName = name
   284  }
   285  
   286  // --- [ Integer types ] -------------------------------------------------------
   287  
   288  // IntType is an LLVM IR integer type.
   289  type IntType struct {
   290  	// Type name; or empty if not present.
   291  	TypeName string
   292  	// Integer size in number of bits.
   293  	BitSize uint64
   294  }
   295  
   296  // NewInt returns a new integer type based on the given integer bit size.
   297  func NewInt(bitSize uint64) *IntType {
   298  	return &IntType{
   299  		BitSize: bitSize,
   300  	}
   301  }
   302  
   303  // Equal reports whether t and u are of equal type.
   304  func (t *IntType) Equal(u Type) bool {
   305  	if u, ok := u.(*IntType); ok {
   306  		return t.BitSize == u.BitSize
   307  	}
   308  	return false
   309  }
   310  
   311  // String returns the string representation of the integer type.
   312  func (t *IntType) String() string {
   313  	if len(t.TypeName) > 0 {
   314  		return enc.TypeName(t.TypeName)
   315  	}
   316  	return t.LLString()
   317  }
   318  
   319  // LLString returns the LLVM syntax representation of the definition of the
   320  // type.
   321  //
   322  // int_type_tok
   323  func (t *IntType) LLString() string {
   324  	return fmt.Sprintf("i%d", t.BitSize)
   325  }
   326  
   327  // Name returns the type name of the type.
   328  func (t *IntType) Name() string {
   329  	return t.TypeName
   330  }
   331  
   332  // SetName sets the type name of the type.
   333  func (t *IntType) SetName(name string) {
   334  	t.TypeName = name
   335  }
   336  
   337  // --- [ Floating-point types ] ------------------------------------------------
   338  
   339  // FloatType is an LLVM IR floating-point type.
   340  type FloatType struct {
   341  	// Type name; or empty if not present.
   342  	TypeName string
   343  	// Floating-point kind.
   344  	Kind FloatKind
   345  }
   346  
   347  // Equal reports whether t and u are of equal type.
   348  func (t *FloatType) Equal(u Type) bool {
   349  	if u, ok := u.(*FloatType); ok {
   350  		return t.Kind == u.Kind
   351  	}
   352  	return false
   353  }
   354  
   355  // String returns the string representation of the floating-point type.
   356  func (t *FloatType) String() string {
   357  	if len(t.TypeName) > 0 {
   358  		return enc.TypeName(t.TypeName)
   359  	}
   360  	return t.LLString()
   361  }
   362  
   363  // LLString returns the LLVM syntax representation of the definition of the
   364  // type.
   365  //
   366  // FloatKind
   367  func (t *FloatType) LLString() string {
   368  	return t.Kind.String()
   369  }
   370  
   371  // Name returns the type name of the type.
   372  func (t *FloatType) Name() string {
   373  	return t.TypeName
   374  }
   375  
   376  // SetName sets the type name of the type.
   377  func (t *FloatType) SetName(name string) {
   378  	t.TypeName = name
   379  }
   380  
   381  //go:generate stringer -linecomment -type FloatKind
   382  
   383  // FloatKind represents the set of floating-point kinds.
   384  type FloatKind uint8
   385  
   386  // Floating-point kinds.
   387  const (
   388  	// 16-bit floating-point type (IEEE 754 half precision).
   389  	FloatKindHalf FloatKind = iota // half
   390  	// 32-bit floating-point type (IEEE 754 single precision).
   391  	FloatKindFloat // float
   392  	// 64-bit floating-point type (IEEE 754 double precision).
   393  	FloatKindDouble // double
   394  	// 128-bit floating-point type (IEEE 754 quadruple precision).
   395  	FloatKindFP128 // fp128
   396  	// 80-bit floating-point type (x86 extended precision).
   397  	FloatKindX86_FP80 // x86_fp80
   398  	// 128-bit floating-point type (PowerPC double-double arithmetic).
   399  	FloatKindPPC_FP128 // ppc_fp128
   400  )
   401  
   402  // --- [ MMX types ] -----------------------------------------------------------
   403  
   404  // MMXType is an LLVM IR MMX type.
   405  type MMXType struct {
   406  	// Type name; or empty if not present.
   407  	TypeName string
   408  }
   409  
   410  // Equal reports whether t and u are of equal type.
   411  func (t *MMXType) Equal(u Type) bool {
   412  	if _, ok := u.(*MMXType); ok {
   413  		return true
   414  	}
   415  	return false
   416  }
   417  
   418  // String returns the string representation of the MMX type.
   419  func (t *MMXType) String() string {
   420  	if len(t.TypeName) > 0 {
   421  		return enc.TypeName(t.TypeName)
   422  	}
   423  	return t.LLString()
   424  }
   425  
   426  // LLString returns the LLVM syntax representation of the definition of the
   427  // type.
   428  //
   429  // 'x86_mmx'
   430  func (t *MMXType) LLString() string {
   431  	return "x86_mmx"
   432  }
   433  
   434  // Name returns the type name of the type.
   435  func (t *MMXType) Name() string {
   436  	return t.TypeName
   437  }
   438  
   439  // SetName sets the type name of the type.
   440  func (t *MMXType) SetName(name string) {
   441  	t.TypeName = name
   442  }
   443  
   444  // --- [ Pointer types ] -------------------------------------------------------
   445  
   446  // PointerType is an LLVM IR pointer type.
   447  type PointerType struct {
   448  	// Type name; or empty if not present.
   449  	TypeName string
   450  	// Element type.
   451  	ElemType Type
   452  	// Address space; or zero value for default address space.
   453  	AddrSpace AddrSpace
   454  }
   455  
   456  // NewPointer returns a new pointer type based on the given element type.
   457  func NewPointer(elemType Type) *PointerType {
   458  	return &PointerType{
   459  		ElemType: elemType,
   460  	}
   461  }
   462  
   463  // Equal reports whether t and u are of equal type.
   464  func (t *PointerType) Equal(u Type) bool {
   465  	// HACK: to prevent infinite loops (e.g. struct foo containing field of type
   466  	// pointer to foo).
   467  	return t.String() == u.String()
   468  }
   469  
   470  // String returns the string representation of the pointer type.
   471  func (t *PointerType) String() string {
   472  	if len(t.TypeName) > 0 {
   473  		return enc.TypeName(t.TypeName)
   474  	}
   475  	return t.LLString()
   476  }
   477  
   478  // LLString returns the LLVM syntax representation of the definition of the
   479  // type.
   480  //
   481  // Elem=Type AddrSpaceopt '*'
   482  func (t *PointerType) LLString() string {
   483  	buf := &strings.Builder{}
   484  	buf.WriteString(t.ElemType.String())
   485  	if t.AddrSpace != 0 {
   486  		fmt.Fprintf(buf, " %s", t.AddrSpace)
   487  	}
   488  	buf.WriteString("*")
   489  	return buf.String()
   490  }
   491  
   492  // SetName sets the type name of the type.
   493  func (t *PointerType) SetName(name string) {
   494  	t.TypeName = name
   495  }
   496  
   497  // Name returns the type name of the type.
   498  func (t *PointerType) Name() string {
   499  	return t.TypeName
   500  }
   501  
   502  // AddrSpace is an LLVM IR pointer type address space.
   503  type AddrSpace uint64
   504  
   505  // String returns the string representation of the pointer type address space.
   506  func (a AddrSpace) String() string {
   507  	// 'addrspace' '(' N=UintLit ')'
   508  	return fmt.Sprintf("addrspace(%d)", uint64(a))
   509  }
   510  
   511  // --- [ Vector types ] --------------------------------------------------------
   512  
   513  // VectorType is an LLVM IR vector type.
   514  type VectorType struct {
   515  	// Type name; or empty if not present.
   516  	TypeName string
   517  	// Scalable vector type.
   518  	Scalable bool
   519  	// Vector length.
   520  	Len uint64
   521  	// Element type.
   522  	ElemType Type
   523  }
   524  
   525  // NewVector returns a new vector type based on the given vector length and
   526  // element type.
   527  func NewVector(len uint64, elemType Type) *VectorType {
   528  	return &VectorType{
   529  		Len:      len,
   530  		ElemType: elemType,
   531  	}
   532  }
   533  
   534  // Equal reports whether t and u are of equal type.
   535  func (t *VectorType) Equal(u Type) bool {
   536  	if u, ok := u.(*VectorType); ok {
   537  		if t.Scalable != u.Scalable {
   538  			return false
   539  		}
   540  		if t.Len != u.Len {
   541  			return false
   542  		}
   543  		return t.ElemType.Equal(u.ElemType)
   544  	}
   545  	return false
   546  }
   547  
   548  // String returns the string representation of the vector type.
   549  func (t *VectorType) String() string {
   550  	if len(t.TypeName) > 0 {
   551  		return enc.TypeName(t.TypeName)
   552  	}
   553  	return t.LLString()
   554  }
   555  
   556  // LLString returns the LLVM syntax representation of the definition of the
   557  // type.
   558  //
   559  // scalable: '<' 'vscale' 'x' Len=UintLit 'x' Elem=Type '>'
   560  // non-scalable: '<' Len=UintLit 'x' Elem=Type '>'
   561  func (t *VectorType) LLString() string {
   562  	if t.Scalable {
   563  		// '<' 'vscale' 'x' Len=UintLit 'x' Elem=Type '>'
   564  		return fmt.Sprintf("<vscale x %d x %s>", t.Len, t.ElemType)
   565  	}
   566  	// '<' Len=UintLit 'x' Elem=Type '>'
   567  	return fmt.Sprintf("<%d x %s>", t.Len, t.ElemType)
   568  }
   569  
   570  // Name returns the type name of the type.
   571  func (t *VectorType) Name() string {
   572  	return t.TypeName
   573  }
   574  
   575  // SetName sets the type name of the type.
   576  func (t *VectorType) SetName(name string) {
   577  	t.TypeName = name
   578  }
   579  
   580  // --- [ Label types ] ---------------------------------------------------------
   581  
   582  // LabelType is an LLVM IR label type, which is used for basic block values.
   583  type LabelType struct {
   584  	// Type name; or empty if not present.
   585  	TypeName string
   586  }
   587  
   588  // Equal reports whether t and u are of equal type.
   589  func (t *LabelType) Equal(u Type) bool {
   590  	if _, ok := u.(*LabelType); ok {
   591  		return true
   592  	}
   593  	return false
   594  }
   595  
   596  // String returns the string representation of the label type.
   597  func (t *LabelType) String() string {
   598  	if len(t.TypeName) > 0 {
   599  		return enc.TypeName(t.TypeName)
   600  	}
   601  	return t.LLString()
   602  }
   603  
   604  // LLString returns the LLVM syntax representation of the definition of the
   605  // type.
   606  //
   607  // 'label'
   608  func (t *LabelType) LLString() string {
   609  	return "label"
   610  }
   611  
   612  // Name returns the type name of the type.
   613  func (t *LabelType) Name() string {
   614  	return t.TypeName
   615  }
   616  
   617  // SetName sets the type name of the type.
   618  func (t *LabelType) SetName(name string) {
   619  	t.TypeName = name
   620  }
   621  
   622  // --- [ Token types ] ---------------------------------------------------------
   623  
   624  // TokenType is an LLVM IR token type.
   625  type TokenType struct {
   626  	// Type name; or empty if not present.
   627  	TypeName string
   628  }
   629  
   630  // Equal reports whether t and u are of equal type.
   631  func (t *TokenType) Equal(u Type) bool {
   632  	if _, ok := u.(*TokenType); ok {
   633  		return true
   634  	}
   635  	return false
   636  }
   637  
   638  // String returns the string representation of the token type.
   639  func (t *TokenType) String() string {
   640  	if len(t.TypeName) > 0 {
   641  		return enc.TypeName(t.TypeName)
   642  	}
   643  	return t.LLString()
   644  }
   645  
   646  // LLString returns the LLVM syntax representation of the definition of the
   647  // type.
   648  //
   649  // 'token'
   650  func (t *TokenType) LLString() string {
   651  	return "token"
   652  }
   653  
   654  // Name returns the type name of the type.
   655  func (t *TokenType) Name() string {
   656  	return t.TypeName
   657  }
   658  
   659  // SetName sets the type name of the type.
   660  func (t *TokenType) SetName(name string) {
   661  	t.TypeName = name
   662  }
   663  
   664  // --- [ Metadata types ] ------------------------------------------------------
   665  
   666  // MetadataType is an LLVM IR metadata type.
   667  type MetadataType struct {
   668  	// Type name; or empty if not present.
   669  	TypeName string
   670  }
   671  
   672  // Equal reports whether t and u are of equal type.
   673  func (t *MetadataType) Equal(u Type) bool {
   674  	if _, ok := u.(*MetadataType); ok {
   675  		return true
   676  	}
   677  	return false
   678  }
   679  
   680  // String returns the string representation of the metadata type.
   681  func (t *MetadataType) String() string {
   682  	if len(t.TypeName) > 0 {
   683  		return enc.TypeName(t.TypeName)
   684  	}
   685  	return t.LLString()
   686  }
   687  
   688  // LLString returns the LLVM syntax representation of the definition of the
   689  // type.
   690  //
   691  // 'metadata'
   692  func (t *MetadataType) LLString() string {
   693  	return "metadata"
   694  }
   695  
   696  // Name returns the type name of the type.
   697  func (t *MetadataType) Name() string {
   698  	return t.TypeName
   699  }
   700  
   701  // SetName sets the type name of the type.
   702  func (t *MetadataType) SetName(name string) {
   703  	t.TypeName = name
   704  }
   705  
   706  // --- [ Array types ] ---------------------------------------------------------
   707  
   708  // ArrayType is an LLVM IR array type.
   709  type ArrayType struct {
   710  	// Type name; or empty if not present.
   711  	TypeName string
   712  	// Array length.
   713  	Len uint64
   714  	// Element type.
   715  	ElemType Type
   716  }
   717  
   718  // NewArray returns a new array type based on the given array length and element
   719  // type.
   720  func NewArray(len uint64, elemType Type) *ArrayType {
   721  	return &ArrayType{
   722  		Len:      len,
   723  		ElemType: elemType,
   724  	}
   725  }
   726  
   727  // Equal reports whether t and u are of equal type.
   728  func (t *ArrayType) Equal(u Type) bool {
   729  	if u, ok := u.(*ArrayType); ok {
   730  		if t.Len != u.Len {
   731  			return false
   732  		}
   733  		return t.ElemType.Equal(u.ElemType)
   734  	}
   735  	return false
   736  }
   737  
   738  // String returns the string representation of the array type.
   739  func (t *ArrayType) String() string {
   740  	if len(t.TypeName) > 0 {
   741  		return enc.TypeName(t.TypeName)
   742  	}
   743  	return t.LLString()
   744  }
   745  
   746  // LLString returns the LLVM syntax representation of the definition of the
   747  // type.
   748  //
   749  // '[' Len=UintLit 'x' Elem=Type ']'
   750  func (t *ArrayType) LLString() string {
   751  	return fmt.Sprintf("[%d x %s]", t.Len, t.ElemType)
   752  }
   753  
   754  // Name returns the type name of the type.
   755  func (t *ArrayType) Name() string {
   756  	return t.TypeName
   757  }
   758  
   759  // SetName sets the type name of the type.
   760  func (t *ArrayType) SetName(name string) {
   761  	t.TypeName = name
   762  }
   763  
   764  // --- [ Structure types ] -----------------------------------------------------
   765  
   766  // StructType is an LLVM IR structure type. Identified (named) struct types are
   767  // uniqued by type names, not by structural identity.
   768  type StructType struct {
   769  	// Type name; or empty if not present.
   770  	TypeName string
   771  	// Packed memory layout.
   772  	Packed bool
   773  	// Struct fields.
   774  	Fields []Type
   775  	// Opaque struct type.
   776  	Opaque bool
   777  }
   778  
   779  // NewStruct returns a new struct type based on the given field types.
   780  func NewStruct(fields ...Type) *StructType {
   781  	return &StructType{
   782  		Fields: fields,
   783  	}
   784  }
   785  
   786  // Equal reports whether t and u are of equal type.
   787  func (t *StructType) Equal(u Type) bool {
   788  	if u, ok := u.(*StructType); ok {
   789  		if len(t.TypeName) > 0 || len(u.TypeName) > 0 {
   790  			// Identified struct types are uniqued by type names, not by structural
   791  			// identity.
   792  			//
   793  			// t or u is an identified struct type.
   794  			return t.TypeName == u.TypeName
   795  		}
   796  		// Literal struct types are uniqued by structural identity.
   797  		if t.Packed != u.Packed {
   798  			return false
   799  		}
   800  		if len(t.Fields) != len(u.Fields) {
   801  			return false
   802  		}
   803  		for i := range t.Fields {
   804  			if !t.Fields[i].Equal(u.Fields[i]) {
   805  				return false
   806  			}
   807  		}
   808  		return true
   809  	}
   810  	return false
   811  }
   812  
   813  // String returns the string representation of the structure type.
   814  func (t *StructType) String() string {
   815  	if len(t.TypeName) > 0 {
   816  		return enc.TypeName(t.TypeName)
   817  	}
   818  	return t.LLString()
   819  }
   820  
   821  // LLString returns the LLVM syntax representation of the definition of the
   822  // type.
   823  //
   824  // Opaque struct type.
   825  //
   826  //    'opaque'
   827  //
   828  // Struct type.
   829  //
   830  //    '{' Fields=(Type separator ',')+? '}'
   831  //
   832  // Packed struct type.
   833  //
   834  //    '<' '{' Fields=(Type separator ',')+? '}' '>'   -> PackedStructType
   835  func (t *StructType) LLString() string {
   836  	if t.Opaque {
   837  		return "opaque"
   838  	}
   839  	if len(t.Fields) == 0 {
   840  		if t.Packed {
   841  			return "<{}>"
   842  		}
   843  		return "{}"
   844  	}
   845  	buf := &strings.Builder{}
   846  	if t.Packed {
   847  		buf.WriteString("<")
   848  	}
   849  	buf.WriteString("{ ")
   850  	for i, field := range t.Fields {
   851  		if i != 0 {
   852  			buf.WriteString(", ")
   853  		}
   854  		buf.WriteString(field.String())
   855  	}
   856  	buf.WriteString(" }")
   857  	if t.Packed {
   858  		buf.WriteString(">")
   859  	}
   860  	return buf.String()
   861  }
   862  
   863  // Name returns the type name of the type.
   864  func (t *StructType) Name() string {
   865  	return t.TypeName
   866  }
   867  
   868  // SetName sets the type name of the type.
   869  func (t *StructType) SetName(name string) {
   870  	t.TypeName = name
   871  }