github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/compiler/compiler.go (about)

     1  package compiler
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"errors"
     6  	"fmt"
     7  	"go/ast"
     8  	"go/constant"
     9  	"go/token"
    10  	"go/types"
    11  	"math/bits"
    12  	"path"
    13  	"path/filepath"
    14  	"sort"
    15  	"strconv"
    16  	"strings"
    17  
    18  	"github.com/tinygo-org/tinygo/compiler/llvmutil"
    19  	"github.com/tinygo-org/tinygo/loader"
    20  	"golang.org/x/tools/go/ssa"
    21  	"golang.org/x/tools/go/types/typeutil"
    22  	"tinygo.org/x/go-llvm"
    23  )
    24  
    25  func init() {
    26  	llvm.InitializeAllTargets()
    27  	llvm.InitializeAllTargetMCs()
    28  	llvm.InitializeAllTargetInfos()
    29  	llvm.InitializeAllAsmParsers()
    30  	llvm.InitializeAllAsmPrinters()
    31  }
    32  
    33  // Config is the configuration for the compiler. Most settings should be copied
    34  // directly from compileopts.Config, it recreated here to decouple the compiler
    35  // package a bit and because it makes caching easier.
    36  //
    37  // This struct can be used for caching: if one of the flags here changes the
    38  // code must be recompiled.
    39  type Config struct {
    40  	// Target and output information.
    41  	Triple          string
    42  	CPU             string
    43  	Features        string
    44  	ABI             string
    45  	GOOS            string
    46  	GOARCH          string
    47  	CodeModel       string
    48  	RelocationModel string
    49  	SizeLevel       int
    50  	TinyGoVersion   string // for llvm.ident
    51  
    52  	// Various compiler options that determine how code is generated.
    53  	Scheduler          string
    54  	AutomaticStackSize bool
    55  	DefaultStackSize   uint64
    56  	MaxStackAlloc      uint64
    57  	NeedsStackObjects  bool
    58  	Debug              bool // Whether to emit debug information in the LLVM module.
    59  	PanicStrategy      string
    60  }
    61  
    62  // compilerContext contains function-independent data that should still be
    63  // available while compiling every function. It is not strictly read-only, but
    64  // must not contain function-dependent data such as an IR builder.
    65  type compilerContext struct {
    66  	*Config
    67  	DumpSSA          bool
    68  	mod              llvm.Module
    69  	ctx              llvm.Context
    70  	builder          llvm.Builder // only used for constant operations
    71  	dibuilder        *llvm.DIBuilder
    72  	cu               llvm.Metadata
    73  	difiles          map[string]llvm.Metadata
    74  	ditypes          map[types.Type]llvm.Metadata
    75  	llvmTypes        typeutil.Map
    76  	interfaceTypes   typeutil.Map
    77  	machine          llvm.TargetMachine
    78  	targetData       llvm.TargetData
    79  	intType          llvm.Type
    80  	dataPtrType      llvm.Type // pointer in address space 0
    81  	funcPtrType      llvm.Type // pointer in function address space (1 for AVR, 0 elsewhere)
    82  	funcPtrAddrSpace int
    83  	uintptrType      llvm.Type
    84  	program          *ssa.Program
    85  	diagnostics      []error
    86  	functionInfos    map[*ssa.Function]functionInfo
    87  	astComments      map[string]*ast.CommentGroup
    88  	embedGlobals     map[string][]*loader.EmbedFile
    89  	pkg              *types.Package
    90  	packageDir       string // directory for this package
    91  	runtimePkg       *types.Package
    92  }
    93  
    94  // newCompilerContext returns a new compiler context ready for use, most
    95  // importantly with a newly created LLVM context and module.
    96  func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *Config, dumpSSA bool) *compilerContext {
    97  	c := &compilerContext{
    98  		Config:        config,
    99  		DumpSSA:       dumpSSA,
   100  		difiles:       make(map[string]llvm.Metadata),
   101  		ditypes:       make(map[types.Type]llvm.Metadata),
   102  		machine:       machine,
   103  		targetData:    machine.CreateTargetData(),
   104  		functionInfos: map[*ssa.Function]functionInfo{},
   105  		astComments:   map[string]*ast.CommentGroup{},
   106  	}
   107  
   108  	c.ctx = llvm.NewContext()
   109  	c.builder = c.ctx.NewBuilder()
   110  	c.mod = c.ctx.NewModule(moduleName)
   111  	c.mod.SetTarget(config.Triple)
   112  	c.mod.SetDataLayout(c.targetData.String())
   113  	if c.Debug {
   114  		c.dibuilder = llvm.NewDIBuilder(c.mod)
   115  	}
   116  
   117  	c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
   118  	if c.targetData.PointerSize() <= 4 {
   119  		// 8, 16, 32 bits targets
   120  		c.intType = c.ctx.Int32Type()
   121  	} else if c.targetData.PointerSize() == 8 {
   122  		// 64 bits target
   123  		c.intType = c.ctx.Int64Type()
   124  	} else {
   125  		panic("unknown pointer size")
   126  	}
   127  	c.dataPtrType = llvm.PointerType(c.ctx.Int8Type(), 0)
   128  
   129  	dummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false)
   130  	dummyFunc := llvm.AddFunction(c.mod, "tinygo.dummy", dummyFuncType)
   131  	c.funcPtrAddrSpace = dummyFunc.Type().PointerAddressSpace()
   132  	c.funcPtrType = dummyFunc.Type()
   133  	dummyFunc.EraseFromParentAsFunction()
   134  
   135  	return c
   136  }
   137  
   138  // Dispose everything related to the context, _except_ for the IR module (and
   139  // the associated context).
   140  func (c *compilerContext) dispose() {
   141  	c.builder.Dispose()
   142  }
   143  
   144  // builder contains all information relevant to build a single function.
   145  type builder struct {
   146  	*compilerContext
   147  	llvm.Builder
   148  	fn                *ssa.Function
   149  	llvmFnType        llvm.Type
   150  	llvmFn            llvm.Value
   151  	info              functionInfo
   152  	locals            map[ssa.Value]llvm.Value            // local variables
   153  	blockEntries      map[*ssa.BasicBlock]llvm.BasicBlock // a *ssa.BasicBlock may be split up
   154  	blockExits        map[*ssa.BasicBlock]llvm.BasicBlock // these are the exit blocks
   155  	currentBlock      *ssa.BasicBlock
   156  	phis              []phiNode
   157  	deferPtr          llvm.Value
   158  	deferFrame        llvm.Value
   159  	stackChainAlloca  llvm.Value
   160  	landingpad        llvm.BasicBlock
   161  	difunc            llvm.Metadata
   162  	dilocals          map[*types.Var]llvm.Metadata
   163  	initInlinedAt     llvm.Metadata            // fake inlinedAt position
   164  	initPseudoFuncs   map[string]llvm.Metadata // fake "inlined" functions for proper init debug locations
   165  	allDeferFuncs     []interface{}
   166  	deferFuncs        map[*ssa.Function]int
   167  	deferInvokeFuncs  map[string]int
   168  	deferClosureFuncs map[*ssa.Function]int
   169  	deferExprFuncs    map[ssa.Value]int
   170  	selectRecvBuf     map[*ssa.Select]llvm.Value
   171  	deferBuiltinFuncs map[ssa.Value]deferBuiltin
   172  	runDefersBlock    []llvm.BasicBlock
   173  	afterDefersBlock  []llvm.BasicBlock
   174  }
   175  
   176  func newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *builder {
   177  	fnType, fn := c.getFunction(f)
   178  	return &builder{
   179  		compilerContext: c,
   180  		Builder:         irbuilder,
   181  		fn:              f,
   182  		llvmFnType:      fnType,
   183  		llvmFn:          fn,
   184  		info:            c.getFunctionInfo(f),
   185  		locals:          make(map[ssa.Value]llvm.Value),
   186  		dilocals:        make(map[*types.Var]llvm.Metadata),
   187  		blockEntries:    make(map[*ssa.BasicBlock]llvm.BasicBlock),
   188  		blockExits:      make(map[*ssa.BasicBlock]llvm.BasicBlock),
   189  	}
   190  }
   191  
   192  type deferBuiltin struct {
   193  	callName string
   194  	pos      token.Pos
   195  	argTypes []types.Type
   196  	callback int
   197  }
   198  
   199  type phiNode struct {
   200  	ssa  *ssa.Phi
   201  	llvm llvm.Value
   202  }
   203  
   204  // NewTargetMachine returns a new llvm.TargetMachine based on the passed-in
   205  // configuration. It is used by the compiler and is needed for machine code
   206  // emission.
   207  func NewTargetMachine(config *Config) (llvm.TargetMachine, error) {
   208  	target, err := llvm.GetTargetFromTriple(config.Triple)
   209  	if err != nil {
   210  		return llvm.TargetMachine{}, err
   211  	}
   212  
   213  	var codeModel llvm.CodeModel
   214  	var relocationModel llvm.RelocMode
   215  
   216  	switch config.CodeModel {
   217  	case "default":
   218  		codeModel = llvm.CodeModelDefault
   219  	case "tiny":
   220  		codeModel = llvm.CodeModelTiny
   221  	case "small":
   222  		codeModel = llvm.CodeModelSmall
   223  	case "kernel":
   224  		codeModel = llvm.CodeModelKernel
   225  	case "medium":
   226  		codeModel = llvm.CodeModelMedium
   227  	case "large":
   228  		codeModel = llvm.CodeModelLarge
   229  	}
   230  
   231  	switch config.RelocationModel {
   232  	case "static":
   233  		relocationModel = llvm.RelocStatic
   234  	case "pic":
   235  		relocationModel = llvm.RelocPIC
   236  	case "dynamicnopic":
   237  		relocationModel = llvm.RelocDynamicNoPic
   238  	}
   239  
   240  	machine := target.CreateTargetMachine(config.Triple, config.CPU, config.Features, llvm.CodeGenLevelDefault, relocationModel, codeModel)
   241  	return machine, nil
   242  }
   243  
   244  // Sizes returns a types.Sizes appropriate for the given target machine. It
   245  // includes the correct int size and aligment as is necessary for the Go
   246  // typechecker.
   247  func Sizes(machine llvm.TargetMachine) types.Sizes {
   248  	targetData := machine.CreateTargetData()
   249  	defer targetData.Dispose()
   250  
   251  	var intWidth int
   252  	if targetData.PointerSize() <= 4 {
   253  		// 8, 16, 32 bits targets
   254  		intWidth = 32
   255  	} else if targetData.PointerSize() == 8 {
   256  		// 64 bits target
   257  		intWidth = 64
   258  	} else {
   259  		panic("unknown pointer size")
   260  	}
   261  
   262  	// Construct a complex128 type because that's likely the type with the
   263  	// biggest alignment on most/all ABIs.
   264  	ctx := llvm.NewContext()
   265  	defer ctx.Dispose()
   266  	complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)
   267  	return &stdSizes{
   268  		IntSize:  int64(intWidth / 8),
   269  		PtrSize:  int64(targetData.PointerSize()),
   270  		MaxAlign: int64(targetData.ABITypeAlignment(complex128Type)),
   271  	}
   272  }
   273  
   274  // CompilePackage compiles a single package to a LLVM module.
   275  func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
   276  	c := newCompilerContext(moduleName, machine, config, dumpSSA)
   277  	defer c.dispose()
   278  	c.packageDir = pkg.OriginalDir()
   279  	c.embedGlobals = pkg.EmbedGlobals
   280  	c.pkg = pkg.Pkg
   281  	c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg
   282  	c.program = ssaPkg.Prog
   283  
   284  	// Convert AST to SSA.
   285  	ssaPkg.Build()
   286  
   287  	// Initialize debug information.
   288  	if c.Debug {
   289  		c.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{
   290  			Language:  0xb, // DW_LANG_C99 (0xc, off-by-one?)
   291  			File:      "<unknown>",
   292  			Dir:       "",
   293  			Producer:  "TinyGo",
   294  			Optimized: true,
   295  		})
   296  	}
   297  
   298  	// Load comments such as //go:extern on globals.
   299  	c.loadASTComments(pkg)
   300  
   301  	// Predeclare the runtime.alloc function, which is used by the wordpack
   302  	// functionality.
   303  	c.getFunction(c.program.ImportedPackage("runtime").Members["alloc"].(*ssa.Function))
   304  	if c.NeedsStackObjects {
   305  		// Predeclare trackPointer, which is used everywhere we use runtime.alloc.
   306  		c.getFunction(c.program.ImportedPackage("runtime").Members["trackPointer"].(*ssa.Function))
   307  	}
   308  
   309  	// Compile all functions, methods, and global variables in this package.
   310  	irbuilder := c.ctx.NewBuilder()
   311  	defer irbuilder.Dispose()
   312  	c.createPackage(irbuilder, ssaPkg)
   313  
   314  	// see: https://reviews.llvm.org/D18355
   315  	if c.Debug {
   316  		c.mod.AddNamedMetadataOperand("llvm.module.flags",
   317  			c.ctx.MDNode([]llvm.Metadata{
   318  				llvm.ConstInt(c.ctx.Int32Type(), 2, false).ConstantAsMetadata(), // Warning on mismatch
   319  				c.ctx.MDString("Debug Info Version"),
   320  				llvm.ConstInt(c.ctx.Int32Type(), 3, false).ConstantAsMetadata(), // DWARF version
   321  			}),
   322  		)
   323  		c.mod.AddNamedMetadataOperand("llvm.module.flags",
   324  			c.ctx.MDNode([]llvm.Metadata{
   325  				llvm.ConstInt(c.ctx.Int32Type(), 7, false).ConstantAsMetadata(), // Max on mismatch
   326  				c.ctx.MDString("Dwarf Version"),
   327  				llvm.ConstInt(c.ctx.Int32Type(), 4, false).ConstantAsMetadata(),
   328  			}),
   329  		)
   330  		if c.TinyGoVersion != "" {
   331  			// It is necessary to set llvm.ident, otherwise debugging on MacOS
   332  			// won't work.
   333  			c.mod.AddNamedMetadataOperand("llvm.ident",
   334  				c.ctx.MDNode(([]llvm.Metadata{
   335  					c.ctx.MDString("TinyGo version " + c.TinyGoVersion),
   336  				})))
   337  		}
   338  		c.dibuilder.Finalize()
   339  		c.dibuilder.Destroy()
   340  	}
   341  
   342  	// Add the "target-abi" flag, which is necessary on RISC-V otherwise it will
   343  	// pick one that doesn't match the -mabi Clang flag.
   344  	if c.ABI != "" {
   345  		c.mod.AddNamedMetadataOperand("llvm.module.flags",
   346  			c.ctx.MDNode([]llvm.Metadata{
   347  				llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
   348  				c.ctx.MDString("target-abi"),
   349  				c.ctx.MDString(c.ABI),
   350  			}),
   351  		)
   352  	}
   353  
   354  	return c.mod, c.diagnostics
   355  }
   356  
   357  func (c *compilerContext) getRuntimeType(name string) types.Type {
   358  	return c.runtimePkg.Scope().Lookup(name).(*types.TypeName).Type()
   359  }
   360  
   361  // getLLVMRuntimeType obtains a named type from the runtime package and returns
   362  // it as a LLVM type, creating it if necessary. It is a shorthand for
   363  // getLLVMType(getRuntimeType(name)).
   364  func (c *compilerContext) getLLVMRuntimeType(name string) llvm.Type {
   365  	return c.getLLVMType(c.getRuntimeType(name))
   366  }
   367  
   368  // getLLVMType returns a LLVM type for a Go type. It doesn't recreate already
   369  // created types. This is somewhat important for performance, but especially
   370  // important for named struct types (which should only be created once).
   371  func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
   372  	// Try to load the LLVM type from the cache.
   373  	// Note: *types.Named isn't unique when working with generics.
   374  	// See https://github.com/golang/go/issues/53914
   375  	// This is the reason for using typeutil.Map to lookup LLVM types for Go types.
   376  	ival := c.llvmTypes.At(goType)
   377  	if ival != nil {
   378  		return ival.(llvm.Type)
   379  	}
   380  	// Not already created, so adding this type to the cache.
   381  	llvmType := c.makeLLVMType(goType)
   382  	c.llvmTypes.Set(goType, llvmType)
   383  	return llvmType
   384  }
   385  
   386  // makeLLVMType creates a LLVM type for a Go type. Don't call this, use
   387  // getLLVMType instead.
   388  func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
   389  	switch typ := goType.(type) {
   390  	case *types.Array:
   391  		elemType := c.getLLVMType(typ.Elem())
   392  		return llvm.ArrayType(elemType, int(typ.Len()))
   393  	case *types.Basic:
   394  		switch typ.Kind() {
   395  		case types.Bool, types.UntypedBool:
   396  			return c.ctx.Int1Type()
   397  		case types.Int8, types.Uint8:
   398  			return c.ctx.Int8Type()
   399  		case types.Int16, types.Uint16:
   400  			return c.ctx.Int16Type()
   401  		case types.Int32, types.Uint32:
   402  			return c.ctx.Int32Type()
   403  		case types.Int, types.Uint:
   404  			return c.intType
   405  		case types.Int64, types.Uint64:
   406  			return c.ctx.Int64Type()
   407  		case types.Float32:
   408  			return c.ctx.FloatType()
   409  		case types.Float64:
   410  			return c.ctx.DoubleType()
   411  		case types.Complex64:
   412  			return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)
   413  		case types.Complex128:
   414  			return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)
   415  		case types.String, types.UntypedString:
   416  			return c.getLLVMRuntimeType("_string")
   417  		case types.Uintptr:
   418  			return c.uintptrType
   419  		case types.UnsafePointer:
   420  			return c.dataPtrType
   421  		default:
   422  			panic("unknown basic type: " + typ.String())
   423  		}
   424  	case *types.Chan, *types.Map, *types.Pointer:
   425  		return c.dataPtrType // all pointers are the same
   426  	case *types.Interface:
   427  		return c.getLLVMRuntimeType("_interface")
   428  	case *types.Named:
   429  		if st, ok := typ.Underlying().(*types.Struct); ok {
   430  			// Structs are a special case. While other named types are ignored
   431  			// in LLVM IR, named structs are implemented as named structs in
   432  			// LLVM. This is because it is otherwise impossible to create
   433  			// self-referencing types such as linked lists.
   434  			llvmName := typ.String()
   435  			llvmType := c.ctx.StructCreateNamed(llvmName)
   436  			c.llvmTypes.Set(goType, llvmType) // avoid infinite recursion
   437  			underlying := c.getLLVMType(st)
   438  			llvmType.StructSetBody(underlying.StructElementTypes(), false)
   439  			return llvmType
   440  		}
   441  		return c.getLLVMType(typ.Underlying())
   442  	case *types.Signature: // function value
   443  		return c.getFuncType(typ)
   444  	case *types.Slice:
   445  		members := []llvm.Type{
   446  			c.dataPtrType,
   447  			c.uintptrType, // len
   448  			c.uintptrType, // cap
   449  		}
   450  		return c.ctx.StructType(members, false)
   451  	case *types.Struct:
   452  		members := make([]llvm.Type, typ.NumFields())
   453  		for i := 0; i < typ.NumFields(); i++ {
   454  			members[i] = c.getLLVMType(typ.Field(i).Type())
   455  		}
   456  		return c.ctx.StructType(members, false)
   457  	case *types.TypeParam:
   458  		return c.getLLVMType(typ.Underlying())
   459  	case *types.Tuple:
   460  		members := make([]llvm.Type, typ.Len())
   461  		for i := 0; i < typ.Len(); i++ {
   462  			members[i] = c.getLLVMType(typ.At(i).Type())
   463  		}
   464  		return c.ctx.StructType(members, false)
   465  	default:
   466  		panic("unknown type: " + goType.String())
   467  	}
   468  }
   469  
   470  // Is this a pointer type of some sort? Can be unsafe.Pointer or any *T pointer.
   471  func isPointer(typ types.Type) bool {
   472  	if _, ok := typ.(*types.Pointer); ok {
   473  		return true
   474  	} else if typ, ok := typ.(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
   475  		return true
   476  	} else {
   477  		return false
   478  	}
   479  }
   480  
   481  // Get the DWARF type for this Go type.
   482  func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
   483  	if md, ok := c.ditypes[typ]; ok {
   484  		return md
   485  	}
   486  	md := c.createDIType(typ)
   487  	c.ditypes[typ] = md
   488  	return md
   489  }
   490  
   491  // createDIType creates a new DWARF type. Don't call this function directly,
   492  // call getDIType instead.
   493  func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
   494  	llvmType := c.getLLVMType(typ)
   495  	sizeInBytes := c.targetData.TypeAllocSize(llvmType)
   496  	switch typ := typ.(type) {
   497  	case *types.Array:
   498  		return c.dibuilder.CreateArrayType(llvm.DIArrayType{
   499  			SizeInBits:  sizeInBytes * 8,
   500  			AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   501  			ElementType: c.getDIType(typ.Elem()),
   502  			Subscripts: []llvm.DISubrange{
   503  				{
   504  					Lo:    0,
   505  					Count: typ.Len(),
   506  				},
   507  			},
   508  		})
   509  	case *types.Basic:
   510  		var encoding llvm.DwarfTypeEncoding
   511  		if typ.Info()&types.IsBoolean != 0 {
   512  			encoding = llvm.DW_ATE_boolean
   513  		} else if typ.Info()&types.IsFloat != 0 {
   514  			encoding = llvm.DW_ATE_float
   515  		} else if typ.Info()&types.IsComplex != 0 {
   516  			encoding = llvm.DW_ATE_complex_float
   517  		} else if typ.Info()&types.IsUnsigned != 0 {
   518  			encoding = llvm.DW_ATE_unsigned
   519  		} else if typ.Info()&types.IsInteger != 0 {
   520  			encoding = llvm.DW_ATE_signed
   521  		} else if typ.Kind() == types.UnsafePointer {
   522  			return c.dibuilder.CreatePointerType(llvm.DIPointerType{
   523  				Name:         "unsafe.Pointer",
   524  				SizeInBits:   c.targetData.TypeAllocSize(llvmType) * 8,
   525  				AlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   526  				AddressSpace: 0,
   527  			})
   528  		} else if typ.Info()&types.IsString != 0 {
   529  			return c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{
   530  				Name:        "string",
   531  				SizeInBits:  sizeInBytes * 8,
   532  				AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   533  				Elements: []llvm.Metadata{
   534  					c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   535  						Name:         "ptr",
   536  						SizeInBits:   c.targetData.TypeAllocSize(c.dataPtrType) * 8,
   537  						AlignInBits:  uint32(c.targetData.ABITypeAlignment(c.dataPtrType)) * 8,
   538  						OffsetInBits: 0,
   539  						Type:         c.getDIType(types.NewPointer(types.Typ[types.Byte])),
   540  					}),
   541  					c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   542  						Name:         "len",
   543  						SizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,
   544  						AlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,
   545  						OffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,
   546  						Type:         c.getDIType(types.Typ[types.Uintptr]),
   547  					}),
   548  				},
   549  			})
   550  		} else {
   551  			panic("unknown basic type")
   552  		}
   553  		return c.dibuilder.CreateBasicType(llvm.DIBasicType{
   554  			Name:       typ.String(),
   555  			SizeInBits: sizeInBytes * 8,
   556  			Encoding:   encoding,
   557  		})
   558  	case *types.Chan:
   559  		return c.getDIType(types.NewPointer(c.program.ImportedPackage("runtime").Members["channel"].(*ssa.Type).Type()))
   560  	case *types.Interface:
   561  		return c.getDIType(c.program.ImportedPackage("runtime").Members["_interface"].(*ssa.Type).Type())
   562  	case *types.Map:
   563  		return c.getDIType(types.NewPointer(c.program.ImportedPackage("runtime").Members["hashmap"].(*ssa.Type).Type()))
   564  	case *types.Named:
   565  		// Placeholder metadata node, to be replaced afterwards.
   566  		temporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{
   567  			Tag:         dwarf.TagTypedef,
   568  			SizeInBits:  sizeInBytes * 8,
   569  			AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   570  		})
   571  		c.ditypes[typ] = temporaryMDNode
   572  		md := c.dibuilder.CreateTypedef(llvm.DITypedef{
   573  			Type: c.getDIType(typ.Underlying()),
   574  			Name: typ.String(),
   575  		})
   576  		temporaryMDNode.ReplaceAllUsesWith(md)
   577  		return md
   578  	case *types.Pointer:
   579  		return c.dibuilder.CreatePointerType(llvm.DIPointerType{
   580  			Pointee:      c.getDIType(typ.Elem()),
   581  			SizeInBits:   c.targetData.TypeAllocSize(llvmType) * 8,
   582  			AlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   583  			AddressSpace: 0,
   584  		})
   585  	case *types.Signature:
   586  		// actually a closure
   587  		fields := llvmType.StructElementTypes()
   588  		return c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{
   589  			SizeInBits:  sizeInBytes * 8,
   590  			AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   591  			Elements: []llvm.Metadata{
   592  				c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   593  					Name:         "context",
   594  					SizeInBits:   c.targetData.TypeAllocSize(fields[1]) * 8,
   595  					AlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[1])) * 8,
   596  					OffsetInBits: 0,
   597  					Type:         c.getDIType(types.Typ[types.UnsafePointer]),
   598  				}),
   599  				c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   600  					Name:         "fn",
   601  					SizeInBits:   c.targetData.TypeAllocSize(fields[0]) * 8,
   602  					AlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[0])) * 8,
   603  					OffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,
   604  					Type:         c.getDIType(types.Typ[types.UnsafePointer]),
   605  				}),
   606  			},
   607  		})
   608  	case *types.Slice:
   609  		fields := llvmType.StructElementTypes()
   610  		return c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{
   611  			Name:        typ.String(),
   612  			SizeInBits:  sizeInBytes * 8,
   613  			AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   614  			Elements: []llvm.Metadata{
   615  				c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   616  					Name:         "ptr",
   617  					SizeInBits:   c.targetData.TypeAllocSize(fields[0]) * 8,
   618  					AlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[0])) * 8,
   619  					OffsetInBits: 0,
   620  					Type:         c.getDIType(types.NewPointer(typ.Elem())),
   621  				}),
   622  				c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   623  					Name:         "len",
   624  					SizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,
   625  					AlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,
   626  					OffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,
   627  					Type:         c.getDIType(types.Typ[types.Uintptr]),
   628  				}),
   629  				c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   630  					Name:         "cap",
   631  					SizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,
   632  					AlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,
   633  					OffsetInBits: c.targetData.ElementOffset(llvmType, 2) * 8,
   634  					Type:         c.getDIType(types.Typ[types.Uintptr]),
   635  				}),
   636  			},
   637  		})
   638  	case *types.Struct:
   639  		elements := make([]llvm.Metadata, typ.NumFields())
   640  		for i := range elements {
   641  			field := typ.Field(i)
   642  			fieldType := field.Type()
   643  			llvmField := c.getLLVMType(fieldType)
   644  			elements[i] = c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{
   645  				Name:         field.Name(),
   646  				SizeInBits:   c.targetData.TypeAllocSize(llvmField) * 8,
   647  				AlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmField)) * 8,
   648  				OffsetInBits: c.targetData.ElementOffset(llvmType, i) * 8,
   649  				Type:         c.getDIType(fieldType),
   650  			})
   651  		}
   652  		md := c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{
   653  			SizeInBits:  sizeInBytes * 8,
   654  			AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
   655  			Elements:    elements,
   656  		})
   657  		return md
   658  	case *types.TypeParam:
   659  		return c.getDIType(typ.Underlying())
   660  	default:
   661  		panic("unknown type while generating DWARF debug type: " + typ.String())
   662  	}
   663  }
   664  
   665  // setDebugLocation sets the current debug location for the builder.
   666  func (b *builder) setDebugLocation(pos token.Pos) {
   667  	if pos == token.NoPos {
   668  		// No debug information available for this instruction.
   669  		b.SetCurrentDebugLocation(0, 0, b.difunc, llvm.Metadata{})
   670  		return
   671  	}
   672  
   673  	position := b.program.Fset.Position(pos)
   674  	if b.fn.Synthetic == "package initializer" {
   675  		// Package initializers are treated specially, because while individual
   676  		// Go SSA instructions have file/line/col information, the parent
   677  		// function does not. LLVM doesn't store filename information per
   678  		// instruction, only per function. We work around this difference by
   679  		// creating a fake DIFunction for each Go file and say that the
   680  		// instruction really came from that (fake) function but was inlined in
   681  		// the package initializer function.
   682  		position := b.program.Fset.Position(pos)
   683  		name := filepath.Base(position.Filename)
   684  		difunc, ok := b.initPseudoFuncs[name]
   685  		if !ok {
   686  			diFuncType := b.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
   687  				File: b.getDIFile(position.Filename),
   688  			})
   689  			difunc = b.dibuilder.CreateFunction(b.getDIFile(position.Filename), llvm.DIFunction{
   690  				Name:         b.fn.RelString(nil) + "#" + name,
   691  				File:         b.getDIFile(position.Filename),
   692  				Line:         0,
   693  				Type:         diFuncType,
   694  				LocalToUnit:  true,
   695  				IsDefinition: true,
   696  				ScopeLine:    0,
   697  				Flags:        llvm.FlagPrototyped,
   698  				Optimized:    true,
   699  			})
   700  			b.initPseudoFuncs[name] = difunc
   701  		}
   702  		b.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), difunc, b.initInlinedAt)
   703  		return
   704  	}
   705  
   706  	// Regular debug information.
   707  	b.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), b.difunc, llvm.Metadata{})
   708  }
   709  
   710  // getLocalVariable returns a debug info entry for a local variable, which may
   711  // either be a parameter or a regular variable. It will create a new metadata
   712  // entry if there isn't one for the variable yet.
   713  func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {
   714  	if dilocal, ok := b.dilocals[variable]; ok {
   715  		// DILocalVariable was already created, return it directly.
   716  		return dilocal
   717  	}
   718  
   719  	pos := b.program.Fset.Position(variable.Pos())
   720  
   721  	// Check whether this is a function parameter.
   722  	for i, param := range b.fn.Params {
   723  		if param.Object().(*types.Var) == variable {
   724  			// Yes it is, create it as a function parameter.
   725  			dilocal := b.dibuilder.CreateParameterVariable(b.difunc, llvm.DIParameterVariable{
   726  				Name:           param.Name(),
   727  				File:           b.getDIFile(pos.Filename),
   728  				Line:           pos.Line,
   729  				Type:           b.getDIType(param.Type()),
   730  				AlwaysPreserve: true,
   731  				ArgNo:          i + 1,
   732  			})
   733  			b.dilocals[variable] = dilocal
   734  			return dilocal
   735  		}
   736  	}
   737  
   738  	// No, it's not a parameter. Create a regular (auto) variable.
   739  	dilocal := b.dibuilder.CreateAutoVariable(b.difunc, llvm.DIAutoVariable{
   740  		Name:           variable.Name(),
   741  		File:           b.getDIFile(pos.Filename),
   742  		Line:           pos.Line,
   743  		Type:           b.getDIType(variable.Type()),
   744  		AlwaysPreserve: true,
   745  	})
   746  	b.dilocals[variable] = dilocal
   747  	return dilocal
   748  }
   749  
   750  // attachDebugInfo adds debug info to a function declaration. It returns the
   751  // DISubprogram metadata node.
   752  func (c *compilerContext) attachDebugInfo(f *ssa.Function) llvm.Metadata {
   753  	pos := c.program.Fset.Position(f.Syntax().Pos())
   754  	_, fn := c.getFunction(f)
   755  	return c.attachDebugInfoRaw(f, fn, "", pos.Filename, pos.Line)
   756  }
   757  
   758  // attachDebugInfo adds debug info to a function declaration. It returns the
   759  // DISubprogram metadata node. This method allows some more control over how
   760  // debug info is added to the function.
   761  func (c *compilerContext) attachDebugInfoRaw(f *ssa.Function, llvmFn llvm.Value, suffix, filename string, line int) llvm.Metadata {
   762  	// Debug info for this function.
   763  	params := getParams(f.Signature)
   764  	diparams := make([]llvm.Metadata, 0, len(params))
   765  	for _, param := range params {
   766  		diparams = append(diparams, c.getDIType(param.Type()))
   767  	}
   768  	diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
   769  		File:       c.getDIFile(filename),
   770  		Parameters: diparams,
   771  		Flags:      0, // ?
   772  	})
   773  	difunc := c.dibuilder.CreateFunction(c.getDIFile(filename), llvm.DIFunction{
   774  		Name:         f.RelString(nil) + suffix,
   775  		LinkageName:  c.getFunctionInfo(f).linkName + suffix,
   776  		File:         c.getDIFile(filename),
   777  		Line:         line,
   778  		Type:         diFuncType,
   779  		LocalToUnit:  true,
   780  		IsDefinition: true,
   781  		ScopeLine:    0,
   782  		Flags:        llvm.FlagPrototyped,
   783  		Optimized:    true,
   784  	})
   785  	llvmFn.SetSubprogram(difunc)
   786  	return difunc
   787  }
   788  
   789  // getDIFile returns a DIFile metadata node for the given filename. It tries to
   790  // use one that was already created, otherwise it falls back to creating a new
   791  // one.
   792  func (c *compilerContext) getDIFile(filename string) llvm.Metadata {
   793  	if _, ok := c.difiles[filename]; !ok {
   794  		dir, file := filepath.Split(filename)
   795  		if dir != "" {
   796  			dir = dir[:len(dir)-1]
   797  		}
   798  		c.difiles[filename] = c.dibuilder.CreateFile(file, dir)
   799  	}
   800  	return c.difiles[filename]
   801  }
   802  
   803  // createPackage builds the LLVM IR for all types, methods, and global variables
   804  // in the given package.
   805  func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package) {
   806  	// Sort by position, so that the order of the functions in the IR matches
   807  	// the order of functions in the source file. This is useful for testing,
   808  	// for example.
   809  	var members []string
   810  	for name := range pkg.Members {
   811  		members = append(members, name)
   812  	}
   813  	sort.Slice(members, func(i, j int) bool {
   814  		iPos := pkg.Members[members[i]].Pos()
   815  		jPos := pkg.Members[members[j]].Pos()
   816  		if i == j {
   817  			// Cannot sort by pos, so do it by name.
   818  			return members[i] < members[j]
   819  		}
   820  		return iPos < jPos
   821  	})
   822  
   823  	// Define all functions.
   824  	for _, name := range members {
   825  		member := pkg.Members[name]
   826  		switch member := member.(type) {
   827  		case *ssa.Function:
   828  			if member.TypeParams() != nil {
   829  				// Do not try to build generic (non-instantiated) functions.
   830  				continue
   831  			}
   832  			// Create the function definition.
   833  			b := newBuilder(c, irbuilder, member)
   834  			if _, ok := mathToLLVMMapping[member.RelString(nil)]; ok {
   835  				// The body of this function (if there is one) is ignored and
   836  				// replaced with a LLVM intrinsic call.
   837  				b.defineMathOp()
   838  				continue
   839  			}
   840  			if ok := b.defineMathBitsIntrinsic(); ok {
   841  				// Like a math intrinsic, the body of this function was replaced
   842  				// with a LLVM intrinsic.
   843  				continue
   844  			}
   845  			if member.Blocks == nil {
   846  				// Try to define this as an intrinsic function.
   847  				b.defineIntrinsicFunction()
   848  				// It might not be an intrinsic function but simply an external
   849  				// function (defined via //go:linkname). Leave it undefined in
   850  				// that case.
   851  				continue
   852  			}
   853  			b.createFunction()
   854  		case *ssa.Type:
   855  			if types.IsInterface(member.Type()) {
   856  				// Interfaces don't have concrete methods.
   857  				continue
   858  			}
   859  
   860  			// Named type. We should make sure all methods are created.
   861  			// This includes both functions with pointer receivers and those
   862  			// without.
   863  			methods := getAllMethods(pkg.Prog, member.Type())
   864  			methods = append(methods, getAllMethods(pkg.Prog, types.NewPointer(member.Type()))...)
   865  			for _, method := range methods {
   866  				// Parse this method.
   867  				fn := pkg.Prog.MethodValue(method)
   868  				if fn == nil {
   869  					continue // probably a generic method
   870  				}
   871  				if member.Type().String() != member.String() {
   872  					// This is a member on a type alias. Do not build such a
   873  					// function.
   874  					continue
   875  				}
   876  				if fn.Blocks == nil {
   877  					continue // external function
   878  				}
   879  				if fn.Synthetic != "" && fn.Synthetic != "package initializer" {
   880  					// This function is a kind of wrapper function (created by
   881  					// the ssa package, not appearing in the source code) that
   882  					// is created by the getFunction method as needed.
   883  					// Therefore, don't build it here to avoid "function
   884  					// redeclared" errors.
   885  					continue
   886  				}
   887  				// Create the function definition.
   888  				b := newBuilder(c, irbuilder, fn)
   889  				b.createFunction()
   890  			}
   891  		case *ssa.Global:
   892  			// Global variable.
   893  			info := c.getGlobalInfo(member)
   894  			global := c.getGlobal(member)
   895  			if files, ok := c.embedGlobals[member.Name()]; ok {
   896  				c.createEmbedGlobal(member, global, files)
   897  			} else if !info.extern {
   898  				global.SetInitializer(llvm.ConstNull(global.GlobalValueType()))
   899  				global.SetVisibility(llvm.HiddenVisibility)
   900  				if info.section != "" {
   901  					global.SetSection(info.section)
   902  				}
   903  			}
   904  		}
   905  	}
   906  
   907  	// Add forwarding functions for functions that would otherwise be
   908  	// implemented in assembly.
   909  	for _, name := range members {
   910  		member := pkg.Members[name]
   911  		switch member := member.(type) {
   912  		case *ssa.Function:
   913  			if member.Blocks != nil {
   914  				continue // external function
   915  			}
   916  			info := c.getFunctionInfo(member)
   917  			if aliasName, ok := stdlibAliases[info.linkName]; ok {
   918  				alias := c.mod.NamedFunction(aliasName)
   919  				if alias.IsNil() {
   920  					// Shouldn't happen, but perhaps best to just ignore.
   921  					// The error will be a link error, if there is an error.
   922  					continue
   923  				}
   924  				b := newBuilder(c, irbuilder, member)
   925  				b.createAlias(alias)
   926  			}
   927  		}
   928  	}
   929  }
   930  
   931  // createEmbedGlobal creates an initializer for a //go:embed global variable.
   932  func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Value, files []*loader.EmbedFile) {
   933  	switch typ := member.Type().(*types.Pointer).Elem().Underlying().(type) {
   934  	case *types.Basic:
   935  		// String type.
   936  		if typ.Kind() != types.String {
   937  			// This is checked at the AST level, so should be unreachable.
   938  			panic("expected a string type")
   939  		}
   940  		if len(files) != 1 {
   941  			c.addError(member.Pos(), fmt.Sprintf("//go:embed for a string should be given exactly one file, got %d", len(files)))
   942  			return
   943  		}
   944  		strObj := c.getEmbedFileString(files[0])
   945  		global.SetInitializer(strObj)
   946  		global.SetVisibility(llvm.HiddenVisibility)
   947  
   948  	case *types.Slice:
   949  		if typ.Elem().Underlying().(*types.Basic).Kind() != types.Byte {
   950  			// This is checked at the AST level, so should be unreachable.
   951  			panic("expected a byte slice")
   952  		}
   953  		if len(files) != 1 {
   954  			c.addError(member.Pos(), fmt.Sprintf("//go:embed for a string should be given exactly one file, got %d", len(files)))
   955  			return
   956  		}
   957  		file := files[0]
   958  		bufferValue := c.ctx.ConstString(string(file.Data), false)
   959  		bufferGlobal := llvm.AddGlobal(c.mod, bufferValue.Type(), c.pkg.Path()+"$embedslice")
   960  		bufferGlobal.SetInitializer(bufferValue)
   961  		bufferGlobal.SetLinkage(llvm.InternalLinkage)
   962  		bufferGlobal.SetAlignment(1)
   963  		slicePtr := llvm.ConstInBoundsGEP(bufferValue.Type(), bufferGlobal, []llvm.Value{
   964  			llvm.ConstInt(c.uintptrType, 0, false),
   965  			llvm.ConstInt(c.uintptrType, 0, false),
   966  		})
   967  		sliceLen := llvm.ConstInt(c.uintptrType, file.Size, false)
   968  		sliceObj := c.ctx.ConstStruct([]llvm.Value{slicePtr, sliceLen, sliceLen}, false)
   969  		global.SetInitializer(sliceObj)
   970  		global.SetVisibility(llvm.HiddenVisibility)
   971  
   972  		if c.Debug {
   973  			// Add debug info to the slice backing array.
   974  			position := c.program.Fset.Position(member.Pos())
   975  			diglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{
   976  				File:        c.getDIFile(position.Filename),
   977  				Line:        position.Line,
   978  				Type:        c.getDIType(types.NewArray(types.Typ[types.Byte], int64(len(file.Data)))),
   979  				LocalToUnit: true,
   980  				Expr:        c.dibuilder.CreateExpression(nil),
   981  			})
   982  			bufferGlobal.AddMetadata(0, diglobal)
   983  		}
   984  
   985  	case *types.Struct:
   986  		// Assume this is an embed.FS struct:
   987  		// https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/embed/embed.go;l=148
   988  		// It looks like this:
   989  		//   type FS struct {
   990  		//       files *file
   991  		//   }
   992  
   993  		// Make a slice of the files, as they will appear in the binary. They
   994  		// are sorted in a special way to allow for binary searches, see
   995  		// src/embed/embed.go for details.
   996  		dirset := map[string]struct{}{}
   997  		var allFiles []*loader.EmbedFile
   998  		for _, file := range files {
   999  			allFiles = append(allFiles, file)
  1000  			dirname := file.Name
  1001  			for {
  1002  				dirname, _ = path.Split(path.Clean(dirname))
  1003  				if dirname == "" {
  1004  					break
  1005  				}
  1006  				if _, ok := dirset[dirname]; ok {
  1007  					break
  1008  				}
  1009  				dirset[dirname] = struct{}{}
  1010  				allFiles = append(allFiles, &loader.EmbedFile{
  1011  					Name: dirname,
  1012  				})
  1013  			}
  1014  		}
  1015  		sort.Slice(allFiles, func(i, j int) bool {
  1016  			dir1, name1 := path.Split(path.Clean(allFiles[i].Name))
  1017  			dir2, name2 := path.Split(path.Clean(allFiles[j].Name))
  1018  			if dir1 != dir2 {
  1019  				return dir1 < dir2
  1020  			}
  1021  			return name1 < name2
  1022  		})
  1023  
  1024  		// Make the backing array for the []files slice. This is a LLVM global.
  1025  		embedFileStructType := typ.Field(0).Type().(*types.Pointer).Elem().(*types.Slice).Elem()
  1026  		llvmEmbedFileStructType := c.getLLVMType(embedFileStructType)
  1027  		var fileStructs []llvm.Value
  1028  		for _, file := range allFiles {
  1029  			fileStruct := llvm.ConstNull(llvmEmbedFileStructType)
  1030  			name := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String]), getPos(member))
  1031  			fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") // "name" field
  1032  			if file.Hash != "" {
  1033  				data := c.getEmbedFileString(file)
  1034  				fileStruct = c.builder.CreateInsertValue(fileStruct, data, 1, "") // "data" field
  1035  			}
  1036  			fileStructs = append(fileStructs, fileStruct)
  1037  		}
  1038  		sliceDataInitializer := llvm.ConstArray(llvmEmbedFileStructType, fileStructs)
  1039  		sliceDataGlobal := llvm.AddGlobal(c.mod, sliceDataInitializer.Type(), c.pkg.Path()+"$embedfsfiles")
  1040  		sliceDataGlobal.SetInitializer(sliceDataInitializer)
  1041  		sliceDataGlobal.SetLinkage(llvm.InternalLinkage)
  1042  		sliceDataGlobal.SetGlobalConstant(true)
  1043  		sliceDataGlobal.SetUnnamedAddr(true)
  1044  		sliceDataGlobal.SetAlignment(c.targetData.ABITypeAlignment(sliceDataInitializer.Type()))
  1045  		if c.Debug {
  1046  			// Add debug information for code size attribution (among others).
  1047  			position := c.program.Fset.Position(member.Pos())
  1048  			diglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{
  1049  				File:        c.getDIFile(position.Filename),
  1050  				Line:        position.Line,
  1051  				Type:        c.getDIType(types.NewArray(embedFileStructType, int64(len(allFiles)))),
  1052  				LocalToUnit: true,
  1053  				Expr:        c.dibuilder.CreateExpression(nil),
  1054  			})
  1055  			sliceDataGlobal.AddMetadata(0, diglobal)
  1056  		}
  1057  
  1058  		// Create the slice object itself.
  1059  		// Because embed.FS refers to it as *[]embed.file instead of a plain
  1060  		// []embed.file, we have to store this as a global.
  1061  		slicePtr := llvm.ConstInBoundsGEP(sliceDataInitializer.Type(), sliceDataGlobal, []llvm.Value{
  1062  			llvm.ConstInt(c.uintptrType, 0, false),
  1063  			llvm.ConstInt(c.uintptrType, 0, false),
  1064  		})
  1065  		sliceLen := llvm.ConstInt(c.uintptrType, uint64(len(fileStructs)), false)
  1066  		sliceInitializer := c.ctx.ConstStruct([]llvm.Value{slicePtr, sliceLen, sliceLen}, false)
  1067  		sliceGlobal := llvm.AddGlobal(c.mod, sliceInitializer.Type(), c.pkg.Path()+"$embedfsslice")
  1068  		sliceGlobal.SetInitializer(sliceInitializer)
  1069  		sliceGlobal.SetLinkage(llvm.InternalLinkage)
  1070  		sliceGlobal.SetGlobalConstant(true)
  1071  		sliceGlobal.SetUnnamedAddr(true)
  1072  		sliceGlobal.SetAlignment(c.targetData.ABITypeAlignment(sliceInitializer.Type()))
  1073  		if c.Debug {
  1074  			position := c.program.Fset.Position(member.Pos())
  1075  			diglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{
  1076  				File:        c.getDIFile(position.Filename),
  1077  				Line:        position.Line,
  1078  				Type:        c.getDIType(types.NewSlice(embedFileStructType)),
  1079  				LocalToUnit: true,
  1080  				Expr:        c.dibuilder.CreateExpression(nil),
  1081  			})
  1082  			sliceGlobal.AddMetadata(0, diglobal)
  1083  		}
  1084  
  1085  		// Define the embed.FS struct. It has only one field: the files (as a
  1086  		// *[]embed.file).
  1087  		globalInitializer := llvm.ConstNull(c.getLLVMType(member.Type().(*types.Pointer).Elem()))
  1088  		globalInitializer = c.builder.CreateInsertValue(globalInitializer, sliceGlobal, 0, "")
  1089  		global.SetInitializer(globalInitializer)
  1090  		global.SetVisibility(llvm.HiddenVisibility)
  1091  		global.SetAlignment(c.targetData.ABITypeAlignment(globalInitializer.Type()))
  1092  	}
  1093  }
  1094  
  1095  // getEmbedFileString returns the (constant) string object with the contents of
  1096  // the given file. This is a llvm.Value of a regular Go string.
  1097  func (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value {
  1098  	dataGlobalName := "embed/file_" + file.Hash
  1099  	dataGlobal := c.mod.NamedGlobal(dataGlobalName)
  1100  	dataGlobalType := llvm.ArrayType(c.ctx.Int8Type(), int(file.Size))
  1101  	if dataGlobal.IsNil() {
  1102  		dataGlobal = llvm.AddGlobal(c.mod, dataGlobalType, dataGlobalName)
  1103  	}
  1104  	strPtr := llvm.ConstInBoundsGEP(dataGlobalType, dataGlobal, []llvm.Value{
  1105  		llvm.ConstInt(c.uintptrType, 0, false),
  1106  		llvm.ConstInt(c.uintptrType, 0, false),
  1107  	})
  1108  	strLen := llvm.ConstInt(c.uintptrType, file.Size, false)
  1109  	return llvm.ConstNamedStruct(c.getLLVMRuntimeType("_string"), []llvm.Value{strPtr, strLen})
  1110  }
  1111  
  1112  // Start defining a function so that it can be filled with instructions: load
  1113  // parameters, create basic blocks, and set up debug information.
  1114  // This is separated out from createFunction() so that it is also usable to
  1115  // define compiler intrinsics like the atomic operations in sync/atomic.
  1116  func (b *builder) createFunctionStart(intrinsic bool) {
  1117  	if b.DumpSSA {
  1118  		fmt.Printf("\nfunc %s:\n", b.fn)
  1119  	}
  1120  	if !b.llvmFn.IsDeclaration() {
  1121  		errValue := b.llvmFn.Name() + " redeclared in this program"
  1122  		fnPos := getPosition(b.llvmFn)
  1123  		if fnPos.IsValid() {
  1124  			errValue += "\n\tprevious declaration at " + fnPos.String()
  1125  		}
  1126  		b.addError(b.fn.Pos(), errValue)
  1127  		return
  1128  	}
  1129  
  1130  	b.addStandardDefinedAttributes(b.llvmFn)
  1131  	if !b.info.exported {
  1132  		// Do not set visibility for local linkage (internal or private).
  1133  		// Otherwise a "local linkage requires default visibility"
  1134  		// assertion error in llvm-project/llvm/include/llvm/IR/GlobalValue.h:236
  1135  		// is thrown.
  1136  		if b.llvmFn.Linkage() != llvm.InternalLinkage &&
  1137  			b.llvmFn.Linkage() != llvm.PrivateLinkage {
  1138  			b.llvmFn.SetVisibility(llvm.HiddenVisibility)
  1139  		}
  1140  		b.llvmFn.SetUnnamedAddr(true)
  1141  	}
  1142  	if b.info.section != "" {
  1143  		b.llvmFn.SetSection(b.info.section)
  1144  	}
  1145  	if b.info.exported && strings.HasPrefix(b.Triple, "wasm") {
  1146  		// Set the exported name. This is necessary for WebAssembly because
  1147  		// otherwise the function is not exported.
  1148  		functionAttr := b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName)
  1149  		b.llvmFn.AddFunctionAttr(functionAttr)
  1150  		// Unlike most targets, exported functions are actually visible in
  1151  		// WebAssembly (even if it's not called from within the WebAssembly
  1152  		// module). But LTO generally optimizes such functions away. Therefore,
  1153  		// exported functions must be explicitly marked as used.
  1154  		llvmutil.AppendToGlobal(b.mod, "llvm.used", b.llvmFn)
  1155  	}
  1156  
  1157  	// Some functions have a pragma controlling the inlining level.
  1158  	switch b.info.inline {
  1159  	case inlineHint:
  1160  		// Add LLVM inline hint to functions with //go:inline pragma.
  1161  		inline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("inlinehint"), 0)
  1162  		b.llvmFn.AddFunctionAttr(inline)
  1163  	case inlineNone:
  1164  		// Add LLVM attribute to always avoid inlining this function.
  1165  		noinline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("noinline"), 0)
  1166  		b.llvmFn.AddFunctionAttr(noinline)
  1167  	}
  1168  
  1169  	if b.info.interrupt {
  1170  		// Mark this function as an interrupt.
  1171  		// This is necessary on MCUs that don't push caller saved registers when
  1172  		// entering an interrupt, such as on AVR.
  1173  		if strings.HasPrefix(b.Triple, "avr") {
  1174  			b.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("signal", ""))
  1175  		} else {
  1176  			b.addError(b.fn.Pos(), "//go:interrupt not supported on this architecture")
  1177  		}
  1178  	}
  1179  
  1180  	// Add debug info, if needed.
  1181  	if b.Debug {
  1182  		if b.fn.Synthetic == "package initializer" {
  1183  			// Package initializer functions have no debug info. Create some
  1184  			// fake debug info to at least have *something*.
  1185  			b.difunc = b.attachDebugInfoRaw(b.fn, b.llvmFn, "", b.packageDir, 0)
  1186  		} else if b.fn.Syntax() != nil {
  1187  			// Create debug info file if needed.
  1188  			b.difunc = b.attachDebugInfo(b.fn)
  1189  		}
  1190  		b.setDebugLocation(b.fn.Pos())
  1191  	}
  1192  
  1193  	// Pre-create all basic blocks in the function.
  1194  	var entryBlock llvm.BasicBlock
  1195  	if intrinsic {
  1196  		// This function isn't defined in Go SSA. It is probably a compiler
  1197  		// intrinsic (like an atomic operation). Create the entry block
  1198  		// manually.
  1199  		entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry")
  1200  	} else {
  1201  		for _, block := range b.fn.DomPreorder() {
  1202  			llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
  1203  			b.blockEntries[block] = llvmBlock
  1204  			b.blockExits[block] = llvmBlock
  1205  		}
  1206  		// Normal functions have an entry block.
  1207  		entryBlock = b.blockEntries[b.fn.Blocks[0]]
  1208  	}
  1209  	b.SetInsertPointAtEnd(entryBlock)
  1210  
  1211  	if b.fn.Synthetic == "package initializer" {
  1212  		b.initPseudoFuncs = make(map[string]llvm.Metadata)
  1213  
  1214  		// Create a fake 'inlined at' metadata node.
  1215  		// See setDebugLocation for details.
  1216  		alloca := b.CreateAlloca(b.uintptrType, "")
  1217  		b.initInlinedAt = alloca.InstructionDebugLoc()
  1218  		alloca.EraseFromParentAsInstruction()
  1219  	}
  1220  
  1221  	// Load function parameters
  1222  	llvmParamIndex := 0
  1223  	for _, param := range b.fn.Params {
  1224  		llvmType := b.getLLVMType(param.Type())
  1225  		fields := make([]llvm.Value, 0, 1)
  1226  		for _, info := range b.expandFormalParamType(llvmType, param.Name(), param.Type()) {
  1227  			param := b.llvmFn.Param(llvmParamIndex)
  1228  			param.SetName(info.name)
  1229  			fields = append(fields, param)
  1230  			llvmParamIndex++
  1231  		}
  1232  		b.locals[param] = b.collapseFormalParam(llvmType, fields)
  1233  
  1234  		// Add debug information to this parameter (if available)
  1235  		if b.Debug && b.fn.Syntax() != nil {
  1236  			dbgParam := b.getLocalVariable(param.Object().(*types.Var))
  1237  			loc := b.GetCurrentDebugLocation()
  1238  			if len(fields) == 1 {
  1239  				expr := b.dibuilder.CreateExpression(nil)
  1240  				b.dibuilder.InsertValueAtEnd(fields[0], dbgParam, expr, loc, entryBlock)
  1241  			} else {
  1242  				fieldOffsets := b.expandFormalParamOffsets(llvmType)
  1243  				for i, field := range fields {
  1244  					expr := b.dibuilder.CreateExpression([]uint64{
  1245  						0x1000,              // DW_OP_LLVM_fragment
  1246  						fieldOffsets[i] * 8, // offset in bits
  1247  						b.targetData.TypeAllocSize(field.Type()) * 8, // size in bits
  1248  					})
  1249  					b.dibuilder.InsertValueAtEnd(field, dbgParam, expr, loc, entryBlock)
  1250  				}
  1251  			}
  1252  		}
  1253  	}
  1254  
  1255  	// Load free variables from the context. This is a closure (or bound
  1256  	// method).
  1257  	var context llvm.Value
  1258  	if !b.info.exported {
  1259  		context = b.llvmFn.LastParam()
  1260  		context.SetName("context")
  1261  	}
  1262  	if len(b.fn.FreeVars) != 0 {
  1263  		// Get a list of all variable types in the context.
  1264  		freeVarTypes := make([]llvm.Type, len(b.fn.FreeVars))
  1265  		for i, freeVar := range b.fn.FreeVars {
  1266  			freeVarTypes[i] = b.getLLVMType(freeVar.Type())
  1267  		}
  1268  
  1269  		// Load each free variable from the context pointer.
  1270  		// A free variable is always a pointer when this is a closure, but it
  1271  		// can be another type when it is a wrapper for a bound method (these
  1272  		// wrappers are generated by the ssa package).
  1273  		for i, val := range b.emitPointerUnpack(context, freeVarTypes) {
  1274  			b.locals[b.fn.FreeVars[i]] = val
  1275  		}
  1276  	}
  1277  
  1278  	if b.fn.Recover != nil {
  1279  		// This function has deferred function calls. Set some things up for
  1280  		// them.
  1281  		b.deferInitFunc()
  1282  	}
  1283  
  1284  	if b.NeedsStackObjects {
  1285  		// Create a dummy alloca that will be used in runtime.trackPointer.
  1286  		// It is necessary to pass a dummy alloca to runtime.trackPointer
  1287  		// because runtime.trackPointer is replaced by an alloca store.
  1288  		b.stackChainAlloca = b.CreateAlloca(b.ctx.Int8Type(), "stackalloc")
  1289  	}
  1290  }
  1291  
  1292  // createFunction builds the LLVM IR implementation for this function. The
  1293  // function must not yet be defined, otherwise this function will create a
  1294  // diagnostic.
  1295  func (b *builder) createFunction() {
  1296  	b.createFunctionStart(false)
  1297  
  1298  	// Fill blocks with instructions.
  1299  	for _, block := range b.fn.DomPreorder() {
  1300  		if b.DumpSSA {
  1301  			fmt.Printf("%d: %s:\n", block.Index, block.Comment)
  1302  		}
  1303  		b.SetInsertPointAtEnd(b.blockEntries[block])
  1304  		b.currentBlock = block
  1305  		for _, instr := range block.Instrs {
  1306  			if instr, ok := instr.(*ssa.DebugRef); ok {
  1307  				if !b.Debug {
  1308  					continue
  1309  				}
  1310  				object := instr.Object()
  1311  				variable, ok := object.(*types.Var)
  1312  				if !ok {
  1313  					// Not a local variable.
  1314  					continue
  1315  				}
  1316  				if instr.IsAddr {
  1317  					// TODO, this may happen for *ssa.Alloc and *ssa.FieldAddr
  1318  					// for example.
  1319  					continue
  1320  				}
  1321  				dbgVar := b.getLocalVariable(variable)
  1322  				pos := b.program.Fset.Position(instr.Pos())
  1323  				b.dibuilder.InsertValueAtEnd(b.getValue(instr.X, getPos(instr)), dbgVar, b.dibuilder.CreateExpression(nil), llvm.DebugLoc{
  1324  					Line:  uint(pos.Line),
  1325  					Col:   uint(pos.Column),
  1326  					Scope: b.difunc,
  1327  				}, b.GetInsertBlock())
  1328  				continue
  1329  			}
  1330  			if b.DumpSSA {
  1331  				if val, ok := instr.(ssa.Value); ok && val.Name() != "" {
  1332  					fmt.Printf("\t%s = %s\n", val.Name(), val.String())
  1333  				} else {
  1334  					fmt.Printf("\t%s\n", instr.String())
  1335  				}
  1336  			}
  1337  			b.createInstruction(instr)
  1338  		}
  1339  		if b.fn.Name() == "init" && len(block.Instrs) == 0 {
  1340  			b.CreateRetVoid()
  1341  		}
  1342  	}
  1343  
  1344  	// The rundefers instruction needs to be created after all defer
  1345  	// instructions have been created. Otherwise it won't handle all defer
  1346  	// cases.
  1347  	for i, bb := range b.runDefersBlock {
  1348  		b.SetInsertPointAtEnd(bb)
  1349  		b.createRunDefers()
  1350  		b.CreateBr(b.afterDefersBlock[i])
  1351  	}
  1352  
  1353  	if b.hasDeferFrame() {
  1354  		// Create the landing pad block, where execution continues after a
  1355  		// panic.
  1356  		b.createLandingPad()
  1357  	}
  1358  
  1359  	// Resolve phi nodes
  1360  	for _, phi := range b.phis {
  1361  		block := phi.ssa.Block()
  1362  		for i, edge := range phi.ssa.Edges {
  1363  			llvmVal := b.getValue(edge, getPos(phi.ssa))
  1364  			llvmBlock := b.blockExits[block.Preds[i]]
  1365  			phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
  1366  		}
  1367  	}
  1368  
  1369  	if b.NeedsStackObjects {
  1370  		// Track phi nodes.
  1371  		for _, phi := range b.phis {
  1372  			insertPoint := llvm.NextInstruction(phi.llvm)
  1373  			for !insertPoint.IsAPHINode().IsNil() {
  1374  				insertPoint = llvm.NextInstruction(insertPoint)
  1375  			}
  1376  			b.SetInsertPointBefore(insertPoint)
  1377  			b.trackValue(phi.llvm)
  1378  		}
  1379  	}
  1380  
  1381  	// Create anonymous functions (closures etc.).
  1382  	for _, sub := range b.fn.AnonFuncs {
  1383  		b := newBuilder(b.compilerContext, b.Builder, sub)
  1384  		b.llvmFn.SetLinkage(llvm.InternalLinkage)
  1385  		b.createFunction()
  1386  	}
  1387  }
  1388  
  1389  // posser is an interface that's implemented by both ssa.Value and
  1390  // ssa.Instruction. It is implemented by everything that has a Pos() method,
  1391  // which is all that getPos() needs.
  1392  type posser interface {
  1393  	Pos() token.Pos
  1394  }
  1395  
  1396  // getPos returns position information for a ssa.Value or ssa.Instruction.
  1397  //
  1398  // Not all instructions have position information, especially when they're
  1399  // implicit (such as implicit casts or implicit returns at the end of a
  1400  // function). In these cases, it makes sense to try a bit harder to guess what
  1401  // the position really should be.
  1402  func getPos(val posser) token.Pos {
  1403  	pos := val.Pos()
  1404  	if pos != token.NoPos {
  1405  		// Easy: position is known.
  1406  		return pos
  1407  	}
  1408  
  1409  	// No position information is known.
  1410  	switch val := val.(type) {
  1411  	case *ssa.MakeInterface:
  1412  		return getPos(val.X)
  1413  	case *ssa.MakeClosure:
  1414  		return val.Fn.(*ssa.Function).Pos()
  1415  	case *ssa.Return:
  1416  		syntax := val.Parent().Syntax()
  1417  		if syntax != nil {
  1418  			// non-synthetic
  1419  			return syntax.End()
  1420  		}
  1421  		return token.NoPos
  1422  	case *ssa.FieldAddr:
  1423  		return getPos(val.X)
  1424  	case *ssa.IndexAddr:
  1425  		return getPos(val.X)
  1426  	case *ssa.Slice:
  1427  		return getPos(val.X)
  1428  	case *ssa.Store:
  1429  		return getPos(val.Addr)
  1430  	case *ssa.Extract:
  1431  		return getPos(val.Tuple)
  1432  	default:
  1433  		// This is reachable, for example with *ssa.Const, *ssa.If, and
  1434  		// *ssa.Jump. They might be implemented in some way in the future.
  1435  		return token.NoPos
  1436  	}
  1437  }
  1438  
  1439  // createInstruction builds the LLVM IR equivalent instructions for the
  1440  // particular Go SSA instruction.
  1441  func (b *builder) createInstruction(instr ssa.Instruction) {
  1442  	if b.Debug {
  1443  		b.setDebugLocation(getPos(instr))
  1444  	}
  1445  
  1446  	switch instr := instr.(type) {
  1447  	case ssa.Value:
  1448  		if value, err := b.createExpr(instr); err != nil {
  1449  			// This expression could not be parsed. Add the error to the list
  1450  			// of diagnostics and continue with an undef value.
  1451  			// The resulting IR will be incorrect (but valid). However,
  1452  			// compilation can proceed which is useful because there may be
  1453  			// more compilation errors which can then all be shown together to
  1454  			// the user.
  1455  			b.diagnostics = append(b.diagnostics, err)
  1456  			b.locals[instr] = llvm.Undef(b.getLLVMType(instr.Type()))
  1457  		} else {
  1458  			b.locals[instr] = value
  1459  			if len(*instr.Referrers()) != 0 && b.NeedsStackObjects {
  1460  				b.trackExpr(instr, value)
  1461  			}
  1462  		}
  1463  	case *ssa.DebugRef:
  1464  		// ignore
  1465  	case *ssa.Defer:
  1466  		b.createDefer(instr)
  1467  	case *ssa.Go:
  1468  		// Start a new goroutine.
  1469  		b.createGo(instr)
  1470  	case *ssa.If:
  1471  		cond := b.getValue(instr.Cond, getPos(instr))
  1472  		block := instr.Block()
  1473  		blockThen := b.blockEntries[block.Succs[0]]
  1474  		blockElse := b.blockEntries[block.Succs[1]]
  1475  		b.CreateCondBr(cond, blockThen, blockElse)
  1476  	case *ssa.Jump:
  1477  		blockJump := b.blockEntries[instr.Block().Succs[0]]
  1478  		b.CreateBr(blockJump)
  1479  	case *ssa.MapUpdate:
  1480  		m := b.getValue(instr.Map, getPos(instr))
  1481  		key := b.getValue(instr.Key, getPos(instr))
  1482  		value := b.getValue(instr.Value, getPos(instr))
  1483  		mapType := instr.Map.Type().Underlying().(*types.Map)
  1484  		b.createMapUpdate(mapType.Key(), m, key, value, instr.Pos())
  1485  	case *ssa.Panic:
  1486  		value := b.getValue(instr.X, getPos(instr))
  1487  		b.createRuntimeInvoke("_panic", []llvm.Value{value}, "")
  1488  		b.CreateUnreachable()
  1489  	case *ssa.Return:
  1490  		if b.hasDeferFrame() {
  1491  			b.createRuntimeCall("destroyDeferFrame", []llvm.Value{b.deferFrame}, "")
  1492  		}
  1493  		if len(instr.Results) == 0 {
  1494  			b.CreateRetVoid()
  1495  		} else if len(instr.Results) == 1 {
  1496  			b.CreateRet(b.getValue(instr.Results[0], getPos(instr)))
  1497  		} else {
  1498  			// Multiple return values. Put them all in a struct.
  1499  			retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())
  1500  			for i, result := range instr.Results {
  1501  				val := b.getValue(result, getPos(instr))
  1502  				retVal = b.CreateInsertValue(retVal, val, i, "")
  1503  			}
  1504  			b.CreateRet(retVal)
  1505  		}
  1506  	case *ssa.RunDefers:
  1507  		// Note where we're going to put the rundefers block
  1508  		run := b.insertBasicBlock("rundefers.block")
  1509  		b.CreateBr(run)
  1510  		b.runDefersBlock = append(b.runDefersBlock, run)
  1511  
  1512  		after := b.insertBasicBlock("rundefers.after")
  1513  		b.SetInsertPointAtEnd(after)
  1514  		b.afterDefersBlock = append(b.afterDefersBlock, after)
  1515  	case *ssa.Send:
  1516  		b.createChanSend(instr)
  1517  	case *ssa.Store:
  1518  		llvmAddr := b.getValue(instr.Addr, getPos(instr))
  1519  		llvmVal := b.getValue(instr.Val, getPos(instr))
  1520  		b.createNilCheck(instr.Addr, llvmAddr, "store")
  1521  		if b.targetData.TypeAllocSize(llvmVal.Type()) == 0 {
  1522  			// nothing to store
  1523  			return
  1524  		}
  1525  		b.CreateStore(llvmVal, llvmAddr)
  1526  	default:
  1527  		b.addError(instr.Pos(), "unknown instruction: "+instr.String())
  1528  	}
  1529  }
  1530  
  1531  // createBuiltin lowers a builtin Go function (append, close, delete, etc.) to
  1532  // LLVM IR. It uses runtime calls for some builtins.
  1533  func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, callName string, pos token.Pos) (llvm.Value, error) {
  1534  	switch callName {
  1535  	case "append":
  1536  		src := argValues[0]
  1537  		elems := argValues[1]
  1538  		srcBuf := b.CreateExtractValue(src, 0, "append.srcBuf")
  1539  		srcLen := b.CreateExtractValue(src, 1, "append.srcLen")
  1540  		srcCap := b.CreateExtractValue(src, 2, "append.srcCap")
  1541  		elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf")
  1542  		elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
  1543  		elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
  1544  		elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
  1545  		result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize}, "append.new")
  1546  		newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
  1547  		newLen := b.CreateExtractValue(result, 1, "append.newLen")
  1548  		newCap := b.CreateExtractValue(result, 2, "append.newCap")
  1549  		newSlice := llvm.Undef(src.Type())
  1550  		newSlice = b.CreateInsertValue(newSlice, newPtr, 0, "")
  1551  		newSlice = b.CreateInsertValue(newSlice, newLen, 1, "")
  1552  		newSlice = b.CreateInsertValue(newSlice, newCap, 2, "")
  1553  		return newSlice, nil
  1554  	case "cap":
  1555  		value := argValues[0]
  1556  		var llvmCap llvm.Value
  1557  		switch argTypes[0].Underlying().(type) {
  1558  		case *types.Chan:
  1559  			llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
  1560  		case *types.Slice:
  1561  			llvmCap = b.CreateExtractValue(value, 2, "cap")
  1562  		default:
  1563  			return llvm.Value{}, b.makeError(pos, "todo: cap: unknown type")
  1564  		}
  1565  		if b.targetData.TypeAllocSize(llvmCap.Type()) < b.targetData.TypeAllocSize(b.intType) {
  1566  			llvmCap = b.CreateZExt(llvmCap, b.intType, "len.int")
  1567  		}
  1568  		return llvmCap, nil
  1569  	case "close":
  1570  		b.createChanClose(argValues[0])
  1571  		return llvm.Value{}, nil
  1572  	case "complex":
  1573  		r := argValues[0]
  1574  		i := argValues[1]
  1575  		t := argTypes[0].Underlying().(*types.Basic)
  1576  		var cplx llvm.Value
  1577  		switch t.Kind() {
  1578  		case types.Float32:
  1579  			cplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.FloatType(), b.ctx.FloatType()}, false))
  1580  		case types.Float64:
  1581  			cplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.DoubleType(), b.ctx.DoubleType()}, false))
  1582  		default:
  1583  			return llvm.Value{}, b.makeError(pos, "unsupported type in complex builtin: "+t.String())
  1584  		}
  1585  		cplx = b.CreateInsertValue(cplx, r, 0, "")
  1586  		cplx = b.CreateInsertValue(cplx, i, 1, "")
  1587  		return cplx, nil
  1588  	case "clear":
  1589  		value := argValues[0]
  1590  		switch typ := argTypes[0].Underlying().(type) {
  1591  		case *types.Slice:
  1592  			elementType := b.getLLVMType(typ.Elem())
  1593  			elementSize := b.targetData.TypeAllocSize(elementType)
  1594  			elementAlign := b.targetData.ABITypeAlignment(elementType)
  1595  
  1596  			// The pointer to the data to be cleared.
  1597  			llvmBuf := b.CreateExtractValue(value, 0, "buf")
  1598  
  1599  			// The length (in bytes) to be cleared.
  1600  			llvmLen := b.CreateExtractValue(value, 1, "len")
  1601  			llvmLen = b.CreateMul(llvmLen, llvm.ConstInt(llvmLen.Type(), elementSize, false), "")
  1602  
  1603  			// Do the clear operation using the LLVM memset builtin.
  1604  			// This is also correct for nil slices: in those cases, len will be
  1605  			// 0 which means the memset call is a no-op (according to the LLVM
  1606  			// LangRef).
  1607  			memset := b.getMemsetFunc()
  1608  			call := b.createCall(memset.GlobalValueType(), memset, []llvm.Value{
  1609  				llvmBuf, // dest
  1610  				llvm.ConstInt(b.ctx.Int8Type(), 0, false), // val
  1611  				llvmLen, // len
  1612  				llvm.ConstInt(b.ctx.Int1Type(), 0, false), // isVolatile
  1613  			}, "")
  1614  			call.AddCallSiteAttribute(1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(elementAlign)))
  1615  
  1616  			return llvm.Value{}, nil
  1617  		case *types.Map:
  1618  			m := argValues[0]
  1619  			b.createMapClear(m)
  1620  			return llvm.Value{}, nil
  1621  		default:
  1622  			return llvm.Value{}, b.makeError(pos, "unsupported type in clear builtin: "+typ.String())
  1623  		}
  1624  	case "copy":
  1625  		dst := argValues[0]
  1626  		src := argValues[1]
  1627  		dstLen := b.CreateExtractValue(dst, 1, "copy.dstLen")
  1628  		srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
  1629  		dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
  1630  		srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
  1631  		elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
  1632  		elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
  1633  		return b.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
  1634  	case "delete":
  1635  		m := argValues[0]
  1636  		key := argValues[1]
  1637  		return llvm.Value{}, b.createMapDelete(argTypes[1], m, key, pos)
  1638  	case "imag":
  1639  		cplx := argValues[0]
  1640  		return b.CreateExtractValue(cplx, 1, "imag"), nil
  1641  	case "len":
  1642  		value := argValues[0]
  1643  		var llvmLen llvm.Value
  1644  		switch argTypes[0].Underlying().(type) {
  1645  		case *types.Basic, *types.Slice:
  1646  			// string or slice
  1647  			llvmLen = b.CreateExtractValue(value, 1, "len")
  1648  		case *types.Chan:
  1649  			llvmLen = b.createRuntimeCall("chanLen", []llvm.Value{value}, "len")
  1650  		case *types.Map:
  1651  			llvmLen = b.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len")
  1652  		default:
  1653  			return llvm.Value{}, b.makeError(pos, "todo: len: unknown type")
  1654  		}
  1655  		if b.targetData.TypeAllocSize(llvmLen.Type()) < b.targetData.TypeAllocSize(b.intType) {
  1656  			llvmLen = b.CreateZExt(llvmLen, b.intType, "len.int")
  1657  		}
  1658  		return llvmLen, nil
  1659  	case "min", "max":
  1660  		// min and max builtins, added in Go 1.21.
  1661  		// We can simply reuse the existing binop comparison code, which has all
  1662  		// the edge cases figured out already.
  1663  		tok := token.LSS
  1664  		if callName == "max" {
  1665  			tok = token.GTR
  1666  		}
  1667  		result := argValues[0]
  1668  		typ := argTypes[0]
  1669  		for _, arg := range argValues[1:] {
  1670  			cmp, err := b.createBinOp(tok, typ, typ, result, arg, pos)
  1671  			if err != nil {
  1672  				return result, err
  1673  			}
  1674  			result = b.CreateSelect(cmp, result, arg, "")
  1675  		}
  1676  		return result, nil
  1677  	case "print", "println":
  1678  		for i, value := range argValues {
  1679  			if i >= 1 && callName == "println" {
  1680  				b.createRuntimeCall("printspace", nil, "")
  1681  			}
  1682  			typ := argTypes[i].Underlying()
  1683  			switch typ := typ.(type) {
  1684  			case *types.Basic:
  1685  				switch typ.Kind() {
  1686  				case types.String, types.UntypedString:
  1687  					b.createRuntimeCall("printstring", []llvm.Value{value}, "")
  1688  				case types.Uintptr:
  1689  					b.createRuntimeCall("printptr", []llvm.Value{value}, "")
  1690  				case types.UnsafePointer:
  1691  					ptrValue := b.CreatePtrToInt(value, b.uintptrType, "")
  1692  					b.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "")
  1693  				default:
  1694  					// runtime.print{int,uint}{8,16,32,64}
  1695  					if typ.Info()&types.IsInteger != 0 {
  1696  						name := "print"
  1697  						if typ.Info()&types.IsUnsigned != 0 {
  1698  							name += "uint"
  1699  						} else {
  1700  							name += "int"
  1701  						}
  1702  						name += strconv.FormatUint(b.targetData.TypeAllocSize(value.Type())*8, 10)
  1703  						b.createRuntimeCall(name, []llvm.Value{value}, "")
  1704  					} else if typ.Kind() == types.Bool {
  1705  						b.createRuntimeCall("printbool", []llvm.Value{value}, "")
  1706  					} else if typ.Kind() == types.Float32 {
  1707  						b.createRuntimeCall("printfloat32", []llvm.Value{value}, "")
  1708  					} else if typ.Kind() == types.Float64 {
  1709  						b.createRuntimeCall("printfloat64", []llvm.Value{value}, "")
  1710  					} else if typ.Kind() == types.Complex64 {
  1711  						b.createRuntimeCall("printcomplex64", []llvm.Value{value}, "")
  1712  					} else if typ.Kind() == types.Complex128 {
  1713  						b.createRuntimeCall("printcomplex128", []llvm.Value{value}, "")
  1714  					} else {
  1715  						return llvm.Value{}, b.makeError(pos, "unknown basic arg type: "+typ.String())
  1716  					}
  1717  				}
  1718  			case *types.Interface:
  1719  				b.createRuntimeCall("printitf", []llvm.Value{value}, "")
  1720  			case *types.Map:
  1721  				b.createRuntimeCall("printmap", []llvm.Value{value}, "")
  1722  			case *types.Pointer:
  1723  				ptrValue := b.CreatePtrToInt(value, b.uintptrType, "")
  1724  				b.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "")
  1725  			case *types.Slice:
  1726  				bufptr := b.CreateExtractValue(value, 0, "")
  1727  				buflen := b.CreateExtractValue(value, 1, "")
  1728  				bufcap := b.CreateExtractValue(value, 2, "")
  1729  				ptrValue := b.CreatePtrToInt(bufptr, b.uintptrType, "")
  1730  				b.createRuntimeCall("printslice", []llvm.Value{ptrValue, buflen, bufcap}, "")
  1731  			default:
  1732  				return llvm.Value{}, b.makeError(pos, "unknown arg type: "+typ.String())
  1733  			}
  1734  		}
  1735  		if callName == "println" {
  1736  			b.createRuntimeCall("printnl", nil, "")
  1737  		}
  1738  		return llvm.Value{}, nil // print() or println() returns void
  1739  	case "real":
  1740  		cplx := argValues[0]
  1741  		return b.CreateExtractValue(cplx, 0, "real"), nil
  1742  	case "recover":
  1743  		useParentFrame := uint64(0)
  1744  		if b.hasDeferFrame() {
  1745  			// recover() should return the panic value of the parent function,
  1746  			// not of the current function.
  1747  			useParentFrame = 1
  1748  		}
  1749  		return b.createRuntimeCall("_recover", []llvm.Value{llvm.ConstInt(b.ctx.Int1Type(), useParentFrame, false)}, ""), nil
  1750  	case "ssa:wrapnilchk":
  1751  		// TODO: do an actual nil check?
  1752  		return argValues[0], nil
  1753  
  1754  	// Builtins from the unsafe package.
  1755  	case "Add": // unsafe.Add
  1756  		// This is basically just a GEP operation.
  1757  		// Note: the pointer is always of type *i8.
  1758  		ptr := argValues[0]
  1759  		len := argValues[1]
  1760  		return b.CreateGEP(b.ctx.Int8Type(), ptr, []llvm.Value{len}, ""), nil
  1761  	case "Alignof": // unsafe.Alignof
  1762  		align := b.targetData.ABITypeAlignment(argValues[0].Type())
  1763  		return llvm.ConstInt(b.uintptrType, uint64(align), false), nil
  1764  	case "Offsetof": // unsafe.Offsetof
  1765  		// This builtin is a bit harder to implement and may need a bit of
  1766  		// refactoring to work (it may be easier to implement if we have access
  1767  		// to the underlying Go SSA instruction). It is also rarely used: it
  1768  		// only applies in generic code and unsafe.Offsetof isn't very commonly
  1769  		// used anyway.
  1770  		// In other words, postpone it to some other day.
  1771  		return llvm.Value{}, b.makeError(pos, "todo: unsafe.Offsetof")
  1772  	case "Sizeof": // unsafe.Sizeof
  1773  		size := b.targetData.TypeAllocSize(argValues[0].Type())
  1774  		return llvm.ConstInt(b.uintptrType, size, false), nil
  1775  	case "Slice", "String": // unsafe.Slice, unsafe.String
  1776  		// This creates a slice or string from a pointer and a length.
  1777  		// Note that the exception mentioned in the documentation (if the
  1778  		// pointer and length are nil, the slice is also nil) is trivially
  1779  		// already the case.
  1780  		ptr := argValues[0]
  1781  		len := argValues[1]
  1782  		var elementType llvm.Type
  1783  		if callName == "Slice" {
  1784  			elementType = b.getLLVMType(argTypes[0].Underlying().(*types.Pointer).Elem())
  1785  		} else {
  1786  			elementType = b.ctx.Int8Type()
  1787  		}
  1788  		b.createUnsafeSliceStringCheck("unsafe."+callName, ptr, len, elementType, argTypes[1].Underlying().(*types.Basic))
  1789  		if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
  1790  			// Too small, zero-extend len.
  1791  			len = b.CreateZExt(len, b.uintptrType, "")
  1792  		} else if len.Type().IntTypeWidth() > b.uintptrType.IntTypeWidth() {
  1793  			// Too big, truncate len.
  1794  			len = b.CreateTrunc(len, b.uintptrType, "")
  1795  		}
  1796  		if callName == "Slice" {
  1797  			slice := llvm.Undef(b.ctx.StructType([]llvm.Type{
  1798  				ptr.Type(),
  1799  				b.uintptrType,
  1800  				b.uintptrType,
  1801  			}, false))
  1802  			slice = b.CreateInsertValue(slice, ptr, 0, "")
  1803  			slice = b.CreateInsertValue(slice, len, 1, "")
  1804  			slice = b.CreateInsertValue(slice, len, 2, "")
  1805  			return slice, nil
  1806  		} else {
  1807  			str := llvm.Undef(b.getLLVMRuntimeType("_string"))
  1808  			str = b.CreateInsertValue(str, argValues[0], 0, "")
  1809  			str = b.CreateInsertValue(str, len, 1, "")
  1810  			return str, nil
  1811  		}
  1812  	case "SliceData", "StringData": // unsafe.SliceData, unsafe.StringData
  1813  		return b.CreateExtractValue(argValues[0], 0, "slice.data"), nil
  1814  	default:
  1815  		return llvm.Value{}, b.makeError(pos, "todo: builtin: "+callName)
  1816  	}
  1817  }
  1818  
  1819  // createFunctionCall lowers a Go SSA call instruction (to a simple function,
  1820  // closure, function pointer, builtin, method, etc.) to LLVM IR, usually a call
  1821  // instruction.
  1822  //
  1823  // This is also where compiler intrinsics are implemented.
  1824  func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) {
  1825  	var params []llvm.Value
  1826  	for _, param := range instr.Args {
  1827  		params = append(params, b.getValue(param, getPos(instr)))
  1828  	}
  1829  
  1830  	// Try to call the function directly for trivially static calls.
  1831  	var callee, context llvm.Value
  1832  	var calleeType llvm.Type
  1833  	exported := false
  1834  	if fn := instr.StaticCallee(); fn != nil {
  1835  		// Direct function call, either to a named or anonymous (directly
  1836  		// applied) function call. If it is anonymous, it may be a closure.
  1837  		name := fn.RelString(nil)
  1838  		switch {
  1839  		case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
  1840  			return b.createInlineAsm(instr.Args)
  1841  		case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
  1842  			return b.createInlineAsmFull(instr)
  1843  		case strings.HasPrefix(name, "device/arm.SVCall"):
  1844  			return b.emitSVCall(instr.Args, getPos(instr))
  1845  		case strings.HasPrefix(name, "device/arm64.SVCall"):
  1846  			return b.emitSV64Call(instr.Args, getPos(instr))
  1847  		case strings.HasPrefix(name, "(device/riscv.CSR)."):
  1848  			return b.emitCSROperation(instr)
  1849  		case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"):
  1850  			return b.createSyscall(instr)
  1851  		case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
  1852  			return b.createRawSyscallNoError(instr)
  1853  		case name == "runtime.supportsRecover":
  1854  			supportsRecover := uint64(0)
  1855  			if b.supportsRecover() {
  1856  				supportsRecover = 1
  1857  			}
  1858  			return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
  1859  		case name == "runtime.panicStrategy":
  1860  			// These constants are defined in src/runtime/panic.go.
  1861  			panicStrategy := map[string]uint64{
  1862  				"print": 1, // panicStrategyPrint
  1863  				"trap":  2, // panicStrategyTrap
  1864  			}[b.Config.PanicStrategy]
  1865  			return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
  1866  		case name == "runtime/interrupt.New":
  1867  			return b.createInterruptGlobal(instr)
  1868  		}
  1869  
  1870  		calleeType, callee = b.getFunction(fn)
  1871  		info := b.getFunctionInfo(fn)
  1872  		if callee.IsNil() {
  1873  			return llvm.Value{}, b.makeError(instr.Pos(), "undefined function: "+info.linkName)
  1874  		}
  1875  		switch value := instr.Value.(type) {
  1876  		case *ssa.Function:
  1877  			// Regular function call. No context is necessary.
  1878  			context = llvm.Undef(b.dataPtrType)
  1879  			if info.variadic && len(fn.Params) == 0 {
  1880  				// This matches Clang, see: https://godbolt.org/z/Gqv49xKMq
  1881  				// Eventually we might be able to eliminate this special case
  1882  				// entirely. For details, see:
  1883  				// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
  1884  				calleeType = llvm.FunctionType(callee.GlobalValueType().ReturnType(), nil, false)
  1885  			}
  1886  		case *ssa.MakeClosure:
  1887  			// A call on a func value, but the callee is trivial to find. For
  1888  			// example: immediately applied functions.
  1889  			funcValue := b.getValue(value, getPos(value))
  1890  			context = b.extractFuncContext(funcValue)
  1891  		default:
  1892  			panic("StaticCallee returned an unexpected value")
  1893  		}
  1894  		exported = info.exported
  1895  	} else if call, ok := instr.Value.(*ssa.Builtin); ok {
  1896  		// Builtin function (append, close, delete, etc.).)
  1897  		var argTypes []types.Type
  1898  		for _, arg := range instr.Args {
  1899  			argTypes = append(argTypes, arg.Type())
  1900  		}
  1901  		return b.createBuiltin(argTypes, params, call.Name(), instr.Pos())
  1902  	} else if instr.IsInvoke() {
  1903  		// Interface method call (aka invoke call).
  1904  		itf := b.getValue(instr.Value, getPos(instr)) // interface value (runtime._interface)
  1905  		typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode")
  1906  		value := b.CreateExtractValue(itf, 1, "invoke.func.value") // receiver
  1907  		// Prefix the params with receiver value and suffix with typecode.
  1908  		params = append([]llvm.Value{value}, params...)
  1909  		params = append(params, typecode)
  1910  		callee = b.getInvokeFunction(instr)
  1911  		calleeType = callee.GlobalValueType()
  1912  		context = llvm.Undef(b.dataPtrType)
  1913  	} else {
  1914  		// Function pointer.
  1915  		value := b.getValue(instr.Value, getPos(instr))
  1916  		// This is a func value, which cannot be called directly. We have to
  1917  		// extract the function pointer and context first from the func value.
  1918  		callee, context = b.decodeFuncValue(value)
  1919  		calleeType = b.getLLVMFunctionType(instr.Value.Type().Underlying().(*types.Signature))
  1920  		b.createNilCheck(instr.Value, callee, "fpcall")
  1921  	}
  1922  
  1923  	if !exported {
  1924  		// This function takes a context parameter.
  1925  		// Add it to the end of the parameter list.
  1926  		params = append(params, context)
  1927  	}
  1928  
  1929  	return b.createInvoke(calleeType, callee, params, ""), nil
  1930  }
  1931  
  1932  // getValue returns the LLVM value of a constant, function value, global, or
  1933  // already processed SSA expression.
  1934  func (b *builder) getValue(expr ssa.Value, pos token.Pos) llvm.Value {
  1935  	switch expr := expr.(type) {
  1936  	case *ssa.Const:
  1937  		if pos == token.NoPos {
  1938  			// If the position isn't known, at least try to find in which file
  1939  			// it is defined.
  1940  			file := b.program.Fset.File(b.fn.Pos())
  1941  			if file != nil {
  1942  				pos = file.Pos(0)
  1943  			}
  1944  		}
  1945  		return b.createConst(expr, pos)
  1946  	case *ssa.Function:
  1947  		if b.getFunctionInfo(expr).exported {
  1948  			b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
  1949  			return llvm.Undef(b.getLLVMType(expr.Type()))
  1950  		}
  1951  		_, fn := b.getFunction(expr)
  1952  		return b.createFuncValue(fn, llvm.Undef(b.dataPtrType), expr.Signature)
  1953  	case *ssa.Global:
  1954  		value := b.getGlobal(expr)
  1955  		if value.IsNil() {
  1956  			b.addError(expr.Pos(), "global not found: "+expr.RelString(nil))
  1957  			return llvm.Undef(b.getLLVMType(expr.Type()))
  1958  		}
  1959  		return value
  1960  	default:
  1961  		// other (local) SSA value
  1962  		if value, ok := b.locals[expr]; ok {
  1963  			return value
  1964  		} else {
  1965  			// indicates a compiler bug
  1966  			panic("local has not been parsed: " + expr.String())
  1967  		}
  1968  	}
  1969  }
  1970  
  1971  // maxSliceSize determines the maximum size a slice of the given element type
  1972  // can be.
  1973  func (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {
  1974  	// Calculate ^uintptr(0), which is the max value that fits in uintptr.
  1975  	maxPointerValue := llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)).ZExtValue()
  1976  	// Calculate (^uint(0))/2, which is the max value that fits in an int.
  1977  	maxIntegerValue := llvm.ConstNot(llvm.ConstInt(c.intType, 0, false)).ZExtValue() / 2
  1978  
  1979  	// Determine the maximum allowed size for a slice. The biggest possible
  1980  	// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so
  1981  	// divide by the element type to get the real maximum size.
  1982  	elementSize := c.targetData.TypeAllocSize(elementType)
  1983  	if elementSize == 0 {
  1984  		elementSize = 1
  1985  	}
  1986  	maxSize := maxPointerValue / elementSize
  1987  
  1988  	// len(slice) is an int. Make sure the length remains small enough to fit in
  1989  	// an int.
  1990  	if maxSize > maxIntegerValue {
  1991  		maxSize = maxIntegerValue
  1992  	}
  1993  
  1994  	return maxSize
  1995  }
  1996  
  1997  // createExpr translates a Go SSA expression to LLVM IR. This can be zero, one,
  1998  // or multiple LLVM IR instructions and/or runtime calls.
  1999  func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
  2000  	if _, ok := b.locals[expr]; ok {
  2001  		// sanity check
  2002  		panic("instruction has already been created: " + expr.String())
  2003  	}
  2004  
  2005  	switch expr := expr.(type) {
  2006  	case *ssa.Alloc:
  2007  		typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
  2008  		size := b.targetData.TypeAllocSize(typ)
  2009  		// Move all "large" allocations to the heap.
  2010  		if expr.Heap || size > b.MaxStackAlloc {
  2011  			// Calculate ^uintptr(0)
  2012  			maxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()
  2013  			if size > maxSize {
  2014  				// Size would be truncated if truncated to uintptr.
  2015  				return llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size))
  2016  			}
  2017  			sizeValue := llvm.ConstInt(b.uintptrType, size, false)
  2018  			layoutValue := b.createObjectLayout(typ, expr.Pos())
  2019  			buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, layoutValue}, expr.Comment)
  2020  			return buf, nil
  2021  		} else {
  2022  			buf := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, expr.Comment)
  2023  			if b.targetData.TypeAllocSize(typ) != 0 {
  2024  				b.CreateStore(llvm.ConstNull(typ), buf) // zero-initialize var
  2025  			}
  2026  			return buf, nil
  2027  		}
  2028  	case *ssa.BinOp:
  2029  		x := b.getValue(expr.X, getPos(expr))
  2030  		y := b.getValue(expr.Y, getPos(expr))
  2031  		return b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos())
  2032  	case *ssa.Call:
  2033  		return b.createFunctionCall(expr.Common())
  2034  	case *ssa.ChangeInterface:
  2035  		// Do not change between interface types: always use the underlying
  2036  		// (concrete) type in the type number of the interface. Every method
  2037  		// call on an interface will do a lookup which method to call.
  2038  		// This is different from how the official Go compiler works, because of
  2039  		// heap allocation and because it's easier to implement, see:
  2040  		// https://research.swtch.com/interfaces
  2041  		return b.getValue(expr.X, getPos(expr)), nil
  2042  	case *ssa.ChangeType:
  2043  		// This instruction changes the type, but the underlying value remains
  2044  		// the same. This is often a no-op, but sometimes we have to change the
  2045  		// LLVM type as well.
  2046  		x := b.getValue(expr.X, getPos(expr))
  2047  		llvmType := b.getLLVMType(expr.Type())
  2048  		if x.Type() == llvmType {
  2049  			// Different Go type but same LLVM type (for example, named int).
  2050  			// This is the common case.
  2051  			return x, nil
  2052  		}
  2053  		// Figure out what kind of type we need to cast.
  2054  		switch llvmType.TypeKind() {
  2055  		case llvm.StructTypeKind:
  2056  			// Unfortunately, we can't just bitcast structs. We have to
  2057  			// actually create a new struct of the correct type and insert the
  2058  			// values from the previous struct in there.
  2059  			value := llvm.Undef(llvmType)
  2060  			for i := 0; i < llvmType.StructElementTypesCount(); i++ {
  2061  				field := b.CreateExtractValue(x, i, "changetype.field")
  2062  				value = b.CreateInsertValue(value, field, i, "changetype.struct")
  2063  			}
  2064  			return value, nil
  2065  		default:
  2066  			return llvm.Value{}, errors.New("todo: unknown ChangeType type: " + expr.X.Type().String())
  2067  		}
  2068  	case *ssa.Const:
  2069  		panic("const is not an expression")
  2070  	case *ssa.Convert:
  2071  		x := b.getValue(expr.X, getPos(expr))
  2072  		return b.createConvert(expr.X.Type(), expr.Type(), x, expr.Pos())
  2073  	case *ssa.Extract:
  2074  		if _, ok := expr.Tuple.(*ssa.Select); ok {
  2075  			return b.getChanSelectResult(expr), nil
  2076  		}
  2077  		value := b.getValue(expr.Tuple, getPos(expr))
  2078  		return b.CreateExtractValue(value, expr.Index, ""), nil
  2079  	case *ssa.Field:
  2080  		value := b.getValue(expr.X, getPos(expr))
  2081  		result := b.CreateExtractValue(value, expr.Field, "")
  2082  		return result, nil
  2083  	case *ssa.FieldAddr:
  2084  		val := b.getValue(expr.X, getPos(expr))
  2085  		// Check for nil pointer before calculating the address, from the spec:
  2086  		// > For an operand x of type T, the address operation &x generates a
  2087  		// > pointer of type *T to x. [...] If the evaluation of x would cause a
  2088  		// > run-time panic, then the evaluation of &x does too.
  2089  		b.createNilCheck(expr.X, val, "gep")
  2090  		// Do a GEP on the pointer to get the field address.
  2091  		indices := []llvm.Value{
  2092  			llvm.ConstInt(b.ctx.Int32Type(), 0, false),
  2093  			llvm.ConstInt(b.ctx.Int32Type(), uint64(expr.Field), false),
  2094  		}
  2095  		elementType := b.getLLVMType(expr.X.Type().Underlying().(*types.Pointer).Elem())
  2096  		return b.CreateInBoundsGEP(elementType, val, indices, ""), nil
  2097  	case *ssa.Function:
  2098  		panic("function is not an expression")
  2099  	case *ssa.Global:
  2100  		panic("global is not an expression")
  2101  	case *ssa.Index:
  2102  		collection := b.getValue(expr.X, getPos(expr))
  2103  		index := b.getValue(expr.Index, getPos(expr))
  2104  
  2105  		switch xType := expr.X.Type().Underlying().(type) {
  2106  		case *types.Basic: // extract byte from string
  2107  			// Value type must be a string, which is a basic type.
  2108  			if xType.Info()&types.IsString == 0 {
  2109  				panic("lookup on non-string?")
  2110  			}
  2111  
  2112  			// Sometimes, the index can be e.g. an uint8 or int8, and we have to
  2113  			// correctly extend that type for two reasons:
  2114  			//  1. The lookup bounds check expects an index of at least uintptr
  2115  			//     size.
  2116  			//  2. getelementptr has signed operands, and therefore s[uint8(x)]
  2117  			//     can be lowered as s[int8(x)]. That would be a bug.
  2118  			index = b.extendInteger(index, expr.Index.Type(), b.uintptrType)
  2119  
  2120  			// Bounds check.
  2121  			length := b.CreateExtractValue(collection, 1, "len")
  2122  			b.createLookupBoundsCheck(length, index)
  2123  
  2124  			// Lookup byte
  2125  			buf := b.CreateExtractValue(collection, 0, "")
  2126  			bufElemType := b.ctx.Int8Type()
  2127  			bufPtr := b.CreateInBoundsGEP(bufElemType, buf, []llvm.Value{index}, "")
  2128  			return b.CreateLoad(bufElemType, bufPtr, ""), nil
  2129  		case *types.Array: // extract element from array
  2130  			// Extend index to at least uintptr size, because getelementptr
  2131  			// assumes index is a signed integer.
  2132  			index = b.extendInteger(index, expr.Index.Type(), b.uintptrType)
  2133  
  2134  			// Check bounds.
  2135  			arrayLen := llvm.ConstInt(b.uintptrType, uint64(xType.Len()), false)
  2136  			b.createLookupBoundsCheck(arrayLen, index)
  2137  
  2138  			// Can't load directly from array (as index is non-constant), so
  2139  			// have to do it using an alloca+gep+load.
  2140  			arrayType := collection.Type()
  2141  			alloca, allocaSize := b.createTemporaryAlloca(arrayType, "index.alloca")
  2142  			b.CreateStore(collection, alloca)
  2143  			zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
  2144  			ptr := b.CreateInBoundsGEP(arrayType, alloca, []llvm.Value{zero, index}, "index.gep")
  2145  			result := b.CreateLoad(arrayType.ElementType(), ptr, "index.load")
  2146  			b.emitLifetimeEnd(alloca, allocaSize)
  2147  			return result, nil
  2148  		default:
  2149  			panic("unknown *ssa.Index type")
  2150  		}
  2151  	case *ssa.IndexAddr:
  2152  		val := b.getValue(expr.X, getPos(expr))
  2153  		index := b.getValue(expr.Index, getPos(expr))
  2154  
  2155  		// Get buffer pointer and length
  2156  		var bufptr, buflen llvm.Value
  2157  		var bufType llvm.Type
  2158  		switch ptrTyp := expr.X.Type().Underlying().(type) {
  2159  		case *types.Pointer:
  2160  			typ := ptrTyp.Elem().Underlying()
  2161  			switch typ := typ.(type) {
  2162  			case *types.Array:
  2163  				bufptr = val
  2164  				buflen = llvm.ConstInt(b.uintptrType, uint64(typ.Len()), false)
  2165  				bufType = b.getLLVMType(typ)
  2166  				// Check for nil pointer before calculating the address, from
  2167  				// the spec:
  2168  				// > For an operand x of type T, the address operation &x
  2169  				// > generates a pointer of type *T to x. [...] If the
  2170  				// > evaluation of x would cause a run-time panic, then the
  2171  				// > evaluation of &x does too.
  2172  				b.createNilCheck(expr.X, bufptr, "gep")
  2173  			default:
  2174  				return llvm.Value{}, b.makeError(expr.Pos(), "todo: indexaddr: "+typ.String())
  2175  			}
  2176  		case *types.Slice:
  2177  			bufptr = b.CreateExtractValue(val, 0, "indexaddr.ptr")
  2178  			buflen = b.CreateExtractValue(val, 1, "indexaddr.len")
  2179  			bufType = b.getLLVMType(ptrTyp.Elem())
  2180  		default:
  2181  			return llvm.Value{}, b.makeError(expr.Pos(), "todo: indexaddr: "+ptrTyp.String())
  2182  		}
  2183  
  2184  		// Make sure index is at least the size of uintptr becuase getelementptr
  2185  		// assumes index is a signed integer.
  2186  		index = b.extendInteger(index, expr.Index.Type(), b.uintptrType)
  2187  
  2188  		// Bounds check.
  2189  		b.createLookupBoundsCheck(buflen, index)
  2190  
  2191  		switch expr.X.Type().Underlying().(type) {
  2192  		case *types.Pointer:
  2193  			indices := []llvm.Value{
  2194  				llvm.ConstInt(b.ctx.Int32Type(), 0, false),
  2195  				index,
  2196  			}
  2197  			return b.CreateInBoundsGEP(bufType, bufptr, indices, ""), nil
  2198  		case *types.Slice:
  2199  			return b.CreateInBoundsGEP(bufType, bufptr, []llvm.Value{index}, ""), nil
  2200  		default:
  2201  			panic("unreachable")
  2202  		}
  2203  	case *ssa.Lookup: // map lookup
  2204  		value := b.getValue(expr.X, getPos(expr))
  2205  		index := b.getValue(expr.Index, getPos(expr))
  2206  		valueType := expr.Type()
  2207  		if expr.CommaOk {
  2208  			valueType = valueType.(*types.Tuple).At(0).Type()
  2209  		}
  2210  		return b.createMapLookup(expr.X.Type().Underlying().(*types.Map).Key(), valueType, value, index, expr.CommaOk, expr.Pos())
  2211  	case *ssa.MakeChan:
  2212  		return b.createMakeChan(expr), nil
  2213  	case *ssa.MakeClosure:
  2214  		return b.parseMakeClosure(expr)
  2215  	case *ssa.MakeInterface:
  2216  		val := b.getValue(expr.X, getPos(expr))
  2217  		return b.createMakeInterface(val, expr.X.Type(), expr.Pos()), nil
  2218  	case *ssa.MakeMap:
  2219  		return b.createMakeMap(expr)
  2220  	case *ssa.MakeSlice:
  2221  		sliceLen := b.getValue(expr.Len, getPos(expr))
  2222  		sliceCap := b.getValue(expr.Cap, getPos(expr))
  2223  		sliceType := expr.Type().Underlying().(*types.Slice)
  2224  		llvmElemType := b.getLLVMType(sliceType.Elem())
  2225  		elemSize := b.targetData.TypeAllocSize(llvmElemType)
  2226  		elemSizeValue := llvm.ConstInt(b.uintptrType, elemSize, false)
  2227  
  2228  		maxSize := b.maxSliceSize(llvmElemType)
  2229  		if elemSize > maxSize {
  2230  			// This seems to be checked by the typechecker already, but let's
  2231  			// check it again just to be sure.
  2232  			return llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf("slice element type is too big (%v bytes)", elemSize))
  2233  		}
  2234  
  2235  		// Bounds checking.
  2236  		lenType := expr.Len.Type().Underlying().(*types.Basic)
  2237  		capType := expr.Cap.Type().Underlying().(*types.Basic)
  2238  		maxSizeValue := llvm.ConstInt(b.uintptrType, maxSize, false)
  2239  		b.createSliceBoundsCheck(maxSizeValue, sliceLen, sliceCap, sliceCap, lenType, capType, capType)
  2240  
  2241  		// Allocate the backing array.
  2242  		sliceCapCast, err := b.createConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())
  2243  		if err != nil {
  2244  			return llvm.Value{}, err
  2245  		}
  2246  		sliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap")
  2247  		layoutValue := b.createObjectLayout(llvmElemType, expr.Pos())
  2248  		slicePtr := b.createRuntimeCall("alloc", []llvm.Value{sliceSize, layoutValue}, "makeslice.buf")
  2249  
  2250  		// Extend or truncate if necessary. This is safe as we've already done
  2251  		// the bounds check.
  2252  		sliceLen, err = b.createConvert(expr.Len.Type(), types.Typ[types.Uintptr], sliceLen, expr.Pos())
  2253  		if err != nil {
  2254  			return llvm.Value{}, err
  2255  		}
  2256  		sliceCap, err = b.createConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())
  2257  		if err != nil {
  2258  			return llvm.Value{}, err
  2259  		}
  2260  
  2261  		// Create the slice.
  2262  		slice := b.ctx.ConstStruct([]llvm.Value{
  2263  			llvm.Undef(slicePtr.Type()),
  2264  			llvm.Undef(b.uintptrType),
  2265  			llvm.Undef(b.uintptrType),
  2266  		}, false)
  2267  		slice = b.CreateInsertValue(slice, slicePtr, 0, "")
  2268  		slice = b.CreateInsertValue(slice, sliceLen, 1, "")
  2269  		slice = b.CreateInsertValue(slice, sliceCap, 2, "")
  2270  		return slice, nil
  2271  	case *ssa.Next:
  2272  		rangeVal := expr.Iter.(*ssa.Range).X
  2273  		llvmRangeVal := b.getValue(rangeVal, getPos(expr))
  2274  		it := b.getValue(expr.Iter, getPos(expr))
  2275  		if expr.IsString {
  2276  			return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
  2277  		} else { // map
  2278  			return b.createMapIteratorNext(rangeVal, llvmRangeVal, it), nil
  2279  		}
  2280  	case *ssa.Phi:
  2281  		phi := b.CreatePHI(b.getLLVMType(expr.Type()), "")
  2282  		b.phis = append(b.phis, phiNode{expr, phi})
  2283  		return phi, nil
  2284  	case *ssa.Range:
  2285  		var iteratorType llvm.Type
  2286  		switch typ := expr.X.Type().Underlying().(type) {
  2287  		case *types.Basic: // string
  2288  			iteratorType = b.getLLVMRuntimeType("stringIterator")
  2289  		case *types.Map:
  2290  			iteratorType = b.getLLVMRuntimeType("hashmapIterator")
  2291  		default:
  2292  			panic("unknown type in range: " + typ.String())
  2293  		}
  2294  		it, _ := b.createTemporaryAlloca(iteratorType, "range.it")
  2295  		b.CreateStore(llvm.ConstNull(iteratorType), it)
  2296  		return it, nil
  2297  	case *ssa.Select:
  2298  		return b.createSelect(expr), nil
  2299  	case *ssa.Slice:
  2300  		value := b.getValue(expr.X, getPos(expr))
  2301  
  2302  		var lowType, highType, maxType *types.Basic
  2303  		var low, high, max llvm.Value
  2304  
  2305  		if expr.Low != nil {
  2306  			lowType = expr.Low.Type().Underlying().(*types.Basic)
  2307  			low = b.getValue(expr.Low, getPos(expr))
  2308  			low = b.extendInteger(low, lowType, b.uintptrType)
  2309  		} else {
  2310  			lowType = types.Typ[types.Uintptr]
  2311  			low = llvm.ConstInt(b.uintptrType, 0, false)
  2312  		}
  2313  
  2314  		if expr.High != nil {
  2315  			highType = expr.High.Type().Underlying().(*types.Basic)
  2316  			high = b.getValue(expr.High, getPos(expr))
  2317  			high = b.extendInteger(high, highType, b.uintptrType)
  2318  		} else {
  2319  			highType = types.Typ[types.Uintptr]
  2320  		}
  2321  
  2322  		if expr.Max != nil {
  2323  			maxType = expr.Max.Type().Underlying().(*types.Basic)
  2324  			max = b.getValue(expr.Max, getPos(expr))
  2325  			max = b.extendInteger(max, maxType, b.uintptrType)
  2326  		} else {
  2327  			maxType = types.Typ[types.Uintptr]
  2328  		}
  2329  
  2330  		switch typ := expr.X.Type().Underlying().(type) {
  2331  		case *types.Pointer: // pointer to array
  2332  			// slice an array
  2333  			arrayType := typ.Elem().Underlying().(*types.Array)
  2334  			length := arrayType.Len()
  2335  			llvmLen := llvm.ConstInt(b.uintptrType, uint64(length), false)
  2336  			if high.IsNil() {
  2337  				high = llvmLen
  2338  			}
  2339  			if max.IsNil() {
  2340  				max = llvmLen
  2341  			}
  2342  			indices := []llvm.Value{
  2343  				llvm.ConstInt(b.ctx.Int32Type(), 0, false),
  2344  				low,
  2345  			}
  2346  
  2347  			b.createNilCheck(expr.X, value, "slice")
  2348  			b.createSliceBoundsCheck(llvmLen, low, high, max, lowType, highType, maxType)
  2349  
  2350  			// Truncate ints bigger than uintptr. This is after the bounds
  2351  			// check so it's safe.
  2352  			if b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2353  				low = b.CreateTrunc(low, b.uintptrType, "")
  2354  			}
  2355  			if b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2356  				high = b.CreateTrunc(high, b.uintptrType, "")
  2357  			}
  2358  			if b.targetData.TypeAllocSize(max.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2359  				max = b.CreateTrunc(max, b.uintptrType, "")
  2360  			}
  2361  
  2362  			sliceLen := b.CreateSub(high, low, "slice.len")
  2363  			slicePtr := b.CreateInBoundsGEP(b.getLLVMType(arrayType), value, indices, "slice.ptr")
  2364  			sliceCap := b.CreateSub(max, low, "slice.cap")
  2365  
  2366  			slice := b.ctx.ConstStruct([]llvm.Value{
  2367  				llvm.Undef(slicePtr.Type()),
  2368  				llvm.Undef(b.uintptrType),
  2369  				llvm.Undef(b.uintptrType),
  2370  			}, false)
  2371  			slice = b.CreateInsertValue(slice, slicePtr, 0, "")
  2372  			slice = b.CreateInsertValue(slice, sliceLen, 1, "")
  2373  			slice = b.CreateInsertValue(slice, sliceCap, 2, "")
  2374  			return slice, nil
  2375  
  2376  		case *types.Slice:
  2377  			// slice a slice
  2378  			oldPtr := b.CreateExtractValue(value, 0, "")
  2379  			oldLen := b.CreateExtractValue(value, 1, "")
  2380  			oldCap := b.CreateExtractValue(value, 2, "")
  2381  			if high.IsNil() {
  2382  				high = oldLen
  2383  			}
  2384  			if max.IsNil() {
  2385  				max = oldCap
  2386  			}
  2387  
  2388  			b.createSliceBoundsCheck(oldCap, low, high, max, lowType, highType, maxType)
  2389  
  2390  			// Truncate ints bigger than uintptr. This is after the bounds
  2391  			// check so it's safe.
  2392  			if b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2393  				low = b.CreateTrunc(low, b.uintptrType, "")
  2394  			}
  2395  			if b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2396  				high = b.CreateTrunc(high, b.uintptrType, "")
  2397  			}
  2398  			if b.targetData.TypeAllocSize(max.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2399  				max = b.CreateTrunc(max, b.uintptrType, "")
  2400  			}
  2401  
  2402  			ptrElemType := b.getLLVMType(typ.Elem())
  2403  			newPtr := b.CreateInBoundsGEP(ptrElemType, oldPtr, []llvm.Value{low}, "")
  2404  			newLen := b.CreateSub(high, low, "")
  2405  			newCap := b.CreateSub(max, low, "")
  2406  			slice := b.ctx.ConstStruct([]llvm.Value{
  2407  				llvm.Undef(newPtr.Type()),
  2408  				llvm.Undef(b.uintptrType),
  2409  				llvm.Undef(b.uintptrType),
  2410  			}, false)
  2411  			slice = b.CreateInsertValue(slice, newPtr, 0, "")
  2412  			slice = b.CreateInsertValue(slice, newLen, 1, "")
  2413  			slice = b.CreateInsertValue(slice, newCap, 2, "")
  2414  			return slice, nil
  2415  
  2416  		case *types.Basic:
  2417  			if typ.Info()&types.IsString == 0 {
  2418  				return llvm.Value{}, b.makeError(expr.Pos(), "unknown slice type: "+typ.String())
  2419  			}
  2420  			// slice a string
  2421  			if expr.Max != nil {
  2422  				// This might as well be a panic, as the frontend should have
  2423  				// handled this already.
  2424  				return llvm.Value{}, b.makeError(expr.Pos(), "slicing a string with a max parameter is not allowed by the spec")
  2425  			}
  2426  			oldPtr := b.CreateExtractValue(value, 0, "")
  2427  			oldLen := b.CreateExtractValue(value, 1, "")
  2428  			if high.IsNil() {
  2429  				high = oldLen
  2430  			}
  2431  
  2432  			b.createSliceBoundsCheck(oldLen, low, high, high, lowType, highType, maxType)
  2433  
  2434  			// Truncate ints bigger than uintptr. This is after the bounds
  2435  			// check so it's safe.
  2436  			if b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2437  				low = b.CreateTrunc(low, b.uintptrType, "")
  2438  			}
  2439  			if b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {
  2440  				high = b.CreateTrunc(high, b.uintptrType, "")
  2441  			}
  2442  
  2443  			newPtr := b.CreateInBoundsGEP(b.ctx.Int8Type(), oldPtr, []llvm.Value{low}, "")
  2444  			newLen := b.CreateSub(high, low, "")
  2445  			str := llvm.Undef(b.getLLVMRuntimeType("_string"))
  2446  			str = b.CreateInsertValue(str, newPtr, 0, "")
  2447  			str = b.CreateInsertValue(str, newLen, 1, "")
  2448  			return str, nil
  2449  
  2450  		default:
  2451  			return llvm.Value{}, b.makeError(expr.Pos(), "unknown slice type: "+typ.String())
  2452  		}
  2453  	case *ssa.SliceToArrayPointer:
  2454  		// Conversion from a slice to an array pointer, as the name clearly
  2455  		// says. This requires a runtime check to make sure the slice is at
  2456  		// least as big as the array.
  2457  		slice := b.getValue(expr.X, getPos(expr))
  2458  		sliceLen := b.CreateExtractValue(slice, 1, "")
  2459  		arrayLen := expr.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Array).Len()
  2460  		b.createSliceToArrayPointerCheck(sliceLen, arrayLen)
  2461  		ptr := b.CreateExtractValue(slice, 0, "")
  2462  		return ptr, nil
  2463  	case *ssa.TypeAssert:
  2464  		return b.createTypeAssert(expr), nil
  2465  	case *ssa.UnOp:
  2466  		return b.createUnOp(expr)
  2467  	default:
  2468  		return llvm.Value{}, b.makeError(expr.Pos(), "todo: unknown expression: "+expr.String())
  2469  	}
  2470  }
  2471  
  2472  // createBinOp creates a LLVM binary operation (add, sub, mul, etc) for a Go
  2473  // binary operation. This is almost a direct mapping, but there are some subtle
  2474  // differences such as the requirement in LLVM IR that both sides must have the
  2475  // same type, even for bitshifts. Also, signedness in Go is encoded in the type
  2476  // and is encoded in the operation in LLVM IR: this is important for some
  2477  // operations such as divide.
  2478  func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Value, pos token.Pos) (llvm.Value, error) {
  2479  	switch typ := typ.Underlying().(type) {
  2480  	case *types.Basic:
  2481  		if typ.Info()&types.IsInteger != 0 {
  2482  			// Operations on integers
  2483  			signed := typ.Info()&types.IsUnsigned == 0
  2484  			switch op {
  2485  			case token.ADD: // +
  2486  				return b.CreateAdd(x, y, ""), nil
  2487  			case token.SUB: // -
  2488  				return b.CreateSub(x, y, ""), nil
  2489  			case token.MUL: // *
  2490  				return b.CreateMul(x, y, ""), nil
  2491  			case token.QUO, token.REM: // /, %
  2492  				// Check for a divide by zero. If y is zero, the Go
  2493  				// specification says that a runtime error must be triggered.
  2494  				b.createDivideByZeroCheck(y)
  2495  
  2496  				if signed {
  2497  					// Deal with signed division overflow.
  2498  					// The LLVM LangRef says:
  2499  					//
  2500  					//   Overflow also leads to undefined behavior; this is a
  2501  					//   rare case, but can occur, for example, by doing a
  2502  					//   32-bit division of -2147483648 by -1.
  2503  					//
  2504  					// The Go specification however says this about division:
  2505  					//
  2506  					//   The one exception to this rule is that if the dividend
  2507  					//   x is the most negative value for the int type of x, the
  2508  					//   quotient q = x / -1 is equal to x (and r = 0) due to
  2509  					//   two's-complement integer overflow.
  2510  					//
  2511  					// In other words, in the special case that the lowest
  2512  					// possible signed integer is divided by -1, the result of
  2513  					// the division is the same as x (the dividend).
  2514  					// This is implemented by checking for this condition and
  2515  					// changing y to 1 if it occurs, for example for 32-bit
  2516  					// ints:
  2517  					//
  2518  					//   if x == -2147483648 && y == -1 {
  2519  					//       y = 1
  2520  					//   }
  2521  					//
  2522  					// Dividing x by 1 obviously returns x, therefore satisfying
  2523  					// the Go specification without a branch.
  2524  					llvmType := x.Type()
  2525  					minusOne := llvm.ConstSub(llvm.ConstInt(llvmType, 0, false), llvm.ConstInt(llvmType, 1, false))
  2526  					lowestInteger := llvm.ConstInt(x.Type(), 1<<(llvmType.IntTypeWidth()-1), false)
  2527  					yIsMinusOne := b.CreateICmp(llvm.IntEQ, y, minusOne, "")
  2528  					xIsLowestInteger := b.CreateICmp(llvm.IntEQ, x, lowestInteger, "")
  2529  					hasOverflow := b.CreateAnd(yIsMinusOne, xIsLowestInteger, "")
  2530  					y = b.CreateSelect(hasOverflow, llvm.ConstInt(llvmType, 1, true), y, "")
  2531  
  2532  					if op == token.QUO {
  2533  						return b.CreateSDiv(x, y, ""), nil
  2534  					} else {
  2535  						return b.CreateSRem(x, y, ""), nil
  2536  					}
  2537  				} else {
  2538  					if op == token.QUO {
  2539  						return b.CreateUDiv(x, y, ""), nil
  2540  					} else {
  2541  						return b.CreateURem(x, y, ""), nil
  2542  					}
  2543  				}
  2544  			case token.AND: // &
  2545  				return b.CreateAnd(x, y, ""), nil
  2546  			case token.OR: // |
  2547  				return b.CreateOr(x, y, ""), nil
  2548  			case token.XOR: // ^
  2549  				return b.CreateXor(x, y, ""), nil
  2550  			case token.SHL, token.SHR:
  2551  				if ytyp.Underlying().(*types.Basic).Info()&types.IsUnsigned == 0 {
  2552  					// Ensure that y is not negative.
  2553  					b.createNegativeShiftCheck(y)
  2554  				}
  2555  
  2556  				sizeX := b.targetData.TypeAllocSize(x.Type())
  2557  				sizeY := b.targetData.TypeAllocSize(y.Type())
  2558  
  2559  				// Check if the shift is bigger than the bit-width of the shifted value.
  2560  				// This is UB in LLVM, so it needs to be handled seperately.
  2561  				// The Go spec indirectly defines the result as 0.
  2562  				// Negative shifts are handled earlier, so we can treat y as unsigned.
  2563  				overshifted := b.CreateICmp(llvm.IntUGE, y, llvm.ConstInt(y.Type(), 8*sizeX, false), "shift.overflow")
  2564  
  2565  				// Adjust the size of y to match x.
  2566  				switch {
  2567  				case sizeX > sizeY:
  2568  					y = b.CreateZExt(y, x.Type(), "")
  2569  				case sizeX < sizeY:
  2570  					// If it gets truncated, overshifted will be true and it will not matter.
  2571  					y = b.CreateTrunc(y, x.Type(), "")
  2572  				}
  2573  
  2574  				// Create a shift operation.
  2575  				var val llvm.Value
  2576  				switch op {
  2577  				case token.SHL: // <<
  2578  					val = b.CreateShl(x, y, "")
  2579  				case token.SHR: // >>
  2580  					if signed {
  2581  						// Arithmetic right shifts work differently, since shifting a negative number right yields -1.
  2582  						// Cap the shift input rather than selecting the output.
  2583  						y = b.CreateSelect(overshifted, llvm.ConstInt(y.Type(), 8*sizeX-1, false), y, "shift.offset")
  2584  						return b.CreateAShr(x, y, ""), nil
  2585  					} else {
  2586  						val = b.CreateLShr(x, y, "")
  2587  					}
  2588  				default:
  2589  					panic("unreachable")
  2590  				}
  2591  
  2592  				// Select between the shift result and zero depending on whether there was an overshift.
  2593  				return b.CreateSelect(overshifted, llvm.ConstInt(val.Type(), 0, false), val, "shift.result"), nil
  2594  			case token.EQL: // ==
  2595  				return b.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2596  			case token.NEQ: // !=
  2597  				return b.CreateICmp(llvm.IntNE, x, y, ""), nil
  2598  			case token.AND_NOT: // &^
  2599  				// Go specific. Calculate "and not" with x & (~y)
  2600  				inv := b.CreateNot(y, "") // ~y
  2601  				return b.CreateAnd(x, inv, ""), nil
  2602  			case token.LSS: // <
  2603  				if signed {
  2604  					return b.CreateICmp(llvm.IntSLT, x, y, ""), nil
  2605  				} else {
  2606  					return b.CreateICmp(llvm.IntULT, x, y, ""), nil
  2607  				}
  2608  			case token.LEQ: // <=
  2609  				if signed {
  2610  					return b.CreateICmp(llvm.IntSLE, x, y, ""), nil
  2611  				} else {
  2612  					return b.CreateICmp(llvm.IntULE, x, y, ""), nil
  2613  				}
  2614  			case token.GTR: // >
  2615  				if signed {
  2616  					return b.CreateICmp(llvm.IntSGT, x, y, ""), nil
  2617  				} else {
  2618  					return b.CreateICmp(llvm.IntUGT, x, y, ""), nil
  2619  				}
  2620  			case token.GEQ: // >=
  2621  				if signed {
  2622  					return b.CreateICmp(llvm.IntSGE, x, y, ""), nil
  2623  				} else {
  2624  					return b.CreateICmp(llvm.IntUGE, x, y, ""), nil
  2625  				}
  2626  			default:
  2627  				panic("binop on integer: " + op.String())
  2628  			}
  2629  		} else if typ.Info()&types.IsFloat != 0 {
  2630  			// Operations on floats
  2631  			switch op {
  2632  			case token.ADD: // +
  2633  				return b.CreateFAdd(x, y, ""), nil
  2634  			case token.SUB: // -
  2635  				return b.CreateFSub(x, y, ""), nil
  2636  			case token.MUL: // *
  2637  				return b.CreateFMul(x, y, ""), nil
  2638  			case token.QUO: // /
  2639  				return b.CreateFDiv(x, y, ""), nil
  2640  			case token.EQL: // ==
  2641  				return b.CreateFCmp(llvm.FloatOEQ, x, y, ""), nil
  2642  			case token.NEQ: // !=
  2643  				return b.CreateFCmp(llvm.FloatUNE, x, y, ""), nil
  2644  			case token.LSS: // <
  2645  				return b.CreateFCmp(llvm.FloatOLT, x, y, ""), nil
  2646  			case token.LEQ: // <=
  2647  				return b.CreateFCmp(llvm.FloatOLE, x, y, ""), nil
  2648  			case token.GTR: // >
  2649  				return b.CreateFCmp(llvm.FloatOGT, x, y, ""), nil
  2650  			case token.GEQ: // >=
  2651  				return b.CreateFCmp(llvm.FloatOGE, x, y, ""), nil
  2652  			default:
  2653  				panic("binop on float: " + op.String())
  2654  			}
  2655  		} else if typ.Info()&types.IsComplex != 0 {
  2656  			r1 := b.CreateExtractValue(x, 0, "r1")
  2657  			r2 := b.CreateExtractValue(y, 0, "r2")
  2658  			i1 := b.CreateExtractValue(x, 1, "i1")
  2659  			i2 := b.CreateExtractValue(y, 1, "i2")
  2660  			switch op {
  2661  			case token.EQL: // ==
  2662  				req := b.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
  2663  				ieq := b.CreateFCmp(llvm.FloatOEQ, i1, i2, "")
  2664  				return b.CreateAnd(req, ieq, ""), nil
  2665  			case token.NEQ: // !=
  2666  				req := b.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
  2667  				ieq := b.CreateFCmp(llvm.FloatOEQ, i1, i2, "")
  2668  				neq := b.CreateAnd(req, ieq, "")
  2669  				return b.CreateNot(neq, ""), nil
  2670  			case token.ADD, token.SUB:
  2671  				var r, i llvm.Value
  2672  				switch op {
  2673  				case token.ADD:
  2674  					r = b.CreateFAdd(r1, r2, "")
  2675  					i = b.CreateFAdd(i1, i2, "")
  2676  				case token.SUB:
  2677  					r = b.CreateFSub(r1, r2, "")
  2678  					i = b.CreateFSub(i1, i2, "")
  2679  				default:
  2680  					panic("unreachable")
  2681  				}
  2682  				cplx := llvm.Undef(b.ctx.StructType([]llvm.Type{r.Type(), i.Type()}, false))
  2683  				cplx = b.CreateInsertValue(cplx, r, 0, "")
  2684  				cplx = b.CreateInsertValue(cplx, i, 1, "")
  2685  				return cplx, nil
  2686  			case token.MUL:
  2687  				// Complex multiplication follows the current implementation in
  2688  				// the Go compiler, with the difference that complex64
  2689  				// components are not first scaled up to float64 for increased
  2690  				// precision.
  2691  				// https://github.com/golang/go/blob/170b8b4b12be50eeccbcdadb8523fb4fc670ca72/src/cmd/compile/internal/gc/ssa.go#L2089-L2127
  2692  				// The implementation is as follows:
  2693  				//   r := real(a) * real(b) - imag(a) * imag(b)
  2694  				//   i := real(a) * imag(b) + imag(a) * real(b)
  2695  				// Note: this does NOT follow the C11 specification (annex G):
  2696  				// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf#page=549
  2697  				// See https://github.com/golang/go/issues/29846 for a related
  2698  				// discussion.
  2699  				r := b.CreateFSub(b.CreateFMul(r1, r2, ""), b.CreateFMul(i1, i2, ""), "")
  2700  				i := b.CreateFAdd(b.CreateFMul(r1, i2, ""), b.CreateFMul(i1, r2, ""), "")
  2701  				cplx := llvm.Undef(b.ctx.StructType([]llvm.Type{r.Type(), i.Type()}, false))
  2702  				cplx = b.CreateInsertValue(cplx, r, 0, "")
  2703  				cplx = b.CreateInsertValue(cplx, i, 1, "")
  2704  				return cplx, nil
  2705  			case token.QUO:
  2706  				// Complex division.
  2707  				// Do this in a library call because it's too difficult to do
  2708  				// inline.
  2709  				switch r1.Type().TypeKind() {
  2710  				case llvm.FloatTypeKind:
  2711  					return b.createRuntimeCall("complex64div", []llvm.Value{x, y}, ""), nil
  2712  				case llvm.DoubleTypeKind:
  2713  					return b.createRuntimeCall("complex128div", []llvm.Value{x, y}, ""), nil
  2714  				default:
  2715  					panic("unexpected complex type")
  2716  				}
  2717  			default:
  2718  				panic("binop on complex: " + op.String())
  2719  			}
  2720  		} else if typ.Info()&types.IsBoolean != 0 {
  2721  			// Operations on booleans
  2722  			switch op {
  2723  			case token.EQL: // ==
  2724  				return b.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2725  			case token.NEQ: // !=
  2726  				return b.CreateICmp(llvm.IntNE, x, y, ""), nil
  2727  			default:
  2728  				panic("binop on bool: " + op.String())
  2729  			}
  2730  		} else if typ.Kind() == types.UnsafePointer {
  2731  			// Operations on pointers
  2732  			switch op {
  2733  			case token.EQL: // ==
  2734  				return b.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2735  			case token.NEQ: // !=
  2736  				return b.CreateICmp(llvm.IntNE, x, y, ""), nil
  2737  			default:
  2738  				panic("binop on pointer: " + op.String())
  2739  			}
  2740  		} else if typ.Info()&types.IsString != 0 {
  2741  			// Operations on strings
  2742  			switch op {
  2743  			case token.ADD: // +
  2744  				return b.createRuntimeCall("stringConcat", []llvm.Value{x, y}, ""), nil
  2745  			case token.EQL: // ==
  2746  				return b.createRuntimeCall("stringEqual", []llvm.Value{x, y}, ""), nil
  2747  			case token.NEQ: // !=
  2748  				result := b.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "")
  2749  				return b.CreateNot(result, ""), nil
  2750  			case token.LSS: // x < y
  2751  				return b.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil
  2752  			case token.LEQ: // x <= y becomes NOT (y < x)
  2753  				result := b.createRuntimeCall("stringLess", []llvm.Value{y, x}, "")
  2754  				return b.CreateNot(result, ""), nil
  2755  			case token.GTR: // x > y becomes y < x
  2756  				return b.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil
  2757  			case token.GEQ: // x >= y becomes NOT (x < y)
  2758  				result := b.createRuntimeCall("stringLess", []llvm.Value{x, y}, "")
  2759  				return b.CreateNot(result, ""), nil
  2760  			default:
  2761  				panic("binop on string: " + op.String())
  2762  			}
  2763  		} else {
  2764  			return llvm.Value{}, b.makeError(pos, "todo: unknown basic type in binop: "+typ.String())
  2765  		}
  2766  	case *types.Signature:
  2767  		// Get raw scalars from the function value and compare those.
  2768  		// Function values may be implemented in multiple ways, but they all
  2769  		// have some way of getting a scalar value identifying the function.
  2770  		// This is safe: function pointers are generally not comparable
  2771  		// against each other, only against nil. So one of these has to be nil.
  2772  		x = b.extractFuncScalar(x)
  2773  		y = b.extractFuncScalar(y)
  2774  		switch op {
  2775  		case token.EQL: // ==
  2776  			return b.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2777  		case token.NEQ: // !=
  2778  			return b.CreateICmp(llvm.IntNE, x, y, ""), nil
  2779  		default:
  2780  			return llvm.Value{}, b.makeError(pos, "binop on signature: "+op.String())
  2781  		}
  2782  	case *types.Interface:
  2783  		switch op {
  2784  		case token.EQL, token.NEQ: // ==, !=
  2785  			nilInterface := llvm.ConstNull(x.Type())
  2786  			var result llvm.Value
  2787  			if x == nilInterface || y == nilInterface {
  2788  				// An interface value is compared against nil.
  2789  				// This is a very common case and is easy to optimize: simply
  2790  				// compare the typecodes (of which one is nil).
  2791  				typecodeX := b.CreateExtractValue(x, 0, "")
  2792  				typecodeY := b.CreateExtractValue(y, 0, "")
  2793  				result = b.CreateICmp(llvm.IntEQ, typecodeX, typecodeY, "")
  2794  			} else {
  2795  				// Fall back to a full interface comparison.
  2796  				result = b.createRuntimeCall("interfaceEqual", []llvm.Value{x, y}, "")
  2797  			}
  2798  			if op == token.NEQ {
  2799  				result = b.CreateNot(result, "")
  2800  			}
  2801  			return result, nil
  2802  		default:
  2803  			return llvm.Value{}, b.makeError(pos, "binop on interface: "+op.String())
  2804  		}
  2805  	case *types.Chan, *types.Map, *types.Pointer:
  2806  		// Maps are in general not comparable, but can be compared against nil
  2807  		// (which is a nil pointer). This means they can be trivially compared
  2808  		// by treating them as a pointer.
  2809  		// Channels behave as pointers in that they are equal as long as they
  2810  		// are created with the same call to make or if both are nil.
  2811  		switch op {
  2812  		case token.EQL: // ==
  2813  			return b.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2814  		case token.NEQ: // !=
  2815  			return b.CreateICmp(llvm.IntNE, x, y, ""), nil
  2816  		default:
  2817  			return llvm.Value{}, b.makeError(pos, "todo: binop on pointer: "+op.String())
  2818  		}
  2819  	case *types.Slice:
  2820  		// Slices are in general not comparable, but can be compared against
  2821  		// nil. Assume at least one of them is nil to make the code easier.
  2822  		xPtr := b.CreateExtractValue(x, 0, "")
  2823  		yPtr := b.CreateExtractValue(y, 0, "")
  2824  		switch op {
  2825  		case token.EQL: // ==
  2826  			return b.CreateICmp(llvm.IntEQ, xPtr, yPtr, ""), nil
  2827  		case token.NEQ: // !=
  2828  			return b.CreateICmp(llvm.IntNE, xPtr, yPtr, ""), nil
  2829  		default:
  2830  			return llvm.Value{}, b.makeError(pos, "todo: binop on slice: "+op.String())
  2831  		}
  2832  	case *types.Array:
  2833  		// Compare each array element and combine the result. From the spec:
  2834  		//     Array values are comparable if values of the array element type
  2835  		//     are comparable. Two array values are equal if their corresponding
  2836  		//     elements are equal.
  2837  		result := llvm.ConstInt(b.ctx.Int1Type(), 1, true)
  2838  		for i := 0; i < int(typ.Len()); i++ {
  2839  			xField := b.CreateExtractValue(x, i, "")
  2840  			yField := b.CreateExtractValue(y, i, "")
  2841  			fieldEqual, err := b.createBinOp(token.EQL, typ.Elem(), typ.Elem(), xField, yField, pos)
  2842  			if err != nil {
  2843  				return llvm.Value{}, err
  2844  			}
  2845  			result = b.CreateAnd(result, fieldEqual, "")
  2846  		}
  2847  		switch op {
  2848  		case token.EQL: // ==
  2849  			return result, nil
  2850  		case token.NEQ: // !=
  2851  			return b.CreateNot(result, ""), nil
  2852  		default:
  2853  			return llvm.Value{}, b.makeError(pos, "unknown: binop on struct: "+op.String())
  2854  		}
  2855  	case *types.Struct:
  2856  		// Compare each struct field and combine the result. From the spec:
  2857  		//     Struct values are comparable if all their fields are comparable.
  2858  		//     Two struct values are equal if their corresponding non-blank
  2859  		//     fields are equal.
  2860  		result := llvm.ConstInt(b.ctx.Int1Type(), 1, true)
  2861  		for i := 0; i < typ.NumFields(); i++ {
  2862  			if typ.Field(i).Name() == "_" {
  2863  				// skip blank fields
  2864  				continue
  2865  			}
  2866  			fieldType := typ.Field(i).Type()
  2867  			xField := b.CreateExtractValue(x, i, "")
  2868  			yField := b.CreateExtractValue(y, i, "")
  2869  			fieldEqual, err := b.createBinOp(token.EQL, fieldType, fieldType, xField, yField, pos)
  2870  			if err != nil {
  2871  				return llvm.Value{}, err
  2872  			}
  2873  			result = b.CreateAnd(result, fieldEqual, "")
  2874  		}
  2875  		switch op {
  2876  		case token.EQL: // ==
  2877  			return result, nil
  2878  		case token.NEQ: // !=
  2879  			return b.CreateNot(result, ""), nil
  2880  		default:
  2881  			return llvm.Value{}, b.makeError(pos, "unknown: binop on struct: "+op.String())
  2882  		}
  2883  	default:
  2884  		return llvm.Value{}, b.makeError(pos, "todo: binop type: "+typ.String())
  2885  	}
  2886  }
  2887  
  2888  // createConst creates a LLVM constant value from a Go constant.
  2889  func (c *compilerContext) createConst(expr *ssa.Const, pos token.Pos) llvm.Value {
  2890  	switch typ := expr.Type().Underlying().(type) {
  2891  	case *types.Basic:
  2892  		llvmType := c.getLLVMType(typ)
  2893  		if typ.Info()&types.IsBoolean != 0 {
  2894  			n := uint64(0)
  2895  			if constant.BoolVal(expr.Value) {
  2896  				n = 1
  2897  			}
  2898  			return llvm.ConstInt(llvmType, n, false)
  2899  		} else if typ.Info()&types.IsString != 0 {
  2900  			str := constant.StringVal(expr.Value)
  2901  			strLen := llvm.ConstInt(c.uintptrType, uint64(len(str)), false)
  2902  			var strPtr llvm.Value
  2903  			if str != "" {
  2904  				objname := c.pkg.Path() + "$string"
  2905  				globalType := llvm.ArrayType(c.ctx.Int8Type(), len(str))
  2906  				global := llvm.AddGlobal(c.mod, globalType, objname)
  2907  				global.SetInitializer(c.ctx.ConstString(str, false))
  2908  				global.SetLinkage(llvm.InternalLinkage)
  2909  				global.SetGlobalConstant(true)
  2910  				global.SetUnnamedAddr(true)
  2911  				global.SetAlignment(1)
  2912  				if c.Debug {
  2913  					// Unfortunately, expr.Pos() is always token.NoPos.
  2914  					position := c.program.Fset.Position(pos)
  2915  					diglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{
  2916  						File:        c.getDIFile(position.Filename),
  2917  						Line:        position.Line,
  2918  						Type:        c.getDIType(types.NewArray(types.Typ[types.Byte], int64(len(str)))),
  2919  						LocalToUnit: true,
  2920  						Expr:        c.dibuilder.CreateExpression(nil),
  2921  					})
  2922  					global.AddMetadata(0, diglobal)
  2923  				}
  2924  				zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
  2925  				strPtr = llvm.ConstInBoundsGEP(globalType, global, []llvm.Value{zero, zero})
  2926  			} else {
  2927  				strPtr = llvm.ConstNull(c.dataPtrType)
  2928  			}
  2929  			strObj := llvm.ConstNamedStruct(c.getLLVMRuntimeType("_string"), []llvm.Value{strPtr, strLen})
  2930  			return strObj
  2931  		} else if typ.Kind() == types.UnsafePointer {
  2932  			if !expr.IsNil() {
  2933  				value, _ := constant.Uint64Val(constant.ToInt(expr.Value))
  2934  				return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, value, false), c.dataPtrType)
  2935  			}
  2936  			return llvm.ConstNull(c.dataPtrType)
  2937  		} else if typ.Info()&types.IsUnsigned != 0 {
  2938  			n, _ := constant.Uint64Val(constant.ToInt(expr.Value))
  2939  			return llvm.ConstInt(llvmType, n, false)
  2940  		} else if typ.Info()&types.IsInteger != 0 { // signed
  2941  			n, _ := constant.Int64Val(constant.ToInt(expr.Value))
  2942  			return llvm.ConstInt(llvmType, uint64(n), true)
  2943  		} else if typ.Info()&types.IsFloat != 0 {
  2944  			n, _ := constant.Float64Val(expr.Value)
  2945  			return llvm.ConstFloat(llvmType, n)
  2946  		} else if typ.Kind() == types.Complex64 {
  2947  			r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32]), pos)
  2948  			i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32]), pos)
  2949  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
  2950  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2951  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2952  			return cplx
  2953  		} else if typ.Kind() == types.Complex128 {
  2954  			r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]), pos)
  2955  			i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64]), pos)
  2956  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
  2957  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2958  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2959  			return cplx
  2960  		} else {
  2961  			panic("unknown constant of basic type: " + expr.String())
  2962  		}
  2963  	case *types.Chan:
  2964  		if expr.Value != nil {
  2965  			panic("expected nil chan constant")
  2966  		}
  2967  		return llvm.ConstNull(c.getLLVMType(expr.Type()))
  2968  	case *types.Signature:
  2969  		if expr.Value != nil {
  2970  			panic("expected nil signature constant")
  2971  		}
  2972  		return llvm.ConstNull(c.getLLVMType(expr.Type()))
  2973  	case *types.Interface:
  2974  		if expr.Value != nil {
  2975  			panic("expected nil interface constant")
  2976  		}
  2977  		// Create a generic nil interface with no dynamic type (typecode=0).
  2978  		fields := []llvm.Value{
  2979  			llvm.ConstInt(c.uintptrType, 0, false),
  2980  			llvm.ConstPointerNull(c.dataPtrType),
  2981  		}
  2982  		return llvm.ConstNamedStruct(c.getLLVMRuntimeType("_interface"), fields)
  2983  	case *types.Pointer:
  2984  		if expr.Value != nil {
  2985  			panic("expected nil pointer constant")
  2986  		}
  2987  		return llvm.ConstPointerNull(c.getLLVMType(typ))
  2988  	case *types.Array:
  2989  		if expr.Value != nil {
  2990  			panic("expected nil array constant")
  2991  		}
  2992  		return llvm.ConstNull(c.getLLVMType(expr.Type()))
  2993  	case *types.Slice:
  2994  		if expr.Value != nil {
  2995  			panic("expected nil slice constant")
  2996  		}
  2997  		llvmPtr := llvm.ConstPointerNull(c.dataPtrType)
  2998  		llvmLen := llvm.ConstInt(c.uintptrType, 0, false)
  2999  		slice := c.ctx.ConstStruct([]llvm.Value{
  3000  			llvmPtr, // backing array
  3001  			llvmLen, // len
  3002  			llvmLen, // cap
  3003  		}, false)
  3004  		return slice
  3005  	case *types.Struct:
  3006  		if expr.Value != nil {
  3007  			panic("expected nil struct constant")
  3008  		}
  3009  		return llvm.ConstNull(c.getLLVMType(expr.Type()))
  3010  	case *types.Map:
  3011  		if !expr.IsNil() {
  3012  			// I believe this is not allowed by the Go spec.
  3013  			panic("non-nil map constant")
  3014  		}
  3015  		llvmType := c.getLLVMType(typ)
  3016  		return llvm.ConstNull(llvmType)
  3017  	default:
  3018  		panic("unknown constant: " + expr.String())
  3019  	}
  3020  }
  3021  
  3022  // createConvert creates a Go type conversion instruction.
  3023  func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) {
  3024  	llvmTypeFrom := value.Type()
  3025  	llvmTypeTo := b.getLLVMType(typeTo)
  3026  
  3027  	// Conversion between unsafe.Pointer and uintptr.
  3028  	isPtrFrom := isPointer(typeFrom.Underlying())
  3029  	isPtrTo := isPointer(typeTo.Underlying())
  3030  	if isPtrFrom && !isPtrTo {
  3031  		return b.CreatePtrToInt(value, llvmTypeTo, ""), nil
  3032  	} else if !isPtrFrom && isPtrTo {
  3033  		return b.CreateIntToPtr(value, llvmTypeTo, ""), nil
  3034  	}
  3035  
  3036  	// Conversion between pointers and unsafe.Pointer.
  3037  	if isPtrFrom && isPtrTo {
  3038  		return value, nil
  3039  	}
  3040  
  3041  	switch typeTo := typeTo.Underlying().(type) {
  3042  	case *types.Basic:
  3043  		sizeFrom := b.targetData.TypeAllocSize(llvmTypeFrom)
  3044  
  3045  		if typeTo.Info()&types.IsString != 0 {
  3046  			switch typeFrom := typeFrom.Underlying().(type) {
  3047  			case *types.Basic:
  3048  				// Assume a Unicode code point, as that is the only possible
  3049  				// value here.
  3050  				// Cast to an i32 value as expected by
  3051  				// runtime.stringFromUnicode.
  3052  				if sizeFrom > 4 {
  3053  					value = b.CreateTrunc(value, b.ctx.Int32Type(), "")
  3054  				} else if sizeFrom < 4 && typeTo.Info()&types.IsUnsigned != 0 {
  3055  					value = b.CreateZExt(value, b.ctx.Int32Type(), "")
  3056  				} else if sizeFrom < 4 {
  3057  					value = b.CreateSExt(value, b.ctx.Int32Type(), "")
  3058  				}
  3059  				return b.createRuntimeCall("stringFromUnicode", []llvm.Value{value}, ""), nil
  3060  			case *types.Slice:
  3061  				switch typeFrom.Elem().(*types.Basic).Kind() {
  3062  				case types.Byte:
  3063  					return b.createRuntimeCall("stringFromBytes", []llvm.Value{value}, ""), nil
  3064  				case types.Rune:
  3065  					return b.createRuntimeCall("stringFromRunes", []llvm.Value{value}, ""), nil
  3066  				default:
  3067  					return llvm.Value{}, b.makeError(pos, "todo: convert to string: "+typeFrom.String())
  3068  				}
  3069  			default:
  3070  				return llvm.Value{}, b.makeError(pos, "todo: convert to string: "+typeFrom.String())
  3071  			}
  3072  		}
  3073  
  3074  		typeFrom := typeFrom.Underlying().(*types.Basic)
  3075  		sizeTo := b.targetData.TypeAllocSize(llvmTypeTo)
  3076  
  3077  		if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 {
  3078  			// Conversion between two integers.
  3079  			if sizeFrom > sizeTo {
  3080  				return b.CreateTrunc(value, llvmTypeTo, ""), nil
  3081  			} else if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned
  3082  				return b.CreateZExt(value, llvmTypeTo, ""), nil
  3083  			} else { // if signed
  3084  				return b.CreateSExt(value, llvmTypeTo, ""), nil
  3085  			}
  3086  		}
  3087  
  3088  		if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsFloat != 0 {
  3089  			// Conversion between two floats.
  3090  			if sizeFrom > sizeTo {
  3091  				return b.CreateFPTrunc(value, llvmTypeTo, ""), nil
  3092  			} else if sizeFrom < sizeTo {
  3093  				return b.CreateFPExt(value, llvmTypeTo, ""), nil
  3094  			} else {
  3095  				return value, nil
  3096  			}
  3097  		}
  3098  
  3099  		if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsInteger != 0 {
  3100  			// Conversion from float to int.
  3101  			// Passing an out-of-bounds float to LLVM would cause UB, so that UB is trapped by select instructions.
  3102  			// The Go specification says that this should be implementation-defined behavior.
  3103  			// This implements saturating behavior, except that NaN is mapped to the minimum value.
  3104  			var significandBits int
  3105  			switch typeFrom.Kind() {
  3106  			case types.Float32:
  3107  				significandBits = 23
  3108  			case types.Float64:
  3109  				significandBits = 52
  3110  			}
  3111  			if typeTo.Info()&types.IsUnsigned != 0 { // if unsigned
  3112  				// Select the maximum value for this unsigned integer type.
  3113  				max := ^(^uint64(0) << uint(llvmTypeTo.IntTypeWidth()))
  3114  				maxFloat := float64(max)
  3115  				if bits.Len64(max) > significandBits {
  3116  					// Round the max down to fit within the significand.
  3117  					maxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))
  3118  				}
  3119  
  3120  				// Check if the value is in-bounds (0 <= value <= max).
  3121  				positive := b.CreateFCmp(llvm.FloatOLE, llvm.ConstNull(llvmTypeFrom), value, "positive")
  3122  				withinMax := b.CreateFCmp(llvm.FloatOLE, value, llvm.ConstFloat(llvmTypeFrom, maxFloat), "withinmax")
  3123  				inBounds := b.CreateAnd(positive, withinMax, "inbounds")
  3124  
  3125  				// Assuming that the value is out-of-bounds, select a saturated value.
  3126  				saturated := b.CreateSelect(positive,
  3127  					llvm.ConstInt(llvmTypeTo, max, false), // value > max
  3128  					llvm.ConstNull(llvmTypeTo),            // value < 0 (or NaN)
  3129  					"saturated",
  3130  				)
  3131  
  3132  				// Do a normal conversion.
  3133  				normal := b.CreateFPToUI(value, llvmTypeTo, "normal")
  3134  
  3135  				return b.CreateSelect(inBounds, normal, saturated, ""), nil
  3136  			} else { // if signed
  3137  				// Select the minimum value for this signed integer type.
  3138  				min := uint64(1) << uint(llvmTypeTo.IntTypeWidth()-1)
  3139  				minFloat := -float64(min)
  3140  
  3141  				// Select the maximum value for this signed integer type.
  3142  				max := ^(^uint64(0) << uint(llvmTypeTo.IntTypeWidth()-1))
  3143  				maxFloat := float64(max)
  3144  				if bits.Len64(max) > significandBits {
  3145  					// Round the max down to fit within the significand.
  3146  					maxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))
  3147  				}
  3148  
  3149  				// Check if the value is in-bounds (min <= value <= max).
  3150  				aboveMin := b.CreateFCmp(llvm.FloatOLE, llvm.ConstFloat(llvmTypeFrom, minFloat), value, "abovemin")
  3151  				belowMax := b.CreateFCmp(llvm.FloatOLE, value, llvm.ConstFloat(llvmTypeFrom, maxFloat), "belowmax")
  3152  				inBounds := b.CreateAnd(aboveMin, belowMax, "inbounds")
  3153  
  3154  				// Assuming that the value is out-of-bounds, select a saturated value.
  3155  				saturated := b.CreateSelect(aboveMin,
  3156  					llvm.ConstInt(llvmTypeTo, max, false), // value > max
  3157  					llvm.ConstInt(llvmTypeTo, min, false), // value < min
  3158  					"saturated",
  3159  				)
  3160  
  3161  				// Map NaN to 0.
  3162  				saturated = b.CreateSelect(b.CreateFCmp(llvm.FloatUNO, value, value, "isnan"),
  3163  					llvm.ConstNull(llvmTypeTo),
  3164  					saturated,
  3165  					"remapped",
  3166  				)
  3167  
  3168  				// Do a normal conversion.
  3169  				normal := b.CreateFPToSI(value, llvmTypeTo, "normal")
  3170  
  3171  				return b.CreateSelect(inBounds, normal, saturated, ""), nil
  3172  			}
  3173  		}
  3174  
  3175  		if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsFloat != 0 {
  3176  			// Conversion from int to float.
  3177  			if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned
  3178  				return b.CreateUIToFP(value, llvmTypeTo, ""), nil
  3179  			} else { // if signed
  3180  				return b.CreateSIToFP(value, llvmTypeTo, ""), nil
  3181  			}
  3182  		}
  3183  
  3184  		if typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 {
  3185  			// Conversion from complex128 to complex64.
  3186  			r := b.CreateExtractValue(value, 0, "real.f64")
  3187  			i := b.CreateExtractValue(value, 1, "imag.f64")
  3188  			r = b.CreateFPTrunc(r, b.ctx.FloatType(), "real.f32")
  3189  			i = b.CreateFPTrunc(i, b.ctx.FloatType(), "imag.f32")
  3190  			cplx := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.FloatType(), b.ctx.FloatType()}, false))
  3191  			cplx = b.CreateInsertValue(cplx, r, 0, "")
  3192  			cplx = b.CreateInsertValue(cplx, i, 1, "")
  3193  			return cplx, nil
  3194  		}
  3195  
  3196  		if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {
  3197  			// Conversion from complex64 to complex128.
  3198  			r := b.CreateExtractValue(value, 0, "real.f32")
  3199  			i := b.CreateExtractValue(value, 1, "imag.f32")
  3200  			r = b.CreateFPExt(r, b.ctx.DoubleType(), "real.f64")
  3201  			i = b.CreateFPExt(i, b.ctx.DoubleType(), "imag.f64")
  3202  			cplx := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.DoubleType(), b.ctx.DoubleType()}, false))
  3203  			cplx = b.CreateInsertValue(cplx, r, 0, "")
  3204  			cplx = b.CreateInsertValue(cplx, i, 1, "")
  3205  			return cplx, nil
  3206  		}
  3207  
  3208  		return llvm.Value{}, b.makeError(pos, "todo: convert: basic non-integer type: "+typeFrom.String()+" -> "+typeTo.String())
  3209  
  3210  	case *types.Slice:
  3211  		if basic, ok := typeFrom.Underlying().(*types.Basic); !ok || basic.Info()&types.IsString == 0 {
  3212  			panic("can only convert from a string to a slice")
  3213  		}
  3214  
  3215  		elemType := typeTo.Elem().Underlying().(*types.Basic) // must be byte or rune
  3216  		switch elemType.Kind() {
  3217  		case types.Byte:
  3218  			return b.createRuntimeCall("stringToBytes", []llvm.Value{value}, ""), nil
  3219  		case types.Rune:
  3220  			return b.createRuntimeCall("stringToRunes", []llvm.Value{value}, ""), nil
  3221  		default:
  3222  			panic("unexpected type in string to slice conversion")
  3223  		}
  3224  
  3225  	default:
  3226  		return llvm.Value{}, b.makeError(pos, "todo: convert "+typeTo.String()+" <- "+typeFrom.String())
  3227  	}
  3228  }
  3229  
  3230  // createUnOp creates LLVM IR for a given Go unary operation.
  3231  // Most unary operators are pretty simple, such as the not and minus operator
  3232  // which can all be directly lowered to IR. However, there is also the channel
  3233  // receive operator which is handled in the runtime directly.
  3234  func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
  3235  	x := b.getValue(unop.X, getPos(unop))
  3236  	switch unop.Op {
  3237  	case token.NOT: // !x
  3238  		return b.CreateNot(x, ""), nil
  3239  	case token.SUB: // -x
  3240  		if typ, ok := unop.X.Type().Underlying().(*types.Basic); ok {
  3241  			if typ.Info()&types.IsInteger != 0 {
  3242  				return b.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil
  3243  			} else if typ.Info()&types.IsFloat != 0 {
  3244  				return b.CreateFNeg(x, ""), nil
  3245  			} else if typ.Info()&types.IsComplex != 0 {
  3246  				// Negate both components of the complex number.
  3247  				r := b.CreateExtractValue(x, 0, "r")
  3248  				i := b.CreateExtractValue(x, 1, "i")
  3249  				r = b.CreateFNeg(r, "")
  3250  				i = b.CreateFNeg(i, "")
  3251  				cplx := llvm.Undef(x.Type())
  3252  				cplx = b.CreateInsertValue(cplx, r, 0, "")
  3253  				cplx = b.CreateInsertValue(cplx, i, 1, "")
  3254  				return cplx, nil
  3255  			} else {
  3256  				return llvm.Value{}, b.makeError(unop.Pos(), "todo: unknown basic type for negate: "+typ.String())
  3257  			}
  3258  		} else {
  3259  			return llvm.Value{}, b.makeError(unop.Pos(), "todo: unknown type for negate: "+unop.X.Type().Underlying().String())
  3260  		}
  3261  	case token.MUL: // *x, dereference pointer
  3262  		valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
  3263  		if b.targetData.TypeAllocSize(valueType) == 0 {
  3264  			// zero-length data
  3265  			return llvm.ConstNull(valueType), nil
  3266  		} else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
  3267  			// CGo function pointer. The cgo part has rewritten CGo function
  3268  			// pointers as stub global variables of the form:
  3269  			//     var C.add unsafe.Pointer
  3270  			// Instead of a load from the global, create a bitcast of the
  3271  			// function pointer itself.
  3272  			name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr")
  3273  			pkg := b.fn.Pkg
  3274  			if pkg == nil {
  3275  				pkg = b.fn.Origin().Pkg
  3276  			}
  3277  			_, fn := b.getFunction(pkg.Members[name].(*ssa.Function))
  3278  			if fn.IsNil() {
  3279  				return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found: "+name)
  3280  			}
  3281  			return fn, nil
  3282  		} else {
  3283  			b.createNilCheck(unop.X, x, "deref")
  3284  			load := b.CreateLoad(valueType, x, "")
  3285  			return load, nil
  3286  		}
  3287  	case token.XOR: // ^x, toggle all bits in integer
  3288  		return b.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), ""), nil
  3289  	case token.ARROW: // <-x, receive from channel
  3290  		return b.createChanRecv(unop), nil
  3291  	default:
  3292  		return llvm.Value{}, b.makeError(unop.Pos(), "todo: unknown unop")
  3293  	}
  3294  }