github.com/aykevl/tinygo@v0.5.0/compiler/compiler.go (about)

     1  package compiler
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"go/build"
     7  	"go/constant"
     8  	"go/token"
     9  	"go/types"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"strconv"
    14  	"strings"
    15  
    16  	"github.com/tinygo-org/tinygo/ir"
    17  	"github.com/tinygo-org/tinygo/loader"
    18  	"golang.org/x/tools/go/ssa"
    19  	"tinygo.org/x/go-llvm"
    20  )
    21  
    22  func init() {
    23  	llvm.InitializeAllTargets()
    24  	llvm.InitializeAllTargetMCs()
    25  	llvm.InitializeAllTargetInfos()
    26  	llvm.InitializeAllAsmParsers()
    27  	llvm.InitializeAllAsmPrinters()
    28  }
    29  
    30  // Configure the compiler.
    31  type Config struct {
    32  	Triple    string   // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default)
    33  	CPU       string   // LLVM CPU name, e.g. atmega328p (empty string means default)
    34  	GOOS      string   //
    35  	GOARCH    string   //
    36  	GC        string   // garbage collection strategy
    37  	CFlags    []string // cflags to pass to cgo
    38  	LDFlags   []string // ldflags to pass to cgo
    39  	DumpSSA   bool     // dump Go SSA, for compiler debugging
    40  	Debug     bool     // add debug symbols for gdb
    41  	RootDir   string   // GOROOT for TinyGo
    42  	GOPATH    string   // GOPATH, like `go env GOPATH`
    43  	BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH})
    44  }
    45  
    46  type Compiler struct {
    47  	Config
    48  	mod                     llvm.Module
    49  	ctx                     llvm.Context
    50  	builder                 llvm.Builder
    51  	dibuilder               *llvm.DIBuilder
    52  	cu                      llvm.Metadata
    53  	difiles                 map[string]llvm.Metadata
    54  	ditypes                 map[string]llvm.Metadata
    55  	machine                 llvm.TargetMachine
    56  	targetData              llvm.TargetData
    57  	intType                 llvm.Type
    58  	i8ptrType               llvm.Type // for convenience
    59  	funcPtrAddrSpace        int
    60  	uintptrType             llvm.Type
    61  	initFuncs               []llvm.Value
    62  	interfaceInvokeWrappers []interfaceInvokeWrapper
    63  	ir                      *ir.Program
    64  }
    65  
    66  type Frame struct {
    67  	fn                *ir.Function
    68  	locals            map[ssa.Value]llvm.Value            // local variables
    69  	blockEntries      map[*ssa.BasicBlock]llvm.BasicBlock // a *ssa.BasicBlock may be split up
    70  	blockExits        map[*ssa.BasicBlock]llvm.BasicBlock // these are the exit blocks
    71  	currentBlock      *ssa.BasicBlock
    72  	phis              []Phi
    73  	taskHandle        llvm.Value
    74  	deferPtr          llvm.Value
    75  	difunc            llvm.Metadata
    76  	allDeferFuncs     []interface{}
    77  	deferFuncs        map[*ir.Function]int
    78  	deferInvokeFuncs  map[string]int
    79  	deferClosureFuncs map[*ir.Function]int
    80  }
    81  
    82  type Phi struct {
    83  	ssa  *ssa.Phi
    84  	llvm llvm.Value
    85  }
    86  
    87  func NewCompiler(pkgName string, config Config) (*Compiler, error) {
    88  	if config.Triple == "" {
    89  		config.Triple = llvm.DefaultTargetTriple()
    90  	}
    91  	if len(config.BuildTags) == 0 {
    92  		config.BuildTags = []string{config.GOOS, config.GOARCH}
    93  	}
    94  	c := &Compiler{
    95  		Config:  config,
    96  		difiles: make(map[string]llvm.Metadata),
    97  		ditypes: make(map[string]llvm.Metadata),
    98  	}
    99  
   100  	target, err := llvm.GetTargetFromTriple(config.Triple)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	c.machine = target.CreateTargetMachine(config.Triple, config.CPU, "", llvm.CodeGenLevelDefault, llvm.RelocStatic, llvm.CodeModelDefault)
   105  	c.targetData = c.machine.CreateTargetData()
   106  
   107  	c.ctx = llvm.NewContext()
   108  	c.mod = c.ctx.NewModule(pkgName)
   109  	c.mod.SetTarget(config.Triple)
   110  	c.mod.SetDataLayout(c.targetData.String())
   111  	c.builder = c.ctx.NewBuilder()
   112  	if c.Debug {
   113  		c.dibuilder = llvm.NewDIBuilder(c.mod)
   114  	}
   115  
   116  	c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
   117  	if c.targetData.PointerSize() <= 4 {
   118  		// 8, 16, 32 bits targets
   119  		c.intType = c.ctx.Int32Type()
   120  	} else if c.targetData.PointerSize() == 8 {
   121  		// 64 bits target
   122  		c.intType = c.ctx.Int64Type()
   123  	} else {
   124  		panic("unknown pointer size")
   125  	}
   126  	c.i8ptrType = llvm.PointerType(c.ctx.Int8Type(), 0)
   127  
   128  	dummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false)
   129  	dummyFunc := llvm.AddFunction(c.mod, "tinygo.dummy", dummyFuncType)
   130  	c.funcPtrAddrSpace = dummyFunc.Type().PointerAddressSpace()
   131  	dummyFunc.EraseFromParentAsFunction()
   132  
   133  	return c, nil
   134  }
   135  
   136  func (c *Compiler) Packages() []*loader.Package {
   137  	return c.ir.LoaderProgram.Sorted()
   138  }
   139  
   140  // Return the LLVM module. Only valid after a successful compile.
   141  func (c *Compiler) Module() llvm.Module {
   142  	return c.mod
   143  }
   144  
   145  // Return the LLVM target data object. Only valid after a successful compile.
   146  func (c *Compiler) TargetData() llvm.TargetData {
   147  	return c.targetData
   148  }
   149  
   150  // selectGC picks an appropriate GC strategy if none was provided.
   151  func (c *Compiler) selectGC() string {
   152  	gc := c.GC
   153  	if gc == "" {
   154  		gc = "dumb"
   155  	}
   156  	return gc
   157  }
   158  
   159  // Compile the given package path or .go file path. Return an error when this
   160  // fails (in any stage).
   161  func (c *Compiler) Compile(mainPath string) error {
   162  	// Prefix the GOPATH with the system GOROOT, as GOROOT is already set to
   163  	// the TinyGo root.
   164  	overlayGopath := c.GOPATH
   165  	if overlayGopath == "" {
   166  		overlayGopath = runtime.GOROOT()
   167  	} else {
   168  		overlayGopath = runtime.GOROOT() + string(filepath.ListSeparator) + overlayGopath
   169  	}
   170  
   171  	wd, err := os.Getwd()
   172  	if err != nil {
   173  		return err
   174  	}
   175  	lprogram := &loader.Program{
   176  		Build: &build.Context{
   177  			GOARCH:      c.GOARCH,
   178  			GOOS:        c.GOOS,
   179  			GOROOT:      runtime.GOROOT(),
   180  			GOPATH:      c.GOPATH,
   181  			CgoEnabled:  true,
   182  			UseAllFiles: false,
   183  			Compiler:    "gc", // must be one of the recognized compilers
   184  			BuildTags:   append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...),
   185  		},
   186  		OverlayBuild: &build.Context{
   187  			GOARCH:      c.GOARCH,
   188  			GOOS:        c.GOOS,
   189  			GOROOT:      c.RootDir,
   190  			GOPATH:      overlayGopath,
   191  			CgoEnabled:  true,
   192  			UseAllFiles: false,
   193  			Compiler:    "gc", // must be one of the recognized compilers
   194  			BuildTags:   append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...),
   195  		},
   196  		ShouldOverlay: func(path string) bool {
   197  			switch path {
   198  			case "machine", "os", "reflect", "runtime", "sync":
   199  				return true
   200  			default:
   201  				if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") {
   202  					return true
   203  				} else if path == "syscall" {
   204  					for _, tag := range c.BuildTags {
   205  						if tag == "avr" || tag == "cortexm" || tag == "darwin" {
   206  							return true
   207  						}
   208  					}
   209  				}
   210  			}
   211  			return false
   212  		},
   213  		TypeChecker: types.Config{
   214  			Sizes: &StdSizes{
   215  				IntSize:  int64(c.targetData.TypeAllocSize(c.intType)),
   216  				PtrSize:  int64(c.targetData.PointerSize()),
   217  				MaxAlign: int64(c.targetData.PrefTypeAlignment(c.i8ptrType)),
   218  			},
   219  		},
   220  		Dir:    wd,
   221  		CFlags: c.CFlags,
   222  	}
   223  	if strings.HasSuffix(mainPath, ".go") {
   224  		_, err = lprogram.ImportFile(mainPath)
   225  		if err != nil {
   226  			return err
   227  		}
   228  	} else {
   229  		_, err = lprogram.Import(mainPath, wd)
   230  		if err != nil {
   231  			return err
   232  		}
   233  	}
   234  	_, err = lprogram.Import("runtime", "")
   235  	if err != nil {
   236  		return err
   237  	}
   238  
   239  	err = lprogram.Parse()
   240  	if err != nil {
   241  		return err
   242  	}
   243  
   244  	c.ir = ir.NewProgram(lprogram, mainPath)
   245  
   246  	// Run a simple dead code elimination pass.
   247  	c.ir.SimpleDCE()
   248  
   249  	// Initialize debug information.
   250  	if c.Debug {
   251  		c.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{
   252  			Language:  llvm.DW_LANG_Go,
   253  			File:      mainPath,
   254  			Dir:       "",
   255  			Producer:  "TinyGo",
   256  			Optimized: true,
   257  		})
   258  	}
   259  
   260  	var frames []*Frame
   261  
   262  	// Declare all named struct types.
   263  	for _, t := range c.ir.NamedTypes {
   264  		if named, ok := t.Type.Type().(*types.Named); ok {
   265  			if _, ok := named.Underlying().(*types.Struct); ok {
   266  				t.LLVMType = c.ctx.StructCreateNamed(named.Obj().Pkg().Path() + "." + named.Obj().Name())
   267  			}
   268  		}
   269  	}
   270  
   271  	// Define all named struct types.
   272  	for _, t := range c.ir.NamedTypes {
   273  		if named, ok := t.Type.Type().(*types.Named); ok {
   274  			if st, ok := named.Underlying().(*types.Struct); ok {
   275  				llvmType, err := c.getLLVMType(st)
   276  				if err != nil {
   277  					return err
   278  				}
   279  				t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false)
   280  			}
   281  		}
   282  	}
   283  
   284  	// Declare all globals.
   285  	for _, g := range c.ir.Globals {
   286  		typ := g.Type().(*types.Pointer).Elem()
   287  		llvmType, err := c.getLLVMType(typ)
   288  		if err != nil {
   289  			return err
   290  		}
   291  		global := c.mod.NamedGlobal(g.LinkName())
   292  		if global.IsNil() {
   293  			global = llvm.AddGlobal(c.mod, llvmType, g.LinkName())
   294  		}
   295  		g.LLVMGlobal = global
   296  		if !g.IsExtern() {
   297  			global.SetLinkage(llvm.InternalLinkage)
   298  			initializer, err := c.getZeroValue(llvmType)
   299  			if err != nil {
   300  				return err
   301  			}
   302  			global.SetInitializer(initializer)
   303  		}
   304  	}
   305  
   306  	// Declare all functions.
   307  	for _, f := range c.ir.Functions {
   308  		frame, err := c.parseFuncDecl(f)
   309  		if err != nil {
   310  			return err
   311  		}
   312  		frames = append(frames, frame)
   313  	}
   314  
   315  	// Add definitions to declarations.
   316  	for _, frame := range frames {
   317  		if frame.fn.Synthetic == "package initializer" {
   318  			c.initFuncs = append(c.initFuncs, frame.fn.LLVMFn)
   319  		}
   320  		if frame.fn.CName() != "" {
   321  			continue
   322  		}
   323  		if frame.fn.Blocks == nil {
   324  			continue // external function
   325  		}
   326  		err := c.parseFunc(frame)
   327  		if err != nil {
   328  			return err
   329  		}
   330  	}
   331  
   332  	// Define the already declared functions that wrap methods for use in
   333  	// interfaces.
   334  	for _, state := range c.interfaceInvokeWrappers {
   335  		err = c.createInterfaceInvokeWrapper(state)
   336  		if err != nil {
   337  			return err
   338  		}
   339  	}
   340  
   341  	// After all packages are imported, add a synthetic initializer function
   342  	// that calls the initializer of each package.
   343  	initFn := c.ir.GetFunction(c.ir.Program.ImportedPackage("runtime").Members["initAll"].(*ssa.Function))
   344  	initFn.LLVMFn.SetLinkage(llvm.InternalLinkage)
   345  	initFn.LLVMFn.SetUnnamedAddr(true)
   346  	if c.Debug {
   347  		difunc, err := c.attachDebugInfo(initFn)
   348  		if err != nil {
   349  			return err
   350  		}
   351  		pos := c.ir.Program.Fset.Position(initFn.Pos())
   352  		c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
   353  	}
   354  	block := c.ctx.AddBasicBlock(initFn.LLVMFn, "entry")
   355  	c.builder.SetInsertPointAtEnd(block)
   356  	for _, fn := range c.initFuncs {
   357  		c.builder.CreateCall(fn, []llvm.Value{llvm.Undef(c.i8ptrType), llvm.Undef(c.i8ptrType)}, "")
   358  	}
   359  	c.builder.CreateRetVoid()
   360  
   361  	// Conserve for goroutine lowering. Without marking these as external, they
   362  	// would be optimized away.
   363  	realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main")
   364  	realMain.SetLinkage(llvm.ExternalLinkage) // keep alive until goroutine lowering
   365  	c.mod.NamedFunction("runtime.alloc").SetLinkage(llvm.ExternalLinkage)
   366  	c.mod.NamedFunction("runtime.free").SetLinkage(llvm.ExternalLinkage)
   367  	c.mod.NamedFunction("runtime.chanSend").SetLinkage(llvm.ExternalLinkage)
   368  	c.mod.NamedFunction("runtime.chanRecv").SetLinkage(llvm.ExternalLinkage)
   369  	c.mod.NamedFunction("runtime.sleepTask").SetLinkage(llvm.ExternalLinkage)
   370  	c.mod.NamedFunction("runtime.activateTask").SetLinkage(llvm.ExternalLinkage)
   371  	c.mod.NamedFunction("runtime.scheduler").SetLinkage(llvm.ExternalLinkage)
   372  
   373  	// Load some attributes
   374  	getAttr := func(attrName string) llvm.Attribute {
   375  		attrKind := llvm.AttributeKindID(attrName)
   376  		return c.ctx.CreateEnumAttribute(attrKind, 0)
   377  	}
   378  	nocapture := getAttr("nocapture")
   379  	writeonly := getAttr("writeonly")
   380  	readonly := getAttr("readonly")
   381  
   382  	// Tell the optimizer that runtime.alloc is an allocator, meaning that it
   383  	// returns values that are never null and never alias to an existing value.
   384  	for _, attrName := range []string{"noalias", "nonnull"} {
   385  		c.mod.NamedFunction("runtime.alloc").AddAttributeAtIndex(0, getAttr(attrName))
   386  	}
   387  
   388  	// See emitNilCheck in asserts.go.
   389  	c.mod.NamedFunction("runtime.isnil").AddAttributeAtIndex(1, nocapture)
   390  
   391  	// Memory copy operations do not capture pointers, even though some weird
   392  	// pointer arithmetic is happening in the Go implementation.
   393  	for _, fnName := range []string{"runtime.memcpy", "runtime.memmove"} {
   394  		fn := c.mod.NamedFunction(fnName)
   395  		fn.AddAttributeAtIndex(1, nocapture)
   396  		fn.AddAttributeAtIndex(1, writeonly)
   397  		fn.AddAttributeAtIndex(2, nocapture)
   398  		fn.AddAttributeAtIndex(2, readonly)
   399  	}
   400  
   401  	// see: https://reviews.llvm.org/D18355
   402  	if c.Debug {
   403  		c.mod.AddNamedMetadataOperand("llvm.module.flags",
   404  			c.ctx.MDNode([]llvm.Metadata{
   405  				llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
   406  				llvm.GlobalContext().MDString("Debug Info Version"),
   407  				llvm.ConstInt(c.ctx.Int32Type(), 3, false).ConstantAsMetadata(), // DWARF version
   408  			}),
   409  		)
   410  		c.dibuilder.Finalize()
   411  	}
   412  
   413  	return nil
   414  }
   415  
   416  func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
   417  	switch typ := goType.(type) {
   418  	case *types.Array:
   419  		elemType, err := c.getLLVMType(typ.Elem())
   420  		if err != nil {
   421  			return llvm.Type{}, err
   422  		}
   423  		return llvm.ArrayType(elemType, int(typ.Len())), nil
   424  	case *types.Basic:
   425  		switch typ.Kind() {
   426  		case types.Bool, types.UntypedBool:
   427  			return c.ctx.Int1Type(), nil
   428  		case types.Int8, types.Uint8:
   429  			return c.ctx.Int8Type(), nil
   430  		case types.Int16, types.Uint16:
   431  			return c.ctx.Int16Type(), nil
   432  		case types.Int32, types.Uint32:
   433  			return c.ctx.Int32Type(), nil
   434  		case types.Int, types.Uint:
   435  			return c.intType, nil
   436  		case types.Int64, types.Uint64:
   437  			return c.ctx.Int64Type(), nil
   438  		case types.Float32:
   439  			return c.ctx.FloatType(), nil
   440  		case types.Float64:
   441  			return c.ctx.DoubleType(), nil
   442  		case types.Complex64:
   443  			return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false), nil
   444  		case types.Complex128:
   445  			return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false), nil
   446  		case types.String, types.UntypedString:
   447  			return c.mod.GetTypeByName("runtime._string"), nil
   448  		case types.Uintptr:
   449  			return c.uintptrType, nil
   450  		case types.UnsafePointer:
   451  			return c.i8ptrType, nil
   452  		default:
   453  			return llvm.Type{}, errors.New("todo: unknown basic type: " + typ.String())
   454  		}
   455  	case *types.Chan:
   456  		return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0), nil
   457  	case *types.Interface:
   458  		return c.mod.GetTypeByName("runtime._interface"), nil
   459  	case *types.Map:
   460  		return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0), nil
   461  	case *types.Named:
   462  		if _, ok := typ.Underlying().(*types.Struct); ok {
   463  			llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
   464  			if llvmType.IsNil() {
   465  				return llvm.Type{}, errors.New("type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
   466  			}
   467  			return llvmType, nil
   468  		}
   469  		return c.getLLVMType(typ.Underlying())
   470  	case *types.Pointer:
   471  		ptrTo, err := c.getLLVMType(typ.Elem())
   472  		if err != nil {
   473  			return llvm.Type{}, err
   474  		}
   475  		return llvm.PointerType(ptrTo, 0), nil
   476  	case *types.Signature: // function value
   477  		return c.getFuncType(typ)
   478  	case *types.Slice:
   479  		elemType, err := c.getLLVMType(typ.Elem())
   480  		if err != nil {
   481  			return llvm.Type{}, err
   482  		}
   483  		members := []llvm.Type{
   484  			llvm.PointerType(elemType, 0),
   485  			c.uintptrType, // len
   486  			c.uintptrType, // cap
   487  		}
   488  		return c.ctx.StructType(members, false), nil
   489  	case *types.Struct:
   490  		members := make([]llvm.Type, typ.NumFields())
   491  		for i := 0; i < typ.NumFields(); i++ {
   492  			member, err := c.getLLVMType(typ.Field(i).Type())
   493  			if err != nil {
   494  				return llvm.Type{}, err
   495  			}
   496  			members[i] = member
   497  		}
   498  		if len(members) > 2 && typ.Field(0).Name() == "C union" {
   499  			// Not a normal struct but a C union emitted by cgo.
   500  			// Such a field name cannot be entered in regular Go code, this must
   501  			// be manually inserted in the AST so this is safe.
   502  			maxAlign := 0
   503  			maxSize := uint64(0)
   504  			mainType := members[0]
   505  			for _, member := range members {
   506  				align := c.targetData.ABITypeAlignment(member)
   507  				size := c.targetData.TypeAllocSize(member)
   508  				if align > maxAlign {
   509  					maxAlign = align
   510  					mainType = member
   511  				} else if align == maxAlign && size > maxSize {
   512  					maxAlign = align
   513  					maxSize = size
   514  					mainType = member
   515  				} else if size > maxSize {
   516  					maxSize = size
   517  				}
   518  			}
   519  			members = []llvm.Type{mainType}
   520  			mainTypeSize := c.targetData.TypeAllocSize(mainType)
   521  			if mainTypeSize < maxSize {
   522  				members = append(members, llvm.ArrayType(c.ctx.Int8Type(), int(maxSize-mainTypeSize)))
   523  			}
   524  		}
   525  		return c.ctx.StructType(members, false), nil
   526  	case *types.Tuple:
   527  		members := make([]llvm.Type, typ.Len())
   528  		for i := 0; i < typ.Len(); i++ {
   529  			member, err := c.getLLVMType(typ.At(i).Type())
   530  			if err != nil {
   531  				return llvm.Type{}, err
   532  			}
   533  			members[i] = member
   534  		}
   535  		return c.ctx.StructType(members, false), nil
   536  	default:
   537  		return llvm.Type{}, errors.New("todo: unknown type: " + goType.String())
   538  	}
   539  }
   540  
   541  // Return a zero LLVM value for any LLVM type. Setting this value as an
   542  // initializer has the same effect as setting 'zeroinitializer' on a value.
   543  // Sadly, I haven't found a way to do it directly with the Go API but this works
   544  // just fine.
   545  func (c *Compiler) getZeroValue(typ llvm.Type) (llvm.Value, error) {
   546  	switch typ.TypeKind() {
   547  	case llvm.ArrayTypeKind:
   548  		subTyp := typ.ElementType()
   549  		subVal, err := c.getZeroValue(subTyp)
   550  		if err != nil {
   551  			return llvm.Value{}, err
   552  		}
   553  		vals := make([]llvm.Value, typ.ArrayLength())
   554  		for i := range vals {
   555  			vals[i] = subVal
   556  		}
   557  		return llvm.ConstArray(subTyp, vals), nil
   558  	case llvm.FloatTypeKind, llvm.DoubleTypeKind:
   559  		return llvm.ConstFloat(typ, 0.0), nil
   560  	case llvm.IntegerTypeKind:
   561  		return llvm.ConstInt(typ, 0, false), nil
   562  	case llvm.PointerTypeKind:
   563  		return llvm.ConstPointerNull(typ), nil
   564  	case llvm.StructTypeKind:
   565  		types := typ.StructElementTypes()
   566  		vals := make([]llvm.Value, len(types))
   567  		for i, subTyp := range types {
   568  			val, err := c.getZeroValue(subTyp)
   569  			if err != nil {
   570  				return llvm.Value{}, err
   571  			}
   572  			vals[i] = val
   573  		}
   574  		if typ.StructName() != "" {
   575  			return llvm.ConstNamedStruct(typ, vals), nil
   576  		} else {
   577  			return c.ctx.ConstStruct(vals, false), nil
   578  		}
   579  	default:
   580  		return llvm.Value{}, errors.New("todo: LLVM zero initializer: " + typ.String())
   581  	}
   582  }
   583  
   584  // Is this a pointer type of some sort? Can be unsafe.Pointer or any *T pointer.
   585  func isPointer(typ types.Type) bool {
   586  	if _, ok := typ.(*types.Pointer); ok {
   587  		return true
   588  	} else if typ, ok := typ.(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
   589  		return true
   590  	} else {
   591  		return false
   592  	}
   593  }
   594  
   595  // Get the DWARF type for this Go type.
   596  func (c *Compiler) getDIType(typ types.Type) (llvm.Metadata, error) {
   597  	name := typ.String()
   598  	if dityp, ok := c.ditypes[name]; ok {
   599  		return dityp, nil
   600  	} else {
   601  		llvmType, err := c.getLLVMType(typ)
   602  		if err != nil {
   603  			return llvm.Metadata{}, err
   604  		}
   605  		sizeInBytes := c.targetData.TypeAllocSize(llvmType)
   606  		var encoding llvm.DwarfTypeEncoding
   607  		switch typ := typ.(type) {
   608  		case *types.Basic:
   609  			if typ.Info()&types.IsBoolean != 0 {
   610  				encoding = llvm.DW_ATE_boolean
   611  			} else if typ.Info()&types.IsFloat != 0 {
   612  				encoding = llvm.DW_ATE_float
   613  			} else if typ.Info()&types.IsComplex != 0 {
   614  				encoding = llvm.DW_ATE_complex_float
   615  			} else if typ.Info()&types.IsUnsigned != 0 {
   616  				encoding = llvm.DW_ATE_unsigned
   617  			} else if typ.Info()&types.IsInteger != 0 {
   618  				encoding = llvm.DW_ATE_signed
   619  			} else if typ.Kind() == types.UnsafePointer {
   620  				encoding = llvm.DW_ATE_address
   621  			}
   622  		case *types.Pointer:
   623  			encoding = llvm.DW_ATE_address
   624  		}
   625  		// TODO: other types
   626  		dityp = c.dibuilder.CreateBasicType(llvm.DIBasicType{
   627  			Name:       name,
   628  			SizeInBits: sizeInBytes * 8,
   629  			Encoding:   encoding,
   630  		})
   631  		c.ditypes[name] = dityp
   632  		return dityp, nil
   633  	}
   634  }
   635  
   636  func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
   637  	frame := &Frame{
   638  		fn:           f,
   639  		locals:       make(map[ssa.Value]llvm.Value),
   640  		blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock),
   641  		blockExits:   make(map[*ssa.BasicBlock]llvm.BasicBlock),
   642  	}
   643  
   644  	var retType llvm.Type
   645  	if f.Signature.Results() == nil {
   646  		retType = c.ctx.VoidType()
   647  	} else if f.Signature.Results().Len() == 1 {
   648  		var err error
   649  		retType, err = c.getLLVMType(f.Signature.Results().At(0).Type())
   650  		if err != nil {
   651  			return nil, err
   652  		}
   653  	} else {
   654  		results := make([]llvm.Type, 0, f.Signature.Results().Len())
   655  		for i := 0; i < f.Signature.Results().Len(); i++ {
   656  			typ, err := c.getLLVMType(f.Signature.Results().At(i).Type())
   657  			if err != nil {
   658  				return nil, err
   659  			}
   660  			results = append(results, typ)
   661  		}
   662  		retType = c.ctx.StructType(results, false)
   663  	}
   664  
   665  	var paramTypes []llvm.Type
   666  	for _, param := range f.Params {
   667  		paramType, err := c.getLLVMType(param.Type())
   668  		if err != nil {
   669  			return nil, err
   670  		}
   671  		paramTypeFragments := c.expandFormalParamType(paramType)
   672  		paramTypes = append(paramTypes, paramTypeFragments...)
   673  	}
   674  
   675  	// Add an extra parameter as the function context. This context is used in
   676  	// closures and bound methods, but should be optimized away when not used.
   677  	if !f.IsExported() {
   678  		paramTypes = append(paramTypes, c.i8ptrType) // context
   679  		paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine
   680  	}
   681  
   682  	fnType := llvm.FunctionType(retType, paramTypes, false)
   683  
   684  	name := f.LinkName()
   685  	frame.fn.LLVMFn = c.mod.NamedFunction(name)
   686  	if frame.fn.LLVMFn.IsNil() {
   687  		frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType)
   688  	}
   689  
   690  	return frame, nil
   691  }
   692  
   693  func (c *Compiler) attachDebugInfo(f *ir.Function) (llvm.Metadata, error) {
   694  	pos := c.ir.Program.Fset.Position(f.Syntax().Pos())
   695  	return c.attachDebugInfoRaw(f, f.LLVMFn, "", pos.Filename, pos.Line)
   696  }
   697  
   698  func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, filename string, line int) (llvm.Metadata, error) {
   699  	if _, ok := c.difiles[filename]; !ok {
   700  		dir, file := filepath.Split(filename)
   701  		if dir != "" {
   702  			dir = dir[:len(dir)-1]
   703  		}
   704  		c.difiles[filename] = c.dibuilder.CreateFile(file, dir)
   705  	}
   706  
   707  	// Debug info for this function.
   708  	diparams := make([]llvm.Metadata, 0, len(f.Params))
   709  	for _, param := range f.Params {
   710  		ditype, err := c.getDIType(param.Type())
   711  		if err != nil {
   712  			return llvm.Metadata{}, err
   713  		}
   714  		diparams = append(diparams, ditype)
   715  	}
   716  	diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
   717  		File:       c.difiles[filename],
   718  		Parameters: diparams,
   719  		Flags:      0, // ?
   720  	})
   721  	difunc := c.dibuilder.CreateFunction(c.difiles[filename], llvm.DIFunction{
   722  		Name:         f.RelString(nil) + suffix,
   723  		LinkageName:  f.LinkName() + suffix,
   724  		File:         c.difiles[filename],
   725  		Line:         line,
   726  		Type:         diFuncType,
   727  		LocalToUnit:  true,
   728  		IsDefinition: true,
   729  		ScopeLine:    0,
   730  		Flags:        llvm.FlagPrototyped,
   731  		Optimized:    true,
   732  	})
   733  	llvmFn.SetSubprogram(difunc)
   734  	return difunc, nil
   735  }
   736  
   737  func (c *Compiler) parseFunc(frame *Frame) error {
   738  	if c.DumpSSA {
   739  		fmt.Printf("\nfunc %s:\n", frame.fn.Function)
   740  	}
   741  	if !frame.fn.IsExported() {
   742  		frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage)
   743  		frame.fn.LLVMFn.SetUnnamedAddr(true)
   744  	}
   745  	if frame.fn.IsInterrupt() && strings.HasPrefix(c.Triple, "avr") {
   746  		frame.fn.LLVMFn.SetFunctionCallConv(85) // CallingConv::AVR_SIGNAL
   747  	}
   748  
   749  	// Add debug info, if needed.
   750  	if c.Debug {
   751  		if frame.fn.Synthetic == "package initializer" {
   752  			// Package initializers have no debug info. Create some fake debug
   753  			// info to at least have *something*.
   754  			difunc, err := c.attachDebugInfoRaw(frame.fn, frame.fn.LLVMFn, "", "", 0)
   755  			if err != nil {
   756  				return err
   757  			}
   758  			frame.difunc = difunc
   759  		} else if frame.fn.Syntax() != nil {
   760  			// Create debug info file if needed.
   761  			difunc, err := c.attachDebugInfo(frame.fn)
   762  			if err != nil {
   763  				return err
   764  			}
   765  			frame.difunc = difunc
   766  		}
   767  		pos := c.ir.Program.Fset.Position(frame.fn.Pos())
   768  		c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
   769  	}
   770  
   771  	// Pre-create all basic blocks in the function.
   772  	for _, block := range frame.fn.DomPreorder() {
   773  		llvmBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, block.Comment)
   774  		frame.blockEntries[block] = llvmBlock
   775  		frame.blockExits[block] = llvmBlock
   776  	}
   777  	entryBlock := frame.blockEntries[frame.fn.Blocks[0]]
   778  	c.builder.SetInsertPointAtEnd(entryBlock)
   779  
   780  	// Load function parameters
   781  	llvmParamIndex := 0
   782  	for i, param := range frame.fn.Params {
   783  		llvmType, err := c.getLLVMType(param.Type())
   784  		if err != nil {
   785  			return err
   786  		}
   787  		fields := make([]llvm.Value, 0, 1)
   788  		for range c.expandFormalParamType(llvmType) {
   789  			fields = append(fields, frame.fn.LLVMFn.Param(llvmParamIndex))
   790  			llvmParamIndex++
   791  		}
   792  		frame.locals[param] = c.collapseFormalParam(llvmType, fields)
   793  
   794  		// Add debug information to this parameter (if available)
   795  		if c.Debug && frame.fn.Syntax() != nil {
   796  			pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
   797  			dityp, err := c.getDIType(param.Type())
   798  			if err != nil {
   799  				return err
   800  			}
   801  			c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{
   802  				Name:           param.Name(),
   803  				File:           c.difiles[pos.Filename],
   804  				Line:           pos.Line,
   805  				Type:           dityp,
   806  				AlwaysPreserve: true,
   807  				ArgNo:          i + 1,
   808  			})
   809  			// TODO: set the value of this parameter.
   810  		}
   811  	}
   812  
   813  	// Load free variables from the context. This is a closure (or bound
   814  	// method).
   815  	var context llvm.Value
   816  	if !frame.fn.IsExported() {
   817  		parentHandle := frame.fn.LLVMFn.LastParam()
   818  		parentHandle.SetName("parentHandle")
   819  		context = llvm.PrevParam(parentHandle)
   820  		context.SetName("context")
   821  	}
   822  	if len(frame.fn.FreeVars) != 0 {
   823  		// Determine the context type. It's a struct containing all variables.
   824  		freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars))
   825  		for _, freeVar := range frame.fn.FreeVars {
   826  			typ, err := c.getLLVMType(freeVar.Type())
   827  			if err != nil {
   828  				return err
   829  			}
   830  			freeVarTypes = append(freeVarTypes, typ)
   831  		}
   832  		contextType := c.ctx.StructType(freeVarTypes, false)
   833  
   834  		// Get a correctly-typed pointer to the context.
   835  		contextAlloc := llvm.Value{}
   836  		if c.targetData.TypeAllocSize(contextType) <= c.targetData.TypeAllocSize(c.i8ptrType) {
   837  			// Context stored directly in pointer. Load it using an alloca.
   838  			contextRawAlloc := c.builder.CreateAlloca(llvm.PointerType(c.i8ptrType, 0), "context.raw.alloc")
   839  			contextRawValue := c.builder.CreateBitCast(context, llvm.PointerType(c.i8ptrType, 0), "context.raw.value")
   840  			c.builder.CreateStore(contextRawValue, contextRawAlloc)
   841  			contextAlloc = c.builder.CreateBitCast(contextRawAlloc, llvm.PointerType(contextType, 0), "context.alloc")
   842  		} else {
   843  			// Context stored in the heap. Bitcast the passed-in pointer to the
   844  			// correct pointer type.
   845  			contextAlloc = c.builder.CreateBitCast(context, llvm.PointerType(contextType, 0), "context.raw.ptr")
   846  		}
   847  
   848  		// Load each free variable from the context.
   849  		// A free variable is always a pointer when this is a closure, but it
   850  		// can be another type when it is a wrapper for a bound method (these
   851  		// wrappers are generated by the ssa package).
   852  		for i, freeVar := range frame.fn.FreeVars {
   853  			indices := []llvm.Value{
   854  				llvm.ConstInt(c.ctx.Int32Type(), 0, false),
   855  				llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false),
   856  			}
   857  			gep := c.builder.CreateInBoundsGEP(contextAlloc, indices, "")
   858  			frame.locals[freeVar] = c.builder.CreateLoad(gep, "")
   859  		}
   860  	}
   861  
   862  	if frame.fn.Recover != nil {
   863  		// This function has deferred function calls. Set some things up for
   864  		// them.
   865  		c.deferInitFunc(frame)
   866  	}
   867  
   868  	// Fill blocks with instructions.
   869  	for _, block := range frame.fn.DomPreorder() {
   870  		if c.DumpSSA {
   871  			fmt.Printf("%d: %s:\n", block.Index, block.Comment)
   872  		}
   873  		c.builder.SetInsertPointAtEnd(frame.blockEntries[block])
   874  		frame.currentBlock = block
   875  		for _, instr := range block.Instrs {
   876  			if _, ok := instr.(*ssa.DebugRef); ok {
   877  				continue
   878  			}
   879  			if c.DumpSSA {
   880  				if val, ok := instr.(ssa.Value); ok && val.Name() != "" {
   881  					fmt.Printf("\t%s = %s\n", val.Name(), val.String())
   882  				} else {
   883  					fmt.Printf("\t%s\n", instr.String())
   884  				}
   885  			}
   886  			err := c.parseInstr(frame, instr)
   887  			if err != nil {
   888  				return err
   889  			}
   890  		}
   891  		if frame.fn.Name() == "init" && len(block.Instrs) == 0 {
   892  			c.builder.CreateRetVoid()
   893  		}
   894  	}
   895  
   896  	// Resolve phi nodes
   897  	for _, phi := range frame.phis {
   898  		block := phi.ssa.Block()
   899  		for i, edge := range phi.ssa.Edges {
   900  			llvmVal, err := c.parseExpr(frame, edge)
   901  			if err != nil {
   902  				return err
   903  			}
   904  			llvmBlock := frame.blockExits[block.Preds[i]]
   905  			phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
   906  		}
   907  	}
   908  
   909  	return nil
   910  }
   911  
   912  func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
   913  	if c.Debug {
   914  		pos := c.ir.Program.Fset.Position(instr.Pos())
   915  		c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
   916  	}
   917  
   918  	switch instr := instr.(type) {
   919  	case ssa.Value:
   920  		value, err := c.parseExpr(frame, instr)
   921  		frame.locals[instr] = value
   922  		return err
   923  	case *ssa.DebugRef:
   924  		return nil // ignore
   925  	case *ssa.Defer:
   926  		return c.emitDefer(frame, instr)
   927  	case *ssa.Go:
   928  		if instr.Call.IsInvoke() {
   929  			return c.makeError(instr.Pos(), "todo: go on method receiver")
   930  		}
   931  		callee := instr.Call.StaticCallee()
   932  		if callee == nil {
   933  			return c.makeError(instr.Pos(), "todo: go on non-direct function (function pointer, etc.)")
   934  		}
   935  		calleeFn := c.ir.GetFunction(callee)
   936  
   937  		// Mark this function as a 'go' invocation and break invalid
   938  		// interprocedural optimizations. For example, heap-to-stack
   939  		// transformations are not sound as goroutines can outlive their parent.
   940  		calleeType := calleeFn.LLVMFn.Type()
   941  		calleeValue := c.builder.CreateBitCast(calleeFn.LLVMFn, c.i8ptrType, "")
   942  		calleeValue = c.createRuntimeCall("makeGoroutine", []llvm.Value{calleeValue}, "")
   943  		calleeValue = c.builder.CreateBitCast(calleeValue, calleeType, "")
   944  
   945  		// Get all function parameters to pass to the goroutine.
   946  		var params []llvm.Value
   947  		for _, param := range instr.Call.Args {
   948  			val, err := c.parseExpr(frame, param)
   949  			if err != nil {
   950  				return err
   951  			}
   952  			params = append(params, val)
   953  		}
   954  		if !calleeFn.IsExported() {
   955  			params = append(params, llvm.Undef(c.i8ptrType)) // context parameter
   956  			params = append(params, llvm.Undef(c.i8ptrType)) // parent coroutine handle
   957  		}
   958  
   959  		c.createCall(calleeValue, params, "")
   960  		return nil
   961  	case *ssa.If:
   962  		cond, err := c.parseExpr(frame, instr.Cond)
   963  		if err != nil {
   964  			return err
   965  		}
   966  		block := instr.Block()
   967  		blockThen := frame.blockEntries[block.Succs[0]]
   968  		blockElse := frame.blockEntries[block.Succs[1]]
   969  		c.builder.CreateCondBr(cond, blockThen, blockElse)
   970  		return nil
   971  	case *ssa.Jump:
   972  		blockJump := frame.blockEntries[instr.Block().Succs[0]]
   973  		c.builder.CreateBr(blockJump)
   974  		return nil
   975  	case *ssa.MapUpdate:
   976  		m, err := c.parseExpr(frame, instr.Map)
   977  		if err != nil {
   978  			return err
   979  		}
   980  		key, err := c.parseExpr(frame, instr.Key)
   981  		if err != nil {
   982  			return err
   983  		}
   984  		value, err := c.parseExpr(frame, instr.Value)
   985  		if err != nil {
   986  			return err
   987  		}
   988  		mapType := instr.Map.Type().Underlying().(*types.Map)
   989  		return c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos())
   990  	case *ssa.Panic:
   991  		value, err := c.parseExpr(frame, instr.X)
   992  		if err != nil {
   993  			return err
   994  		}
   995  		c.createRuntimeCall("_panic", []llvm.Value{value}, "")
   996  		c.builder.CreateUnreachable()
   997  		return nil
   998  	case *ssa.Return:
   999  		if len(instr.Results) == 0 {
  1000  			c.builder.CreateRetVoid()
  1001  			return nil
  1002  		} else if len(instr.Results) == 1 {
  1003  			val, err := c.parseExpr(frame, instr.Results[0])
  1004  			if err != nil {
  1005  				return err
  1006  			}
  1007  			c.builder.CreateRet(val)
  1008  			return nil
  1009  		} else {
  1010  			// Multiple return values. Put them all in a struct.
  1011  			retVal, err := c.getZeroValue(frame.fn.LLVMFn.Type().ElementType().ReturnType())
  1012  			if err != nil {
  1013  				return err
  1014  			}
  1015  			for i, result := range instr.Results {
  1016  				val, err := c.parseExpr(frame, result)
  1017  				if err != nil {
  1018  					return err
  1019  				}
  1020  				retVal = c.builder.CreateInsertValue(retVal, val, i, "")
  1021  			}
  1022  			c.builder.CreateRet(retVal)
  1023  			return nil
  1024  		}
  1025  	case *ssa.RunDefers:
  1026  		return c.emitRunDefers(frame)
  1027  	case *ssa.Send:
  1028  		return c.emitChanSend(frame, instr)
  1029  	case *ssa.Store:
  1030  		llvmAddr, err := c.parseExpr(frame, instr.Addr)
  1031  		if err != nil {
  1032  			return err
  1033  		}
  1034  		llvmVal, err := c.parseExpr(frame, instr.Val)
  1035  		if err != nil {
  1036  			return err
  1037  		}
  1038  		if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 {
  1039  			// nothing to store
  1040  			return nil
  1041  		}
  1042  		store := c.builder.CreateStore(llvmVal, llvmAddr)
  1043  		valType := instr.Addr.Type().Underlying().(*types.Pointer).Elem()
  1044  		if c.ir.IsVolatile(valType) {
  1045  			// Volatile store, for memory-mapped registers.
  1046  			store.SetVolatile(true)
  1047  		}
  1048  		return nil
  1049  	default:
  1050  		return c.makeError(instr.Pos(), "unknown instruction: "+instr.String())
  1051  	}
  1052  }
  1053  
  1054  func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, pos token.Pos) (llvm.Value, error) {
  1055  	switch callName {
  1056  	case "append":
  1057  		src, err := c.parseExpr(frame, args[0])
  1058  		if err != nil {
  1059  			return llvm.Value{}, err
  1060  		}
  1061  		elems, err := c.parseExpr(frame, args[1])
  1062  		if err != nil {
  1063  			return llvm.Value{}, err
  1064  		}
  1065  		srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf")
  1066  		srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr")
  1067  		srcLen := c.builder.CreateExtractValue(src, 1, "append.srcLen")
  1068  		srcCap := c.builder.CreateExtractValue(src, 2, "append.srcCap")
  1069  		elemsBuf := c.builder.CreateExtractValue(elems, 0, "append.elemsBuf")
  1070  		elemsPtr := c.builder.CreateBitCast(elemsBuf, c.i8ptrType, "append.srcPtr")
  1071  		elemsLen := c.builder.CreateExtractValue(elems, 1, "append.elemsLen")
  1072  		elemType := srcBuf.Type().ElementType()
  1073  		elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false)
  1074  		result := c.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new")
  1075  		newPtr := c.builder.CreateExtractValue(result, 0, "append.newPtr")
  1076  		newBuf := c.builder.CreateBitCast(newPtr, srcBuf.Type(), "append.newBuf")
  1077  		newLen := c.builder.CreateExtractValue(result, 1, "append.newLen")
  1078  		newCap := c.builder.CreateExtractValue(result, 2, "append.newCap")
  1079  		newSlice := llvm.Undef(src.Type())
  1080  		newSlice = c.builder.CreateInsertValue(newSlice, newBuf, 0, "")
  1081  		newSlice = c.builder.CreateInsertValue(newSlice, newLen, 1, "")
  1082  		newSlice = c.builder.CreateInsertValue(newSlice, newCap, 2, "")
  1083  		return newSlice, nil
  1084  	case "cap":
  1085  		value, err := c.parseExpr(frame, args[0])
  1086  		if err != nil {
  1087  			return llvm.Value{}, err
  1088  		}
  1089  		var llvmCap llvm.Value
  1090  		switch args[0].Type().(type) {
  1091  		case *types.Chan:
  1092  			// Channel. Buffered channels haven't been implemented yet so always
  1093  			// return 0.
  1094  			llvmCap = llvm.ConstInt(c.intType, 0, false)
  1095  		case *types.Slice:
  1096  			llvmCap = c.builder.CreateExtractValue(value, 2, "cap")
  1097  		default:
  1098  			return llvm.Value{}, c.makeError(pos, "todo: cap: unknown type")
  1099  		}
  1100  		if c.targetData.TypeAllocSize(llvmCap.Type()) < c.targetData.TypeAllocSize(c.intType) {
  1101  			llvmCap = c.builder.CreateZExt(llvmCap, c.intType, "len.int")
  1102  		}
  1103  		return llvmCap, nil
  1104  	case "close":
  1105  		return llvm.Value{}, c.emitChanClose(frame, args[0])
  1106  	case "complex":
  1107  		r, err := c.parseExpr(frame, args[0])
  1108  		if err != nil {
  1109  			return llvm.Value{}, err
  1110  		}
  1111  		i, err := c.parseExpr(frame, args[1])
  1112  		if err != nil {
  1113  			return llvm.Value{}, err
  1114  		}
  1115  		t := args[0].Type().Underlying().(*types.Basic)
  1116  		var cplx llvm.Value
  1117  		switch t.Kind() {
  1118  		case types.Float32:
  1119  			cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
  1120  		case types.Float64:
  1121  			cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
  1122  		default:
  1123  			return llvm.Value{}, c.makeError(pos, "unsupported type in complex builtin: "+t.String())
  1124  		}
  1125  		cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  1126  		cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  1127  		return cplx, nil
  1128  	case "copy":
  1129  		dst, err := c.parseExpr(frame, args[0])
  1130  		if err != nil {
  1131  			return llvm.Value{}, err
  1132  		}
  1133  		src, err := c.parseExpr(frame, args[1])
  1134  		if err != nil {
  1135  			return llvm.Value{}, err
  1136  		}
  1137  		dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen")
  1138  		srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen")
  1139  		dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray")
  1140  		srcBuf := c.builder.CreateExtractValue(src, 0, "copy.srcArray")
  1141  		elemType := dstBuf.Type().ElementType()
  1142  		dstBuf = c.builder.CreateBitCast(dstBuf, c.i8ptrType, "copy.dstPtr")
  1143  		srcBuf = c.builder.CreateBitCast(srcBuf, c.i8ptrType, "copy.srcPtr")
  1144  		elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false)
  1145  		return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
  1146  	case "delete":
  1147  		m, err := c.parseExpr(frame, args[0])
  1148  		if err != nil {
  1149  			return llvm.Value{}, err
  1150  		}
  1151  		key, err := c.parseExpr(frame, args[1])
  1152  		if err != nil {
  1153  			return llvm.Value{}, err
  1154  		}
  1155  		return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos)
  1156  	case "imag":
  1157  		cplx, err := c.parseExpr(frame, args[0])
  1158  		if err != nil {
  1159  			return llvm.Value{}, err
  1160  		}
  1161  		return c.builder.CreateExtractValue(cplx, 1, "imag"), nil
  1162  	case "len":
  1163  		value, err := c.parseExpr(frame, args[0])
  1164  		if err != nil {
  1165  			return llvm.Value{}, err
  1166  		}
  1167  		var llvmLen llvm.Value
  1168  		switch args[0].Type().Underlying().(type) {
  1169  		case *types.Basic, *types.Slice:
  1170  			// string or slice
  1171  			llvmLen = c.builder.CreateExtractValue(value, 1, "len")
  1172  		case *types.Chan:
  1173  			// Channel. Buffered channels haven't been implemented yet so always
  1174  			// return 0.
  1175  			llvmLen = llvm.ConstInt(c.intType, 0, false)
  1176  		case *types.Map:
  1177  			llvmLen = c.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len")
  1178  		default:
  1179  			return llvm.Value{}, c.makeError(pos, "todo: len: unknown type")
  1180  		}
  1181  		if c.targetData.TypeAllocSize(llvmLen.Type()) < c.targetData.TypeAllocSize(c.intType) {
  1182  			llvmLen = c.builder.CreateZExt(llvmLen, c.intType, "len.int")
  1183  		}
  1184  		return llvmLen, nil
  1185  	case "print", "println":
  1186  		for i, arg := range args {
  1187  			if i >= 1 && callName == "println" {
  1188  				c.createRuntimeCall("printspace", nil, "")
  1189  			}
  1190  			value, err := c.parseExpr(frame, arg)
  1191  			if err != nil {
  1192  				return llvm.Value{}, err
  1193  			}
  1194  			typ := arg.Type().Underlying()
  1195  			switch typ := typ.(type) {
  1196  			case *types.Basic:
  1197  				switch typ.Kind() {
  1198  				case types.String, types.UntypedString:
  1199  					c.createRuntimeCall("printstring", []llvm.Value{value}, "")
  1200  				case types.Uintptr:
  1201  					c.createRuntimeCall("printptr", []llvm.Value{value}, "")
  1202  				case types.UnsafePointer:
  1203  					ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "")
  1204  					c.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "")
  1205  				default:
  1206  					// runtime.print{int,uint}{8,16,32,64}
  1207  					if typ.Info()&types.IsInteger != 0 {
  1208  						name := "print"
  1209  						if typ.Info()&types.IsUnsigned != 0 {
  1210  							name += "uint"
  1211  						} else {
  1212  							name += "int"
  1213  						}
  1214  						name += strconv.FormatUint(c.targetData.TypeAllocSize(value.Type())*8, 10)
  1215  						c.createRuntimeCall(name, []llvm.Value{value}, "")
  1216  					} else if typ.Kind() == types.Bool {
  1217  						c.createRuntimeCall("printbool", []llvm.Value{value}, "")
  1218  					} else if typ.Kind() == types.Float32 {
  1219  						c.createRuntimeCall("printfloat32", []llvm.Value{value}, "")
  1220  					} else if typ.Kind() == types.Float64 {
  1221  						c.createRuntimeCall("printfloat64", []llvm.Value{value}, "")
  1222  					} else if typ.Kind() == types.Complex64 {
  1223  						c.createRuntimeCall("printcomplex64", []llvm.Value{value}, "")
  1224  					} else if typ.Kind() == types.Complex128 {
  1225  						c.createRuntimeCall("printcomplex128", []llvm.Value{value}, "")
  1226  					} else {
  1227  						return llvm.Value{}, c.makeError(pos, "unknown basic arg type: "+typ.String())
  1228  					}
  1229  				}
  1230  			case *types.Interface:
  1231  				c.createRuntimeCall("printitf", []llvm.Value{value}, "")
  1232  			case *types.Map:
  1233  				c.createRuntimeCall("printmap", []llvm.Value{value}, "")
  1234  			case *types.Pointer:
  1235  				ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "")
  1236  				c.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "")
  1237  			default:
  1238  				return llvm.Value{}, c.makeError(pos, "unknown arg type: "+typ.String())
  1239  			}
  1240  		}
  1241  		if callName == "println" {
  1242  			c.createRuntimeCall("printnl", nil, "")
  1243  		}
  1244  		return llvm.Value{}, nil // print() or println() returns void
  1245  	case "real":
  1246  		cplx, err := c.parseExpr(frame, args[0])
  1247  		if err != nil {
  1248  			return llvm.Value{}, err
  1249  		}
  1250  		return c.builder.CreateExtractValue(cplx, 0, "real"), nil
  1251  	case "recover":
  1252  		return c.createRuntimeCall("_recover", nil, ""), nil
  1253  	case "ssa:wrapnilchk":
  1254  		// TODO: do an actual nil check?
  1255  		return c.parseExpr(frame, args[0])
  1256  	default:
  1257  		return llvm.Value{}, c.makeError(pos, "todo: builtin: "+callName)
  1258  	}
  1259  }
  1260  
  1261  func (c *Compiler) parseFunctionCall(frame *Frame, args []ssa.Value, llvmFn, context llvm.Value, exported bool) (llvm.Value, error) {
  1262  	var params []llvm.Value
  1263  	for _, param := range args {
  1264  		val, err := c.parseExpr(frame, param)
  1265  		if err != nil {
  1266  			return llvm.Value{}, err
  1267  		}
  1268  		params = append(params, val)
  1269  	}
  1270  
  1271  	if !exported {
  1272  		// This function takes a context parameter.
  1273  		// Add it to the end of the parameter list.
  1274  		params = append(params, context)
  1275  
  1276  		// Parent coroutine handle.
  1277  		params = append(params, llvm.Undef(c.i8ptrType))
  1278  	}
  1279  
  1280  	return c.createCall(llvmFn, params, ""), nil
  1281  }
  1282  
  1283  func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
  1284  	if instr.IsInvoke() {
  1285  		fnCast, args, err := c.getInvokeCall(frame, instr)
  1286  		if err != nil {
  1287  			return llvm.Value{}, err
  1288  		}
  1289  		return c.createCall(fnCast, args, ""), nil
  1290  	}
  1291  
  1292  	// Try to call the function directly for trivially static calls.
  1293  	if fn := instr.StaticCallee(); fn != nil {
  1294  		switch fn.RelString(nil) {
  1295  		case "device/arm.ReadRegister":
  1296  			return c.emitReadRegister(instr.Args)
  1297  		case "device/arm.Asm", "device/avr.Asm":
  1298  			return c.emitAsm(instr.Args)
  1299  		case "device/arm.AsmFull", "device/avr.AsmFull":
  1300  			return c.emitAsmFull(frame, instr)
  1301  		case "device/arm.SVCall0", "device/arm.SVCall1", "device/arm.SVCall2", "device/arm.SVCall3", "device/arm.SVCall4":
  1302  			return c.emitSVCall(frame, instr.Args)
  1303  		case "syscall.Syscall", "syscall.Syscall6", "syscall.Syscall9":
  1304  			return c.emitSyscall(frame, instr)
  1305  		}
  1306  
  1307  		targetFunc := c.ir.GetFunction(fn)
  1308  		if targetFunc.LLVMFn.IsNil() {
  1309  			return llvm.Value{}, c.makeError(instr.Pos(), "undefined function: "+targetFunc.LinkName())
  1310  		}
  1311  		var context llvm.Value
  1312  		switch value := instr.Value.(type) {
  1313  		case *ssa.Function:
  1314  			// Regular function call. No context is necessary.
  1315  			context = llvm.Undef(c.i8ptrType)
  1316  		case *ssa.MakeClosure:
  1317  			// A call on a func value, but the callee is trivial to find. For
  1318  			// example: immediately applied functions.
  1319  			funcValue, err := c.parseExpr(frame, value)
  1320  			if err != nil {
  1321  				return llvm.Value{}, err
  1322  			}
  1323  			context = c.extractFuncContext(funcValue)
  1324  		default:
  1325  			panic("StaticCallee returned an unexpected value")
  1326  		}
  1327  		return c.parseFunctionCall(frame, instr.Args, targetFunc.LLVMFn, context, targetFunc.IsExported())
  1328  	}
  1329  
  1330  	// Builtin or function pointer.
  1331  	switch call := instr.Value.(type) {
  1332  	case *ssa.Builtin:
  1333  		return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos())
  1334  	default: // function pointer
  1335  		value, err := c.parseExpr(frame, instr.Value)
  1336  		if err != nil {
  1337  			return llvm.Value{}, err
  1338  		}
  1339  		// This is a func value, which cannot be called directly. We have to
  1340  		// extract the function pointer and context first from the func value.
  1341  		funcPtr, context, err := c.decodeFuncValue(value, instr.Value.Type().(*types.Signature))
  1342  		if err != nil {
  1343  			return llvm.Value{}, err
  1344  		}
  1345  		c.emitNilCheck(frame, funcPtr, "fpcall")
  1346  		return c.parseFunctionCall(frame, instr.Args, funcPtr, context, false)
  1347  	}
  1348  }
  1349  
  1350  func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
  1351  	if value, ok := frame.locals[expr]; ok {
  1352  		// Value is a local variable that has already been computed.
  1353  		if value.IsNil() {
  1354  			return llvm.Value{}, c.makeError(expr.Pos(), "undefined local var (from cgo?)")
  1355  		}
  1356  		return value, nil
  1357  	}
  1358  
  1359  	switch expr := expr.(type) {
  1360  	case *ssa.Alloc:
  1361  		typ, err := c.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
  1362  		if err != nil {
  1363  			return llvm.Value{}, err
  1364  		}
  1365  		var buf llvm.Value
  1366  		if expr.Heap {
  1367  			size := c.targetData.TypeAllocSize(typ)
  1368  			// Calculate ^uintptr(0)
  1369  			maxSize := llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)).ZExtValue()
  1370  			if size > maxSize {
  1371  				// Size would be truncated if truncated to uintptr.
  1372  				return llvm.Value{}, c.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size))
  1373  			}
  1374  			// TODO: escape analysis
  1375  			sizeValue := llvm.ConstInt(c.uintptrType, size, false)
  1376  			buf = c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, expr.Comment)
  1377  			buf = c.builder.CreateBitCast(buf, llvm.PointerType(typ, 0), "")
  1378  		} else {
  1379  			buf = c.builder.CreateAlloca(typ, expr.Comment)
  1380  			if c.targetData.TypeAllocSize(typ) != 0 {
  1381  				zero, err := c.getZeroValue(typ)
  1382  				if err != nil {
  1383  					return llvm.Value{}, err
  1384  				}
  1385  				c.builder.CreateStore(zero, buf) // zero-initialize var
  1386  			}
  1387  		}
  1388  		return buf, nil
  1389  	case *ssa.BinOp:
  1390  		x, err := c.parseExpr(frame, expr.X)
  1391  		if err != nil {
  1392  			return llvm.Value{}, err
  1393  		}
  1394  		y, err := c.parseExpr(frame, expr.Y)
  1395  		if err != nil {
  1396  			return llvm.Value{}, err
  1397  		}
  1398  		return c.parseBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos())
  1399  	case *ssa.Call:
  1400  		// Passing the current task here to the subroutine. It is only used when
  1401  		// the subroutine is blocking.
  1402  		return c.parseCall(frame, expr.Common())
  1403  	case *ssa.ChangeInterface:
  1404  		// Do not change between interface types: always use the underlying
  1405  		// (concrete) type in the type number of the interface. Every method
  1406  		// call on an interface will do a lookup which method to call.
  1407  		// This is different from how the official Go compiler works, because of
  1408  		// heap allocation and because it's easier to implement, see:
  1409  		// https://research.swtch.com/interfaces
  1410  		return c.parseExpr(frame, expr.X)
  1411  	case *ssa.ChangeType:
  1412  		// This instruction changes the type, but the underlying value remains
  1413  		// the same. This is often a no-op, but sometimes we have to change the
  1414  		// LLVM type as well.
  1415  		x, err := c.parseExpr(frame, expr.X)
  1416  		if err != nil {
  1417  			return llvm.Value{}, err
  1418  		}
  1419  		llvmType, err := c.getLLVMType(expr.Type())
  1420  		if err != nil {
  1421  			return llvm.Value{}, err
  1422  		}
  1423  		if x.Type() == llvmType {
  1424  			// Different Go type but same LLVM type (for example, named int).
  1425  			// This is the common case.
  1426  			return x, nil
  1427  		}
  1428  		// Figure out what kind of type we need to cast.
  1429  		switch llvmType.TypeKind() {
  1430  		case llvm.StructTypeKind:
  1431  			// Unfortunately, we can't just bitcast structs. We have to
  1432  			// actually create a new struct of the correct type and insert the
  1433  			// values from the previous struct in there.
  1434  			value := llvm.Undef(llvmType)
  1435  			for i := 0; i < llvmType.StructElementTypesCount(); i++ {
  1436  				field := c.builder.CreateExtractValue(x, i, "changetype.field")
  1437  				value = c.builder.CreateInsertValue(value, field, i, "changetype.struct")
  1438  			}
  1439  			return value, nil
  1440  		case llvm.PointerTypeKind:
  1441  			// This can happen with pointers to structs. This case is easy:
  1442  			// simply bitcast the pointer to the destination type.
  1443  			return c.builder.CreateBitCast(x, llvmType, "changetype.pointer"), nil
  1444  		default:
  1445  			return llvm.Value{}, errors.New("todo: unknown ChangeType type: " + expr.X.Type().String())
  1446  		}
  1447  	case *ssa.Const:
  1448  		return c.parseConst(frame.fn.LinkName(), expr)
  1449  	case *ssa.Convert:
  1450  		x, err := c.parseExpr(frame, expr.X)
  1451  		if err != nil {
  1452  			return llvm.Value{}, err
  1453  		}
  1454  		return c.parseConvert(expr.X.Type(), expr.Type(), x, expr.Pos())
  1455  	case *ssa.Extract:
  1456  		value, err := c.parseExpr(frame, expr.Tuple)
  1457  		if err != nil {
  1458  			return llvm.Value{}, err
  1459  		}
  1460  		result := c.builder.CreateExtractValue(value, expr.Index, "")
  1461  		return result, nil
  1462  	case *ssa.Field:
  1463  		value, err := c.parseExpr(frame, expr.X)
  1464  		if err != nil {
  1465  			return llvm.Value{}, err
  1466  		}
  1467  		if s := expr.X.Type().Underlying().(*types.Struct); s.NumFields() > 2 && s.Field(0).Name() == "C union" {
  1468  			// Extract a field from a CGo union.
  1469  			// This could be done directly, but as this is a very infrequent
  1470  			// operation it's much easier to bitcast it through an alloca.
  1471  			resultType, err := c.getLLVMType(expr.Type())
  1472  			if err != nil {
  1473  				return llvm.Value{}, err
  1474  			}
  1475  			alloca := c.builder.CreateAlloca(value.Type(), "")
  1476  			c.builder.CreateStore(value, alloca)
  1477  			bitcast := c.builder.CreateBitCast(alloca, llvm.PointerType(resultType, 0), "")
  1478  			return c.builder.CreateLoad(bitcast, ""), nil
  1479  		}
  1480  		result := c.builder.CreateExtractValue(value, expr.Field, "")
  1481  		return result, nil
  1482  	case *ssa.FieldAddr:
  1483  		val, err := c.parseExpr(frame, expr.X)
  1484  		if err != nil {
  1485  			return llvm.Value{}, err
  1486  		}
  1487  		// Check for nil pointer before calculating the address, from the spec:
  1488  		// > For an operand x of type T, the address operation &x generates a
  1489  		// > pointer of type *T to x. [...] If the evaluation of x would cause a
  1490  		// > run-time panic, then the evaluation of &x does too.
  1491  		c.emitNilCheck(frame, val, "gep")
  1492  		if s := expr.X.Type().(*types.Pointer).Elem().Underlying().(*types.Struct); s.NumFields() > 2 && s.Field(0).Name() == "C union" {
  1493  			// This is not a regular struct but actually an union.
  1494  			// That simplifies things, as we can just bitcast the pointer to the
  1495  			// right type.
  1496  			ptrType, err := c.getLLVMType(expr.Type())
  1497  			if err != nil {
  1498  				return llvm.Value{}, nil
  1499  			}
  1500  			return c.builder.CreateBitCast(val, ptrType, ""), nil
  1501  		} else {
  1502  			// Do a GEP on the pointer to get the field address.
  1503  			indices := []llvm.Value{
  1504  				llvm.ConstInt(c.ctx.Int32Type(), 0, false),
  1505  				llvm.ConstInt(c.ctx.Int32Type(), uint64(expr.Field), false),
  1506  			}
  1507  			return c.builder.CreateGEP(val, indices, ""), nil
  1508  		}
  1509  	case *ssa.Function:
  1510  		fn := c.ir.GetFunction(expr)
  1511  		if fn.IsExported() {
  1512  			return llvm.Value{}, c.makeError(expr.Pos(), "cannot use an exported function as value")
  1513  		}
  1514  		return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature)
  1515  	case *ssa.Global:
  1516  		value := c.ir.GetGlobal(expr).LLVMGlobal
  1517  		if value.IsNil() {
  1518  			return llvm.Value{}, c.makeError(expr.Pos(), "global not found: "+c.ir.GetGlobal(expr).LinkName())
  1519  		}
  1520  		return value, nil
  1521  	case *ssa.Index:
  1522  		array, err := c.parseExpr(frame, expr.X)
  1523  		if err != nil {
  1524  			return llvm.Value{}, err
  1525  		}
  1526  		index, err := c.parseExpr(frame, expr.Index)
  1527  		if err != nil {
  1528  			return llvm.Value{}, err
  1529  		}
  1530  
  1531  		// Check bounds.
  1532  		arrayLen := expr.X.Type().(*types.Array).Len()
  1533  		arrayLenLLVM := llvm.ConstInt(c.uintptrType, uint64(arrayLen), false)
  1534  		c.emitLookupBoundsCheck(frame, arrayLenLLVM, index, expr.Index.Type())
  1535  
  1536  		// Can't load directly from array (as index is non-constant), so have to
  1537  		// do it using an alloca+gep+load.
  1538  		alloca := c.builder.CreateAlloca(array.Type(), "index.alloca")
  1539  		c.builder.CreateStore(array, alloca)
  1540  		zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
  1541  		ptr := c.builder.CreateGEP(alloca, []llvm.Value{zero, index}, "index.gep")
  1542  		return c.builder.CreateLoad(ptr, "index.load"), nil
  1543  	case *ssa.IndexAddr:
  1544  		val, err := c.parseExpr(frame, expr.X)
  1545  		if err != nil {
  1546  			return llvm.Value{}, err
  1547  		}
  1548  		index, err := c.parseExpr(frame, expr.Index)
  1549  		if err != nil {
  1550  			return llvm.Value{}, err
  1551  		}
  1552  
  1553  		// Get buffer pointer and length
  1554  		var bufptr, buflen llvm.Value
  1555  		switch ptrTyp := expr.X.Type().Underlying().(type) {
  1556  		case *types.Pointer:
  1557  			typ := expr.X.Type().Underlying().(*types.Pointer).Elem().Underlying()
  1558  			switch typ := typ.(type) {
  1559  			case *types.Array:
  1560  				bufptr = val
  1561  				buflen = llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false)
  1562  				// Check for nil pointer before calculating the address, from
  1563  				// the spec:
  1564  				// > For an operand x of type T, the address operation &x
  1565  				// > generates a pointer of type *T to x. [...] If the
  1566  				// > evaluation of x would cause a run-time panic, then the
  1567  				// > evaluation of &x does too.
  1568  				c.emitNilCheck(frame, bufptr, "gep")
  1569  			default:
  1570  				return llvm.Value{}, c.makeError(expr.Pos(), "todo: indexaddr: "+typ.String())
  1571  			}
  1572  		case *types.Slice:
  1573  			bufptr = c.builder.CreateExtractValue(val, 0, "indexaddr.ptr")
  1574  			buflen = c.builder.CreateExtractValue(val, 1, "indexaddr.len")
  1575  		default:
  1576  			return llvm.Value{}, c.makeError(expr.Pos(), "todo: indexaddr: "+ptrTyp.String())
  1577  		}
  1578  
  1579  		// Bounds check.
  1580  		c.emitLookupBoundsCheck(frame, buflen, index, expr.Index.Type())
  1581  
  1582  		switch expr.X.Type().Underlying().(type) {
  1583  		case *types.Pointer:
  1584  			indices := []llvm.Value{
  1585  				llvm.ConstInt(c.ctx.Int32Type(), 0, false),
  1586  				index,
  1587  			}
  1588  			return c.builder.CreateGEP(bufptr, indices, ""), nil
  1589  		case *types.Slice:
  1590  			return c.builder.CreateGEP(bufptr, []llvm.Value{index}, ""), nil
  1591  		default:
  1592  			panic("unreachable")
  1593  		}
  1594  	case *ssa.Lookup:
  1595  		value, err := c.parseExpr(frame, expr.X)
  1596  		if err != nil {
  1597  			return llvm.Value{}, nil
  1598  		}
  1599  		index, err := c.parseExpr(frame, expr.Index)
  1600  		if err != nil {
  1601  			return llvm.Value{}, nil
  1602  		}
  1603  		switch xType := expr.X.Type().Underlying().(type) {
  1604  		case *types.Basic:
  1605  			// Value type must be a string, which is a basic type.
  1606  			if xType.Info()&types.IsString == 0 {
  1607  				panic("lookup on non-string?")
  1608  			}
  1609  
  1610  			// Bounds check.
  1611  			length := c.builder.CreateExtractValue(value, 1, "len")
  1612  			c.emitLookupBoundsCheck(frame, length, index, expr.Index.Type())
  1613  
  1614  			// Lookup byte
  1615  			buf := c.builder.CreateExtractValue(value, 0, "")
  1616  			bufPtr := c.builder.CreateGEP(buf, []llvm.Value{index}, "")
  1617  			return c.builder.CreateLoad(bufPtr, ""), nil
  1618  		case *types.Map:
  1619  			valueType := expr.Type()
  1620  			if expr.CommaOk {
  1621  				valueType = valueType.(*types.Tuple).At(0).Type()
  1622  			}
  1623  			return c.emitMapLookup(xType.Key(), valueType, value, index, expr.CommaOk, expr.Pos())
  1624  		default:
  1625  			panic("unknown lookup type: " + expr.String())
  1626  		}
  1627  	case *ssa.MakeChan:
  1628  		return c.emitMakeChan(expr)
  1629  	case *ssa.MakeClosure:
  1630  		return c.parseMakeClosure(frame, expr)
  1631  	case *ssa.MakeInterface:
  1632  		val, err := c.parseExpr(frame, expr.X)
  1633  		if err != nil {
  1634  			return llvm.Value{}, err
  1635  		}
  1636  		return c.parseMakeInterface(val, expr.X.Type(), expr.Pos())
  1637  	case *ssa.MakeMap:
  1638  		mapType := expr.Type().Underlying().(*types.Map)
  1639  		llvmKeyType, err := c.getLLVMType(mapType.Key().Underlying())
  1640  		if err != nil {
  1641  			return llvm.Value{}, err
  1642  		}
  1643  		llvmValueType, err := c.getLLVMType(mapType.Elem().Underlying())
  1644  		if err != nil {
  1645  			return llvm.Value{}, err
  1646  		}
  1647  		keySize := c.targetData.TypeAllocSize(llvmKeyType)
  1648  		valueSize := c.targetData.TypeAllocSize(llvmValueType)
  1649  		llvmKeySize := llvm.ConstInt(c.ctx.Int8Type(), keySize, false)
  1650  		llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false)
  1651  		hashmap := c.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize}, "")
  1652  		return hashmap, nil
  1653  	case *ssa.MakeSlice:
  1654  		sliceLen, err := c.parseExpr(frame, expr.Len)
  1655  		if err != nil {
  1656  			return llvm.Value{}, nil
  1657  		}
  1658  		sliceCap, err := c.parseExpr(frame, expr.Cap)
  1659  		if err != nil {
  1660  			return llvm.Value{}, nil
  1661  		}
  1662  		sliceType := expr.Type().Underlying().(*types.Slice)
  1663  		llvmElemType, err := c.getLLVMType(sliceType.Elem())
  1664  		if err != nil {
  1665  			return llvm.Value{}, nil
  1666  		}
  1667  		elemSize := c.targetData.TypeAllocSize(llvmElemType)
  1668  		elemSizeValue := llvm.ConstInt(c.uintptrType, elemSize, false)
  1669  
  1670  		// Calculate (^uintptr(0)) >> 1, which is the max value that fits in
  1671  		// uintptr if uintptr were signed.
  1672  		maxSize := llvm.ConstLShr(llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)), llvm.ConstInt(c.uintptrType, 1, false))
  1673  		if elemSize > maxSize.ZExtValue() {
  1674  			// This seems to be checked by the typechecker already, but let's
  1675  			// check it again just to be sure.
  1676  			return llvm.Value{}, c.makeError(expr.Pos(), fmt.Sprintf("slice element type is too big (%v bytes)", elemSize))
  1677  		}
  1678  
  1679  		// Bounds checking.
  1680  		c.emitSliceBoundsCheck(frame, maxSize, sliceLen, sliceCap, expr.Len.Type().(*types.Basic), expr.Cap.Type().(*types.Basic))
  1681  
  1682  		// Allocate the backing array.
  1683  		// TODO: escape analysis
  1684  		sliceCapCast, err := c.parseConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())
  1685  		if err != nil {
  1686  			return llvm.Value{}, err
  1687  		}
  1688  		sliceSize := c.builder.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap")
  1689  		slicePtr := c.createRuntimeCall("alloc", []llvm.Value{sliceSize}, "makeslice.buf")
  1690  		slicePtr = c.builder.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array")
  1691  
  1692  		// Extend or truncate if necessary. This is safe as we've already done
  1693  		// the bounds check.
  1694  		sliceLen, err = c.parseConvert(expr.Len.Type(), types.Typ[types.Uintptr], sliceLen, expr.Pos())
  1695  		if err != nil {
  1696  			return llvm.Value{}, err
  1697  		}
  1698  		sliceCap, err = c.parseConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())
  1699  		if err != nil {
  1700  			return llvm.Value{}, err
  1701  		}
  1702  
  1703  		// Create the slice.
  1704  		slice := c.ctx.ConstStruct([]llvm.Value{
  1705  			llvm.Undef(slicePtr.Type()),
  1706  			llvm.Undef(c.uintptrType),
  1707  			llvm.Undef(c.uintptrType),
  1708  		}, false)
  1709  		slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
  1710  		slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
  1711  		slice = c.builder.CreateInsertValue(slice, sliceCap, 2, "")
  1712  		return slice, nil
  1713  	case *ssa.Next:
  1714  		rangeVal := expr.Iter.(*ssa.Range).X
  1715  		llvmRangeVal, err := c.parseExpr(frame, rangeVal)
  1716  		if err != nil {
  1717  			return llvm.Value{}, err
  1718  		}
  1719  		it, err := c.parseExpr(frame, expr.Iter)
  1720  		if err != nil {
  1721  			return llvm.Value{}, err
  1722  		}
  1723  		if expr.IsString {
  1724  			return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
  1725  		} else { // map
  1726  			llvmKeyType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key())
  1727  			if err != nil {
  1728  				return llvm.Value{}, err
  1729  			}
  1730  			llvmValueType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem())
  1731  			if err != nil {
  1732  				return llvm.Value{}, err
  1733  			}
  1734  
  1735  			mapKeyAlloca := c.builder.CreateAlloca(llvmKeyType, "range.key")
  1736  			mapKeyPtr := c.builder.CreateBitCast(mapKeyAlloca, c.i8ptrType, "range.keyptr")
  1737  			mapValueAlloca := c.builder.CreateAlloca(llvmValueType, "range.value")
  1738  			mapValuePtr := c.builder.CreateBitCast(mapValueAlloca, c.i8ptrType, "range.valueptr")
  1739  			ok := c.createRuntimeCall("hashmapNext", []llvm.Value{llvmRangeVal, it, mapKeyPtr, mapValuePtr}, "range.next")
  1740  
  1741  			tuple := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.Int1Type(), llvmKeyType, llvmValueType}, false))
  1742  			tuple = c.builder.CreateInsertValue(tuple, ok, 0, "")
  1743  			tuple = c.builder.CreateInsertValue(tuple, c.builder.CreateLoad(mapKeyAlloca, ""), 1, "")
  1744  			tuple = c.builder.CreateInsertValue(tuple, c.builder.CreateLoad(mapValueAlloca, ""), 2, "")
  1745  			return tuple, nil
  1746  		}
  1747  	case *ssa.Phi:
  1748  		t, err := c.getLLVMType(expr.Type())
  1749  		if err != nil {
  1750  			return llvm.Value{}, err
  1751  		}
  1752  		phi := c.builder.CreatePHI(t, "")
  1753  		frame.phis = append(frame.phis, Phi{expr, phi})
  1754  		return phi, nil
  1755  	case *ssa.Range:
  1756  		var iteratorType llvm.Type
  1757  		switch typ := expr.X.Type().Underlying().(type) {
  1758  		case *types.Basic: // string
  1759  			iteratorType = c.mod.GetTypeByName("runtime.stringIterator")
  1760  		case *types.Map:
  1761  			iteratorType = c.mod.GetTypeByName("runtime.hashmapIterator")
  1762  		default:
  1763  			panic("unknown type in range: " + typ.String())
  1764  		}
  1765  		it := c.builder.CreateAlloca(iteratorType, "range.it")
  1766  		zero, err := c.getZeroValue(iteratorType)
  1767  		if err != nil {
  1768  			return llvm.Value{}, nil
  1769  		}
  1770  		c.builder.CreateStore(zero, it)
  1771  		return it, nil
  1772  	case *ssa.Select:
  1773  		if len(expr.States) == 0 {
  1774  			// Shortcuts for some simple selects.
  1775  			llvmType, err := c.getLLVMType(expr.Type())
  1776  			if err != nil {
  1777  				return llvm.Value{}, err
  1778  			}
  1779  			if expr.Blocking {
  1780  				// Blocks forever:
  1781  				//     select {}
  1782  				c.createRuntimeCall("deadlockStub", nil, "")
  1783  				return llvm.Undef(llvmType), nil
  1784  			} else {
  1785  				// No-op:
  1786  				//     select {
  1787  				//     default:
  1788  				//     }
  1789  				retval := llvm.Undef(llvmType)
  1790  				retval = c.builder.CreateInsertValue(retval, llvm.ConstInt(c.intType, 0xffffffffffffffff, true), 0, "")
  1791  				return retval, nil // {-1, false}
  1792  			}
  1793  		}
  1794  		return llvm.Value{}, c.makeError(expr.Pos(), "unimplemented: "+expr.String())
  1795  	case *ssa.Slice:
  1796  		if expr.Max != nil {
  1797  			return llvm.Value{}, c.makeError(expr.Pos(), "todo: full slice expressions (with max): "+expr.Type().String())
  1798  		}
  1799  		value, err := c.parseExpr(frame, expr.X)
  1800  		if err != nil {
  1801  			return llvm.Value{}, err
  1802  		}
  1803  
  1804  		var lowType, highType *types.Basic
  1805  		var low, high llvm.Value
  1806  
  1807  		if expr.Low != nil {
  1808  			lowType = expr.Low.Type().Underlying().(*types.Basic)
  1809  			low, err = c.parseExpr(frame, expr.Low)
  1810  			if err != nil {
  1811  				return llvm.Value{}, nil
  1812  			}
  1813  			if low.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
  1814  				if lowType.Info()&types.IsUnsigned != 0 {
  1815  					low = c.builder.CreateZExt(low, c.uintptrType, "")
  1816  				} else {
  1817  					low = c.builder.CreateSExt(low, c.uintptrType, "")
  1818  				}
  1819  			}
  1820  		} else {
  1821  			lowType = types.Typ[types.Uintptr]
  1822  			low = llvm.ConstInt(c.uintptrType, 0, false)
  1823  		}
  1824  
  1825  		if expr.High != nil {
  1826  			highType = expr.High.Type().Underlying().(*types.Basic)
  1827  			high, err = c.parseExpr(frame, expr.High)
  1828  			if err != nil {
  1829  				return llvm.Value{}, nil
  1830  			}
  1831  			if high.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
  1832  				if highType.Info()&types.IsUnsigned != 0 {
  1833  					high = c.builder.CreateZExt(high, c.uintptrType, "")
  1834  				} else {
  1835  					high = c.builder.CreateSExt(high, c.uintptrType, "")
  1836  				}
  1837  			}
  1838  		} else {
  1839  			highType = types.Typ[types.Uintptr]
  1840  		}
  1841  
  1842  		switch typ := expr.X.Type().Underlying().(type) {
  1843  		case *types.Pointer: // pointer to array
  1844  			// slice an array
  1845  			length := typ.Elem().Underlying().(*types.Array).Len()
  1846  			llvmLen := llvm.ConstInt(c.uintptrType, uint64(length), false)
  1847  			if high.IsNil() {
  1848  				high = llvmLen
  1849  			}
  1850  			indices := []llvm.Value{
  1851  				llvm.ConstInt(c.ctx.Int32Type(), 0, false),
  1852  				low,
  1853  			}
  1854  
  1855  			c.emitSliceBoundsCheck(frame, llvmLen, low, high, lowType, highType)
  1856  
  1857  			// Truncate ints bigger than uintptr. This is after the bounds
  1858  			// check so it's safe.
  1859  			if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1860  				high = c.builder.CreateTrunc(high, c.uintptrType, "")
  1861  			}
  1862  			if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1863  				low = c.builder.CreateTrunc(low, c.uintptrType, "")
  1864  			}
  1865  
  1866  			sliceLen := c.builder.CreateSub(high, low, "slice.len")
  1867  			slicePtr := c.builder.CreateGEP(value, indices, "slice.ptr")
  1868  			sliceCap := c.builder.CreateSub(llvmLen, low, "slice.cap")
  1869  
  1870  			slice := c.ctx.ConstStruct([]llvm.Value{
  1871  				llvm.Undef(slicePtr.Type()),
  1872  				llvm.Undef(c.uintptrType),
  1873  				llvm.Undef(c.uintptrType),
  1874  			}, false)
  1875  			slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
  1876  			slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
  1877  			slice = c.builder.CreateInsertValue(slice, sliceCap, 2, "")
  1878  			return slice, nil
  1879  
  1880  		case *types.Slice:
  1881  			// slice a slice
  1882  			oldPtr := c.builder.CreateExtractValue(value, 0, "")
  1883  			oldLen := c.builder.CreateExtractValue(value, 1, "")
  1884  			oldCap := c.builder.CreateExtractValue(value, 2, "")
  1885  			if high.IsNil() {
  1886  				high = oldLen
  1887  			}
  1888  
  1889  			c.emitSliceBoundsCheck(frame, oldCap, low, high, lowType, highType)
  1890  
  1891  			// Truncate ints bigger than uintptr. This is after the bounds
  1892  			// check so it's safe.
  1893  			if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1894  				low = c.builder.CreateTrunc(low, c.uintptrType, "")
  1895  			}
  1896  			if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1897  				high = c.builder.CreateTrunc(high, c.uintptrType, "")
  1898  			}
  1899  
  1900  			newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
  1901  			newLen := c.builder.CreateSub(high, low, "")
  1902  			newCap := c.builder.CreateSub(oldCap, low, "")
  1903  			slice := c.ctx.ConstStruct([]llvm.Value{
  1904  				llvm.Undef(newPtr.Type()),
  1905  				llvm.Undef(c.uintptrType),
  1906  				llvm.Undef(c.uintptrType),
  1907  			}, false)
  1908  			slice = c.builder.CreateInsertValue(slice, newPtr, 0, "")
  1909  			slice = c.builder.CreateInsertValue(slice, newLen, 1, "")
  1910  			slice = c.builder.CreateInsertValue(slice, newCap, 2, "")
  1911  			return slice, nil
  1912  
  1913  		case *types.Basic:
  1914  			if typ.Info()&types.IsString == 0 {
  1915  				return llvm.Value{}, c.makeError(expr.Pos(), "unknown slice type: "+typ.String())
  1916  			}
  1917  			// slice a string
  1918  			oldPtr := c.builder.CreateExtractValue(value, 0, "")
  1919  			oldLen := c.builder.CreateExtractValue(value, 1, "")
  1920  			if high.IsNil() {
  1921  				high = oldLen
  1922  			}
  1923  
  1924  			c.emitSliceBoundsCheck(frame, oldLen, low, high, lowType, highType)
  1925  
  1926  			// Truncate ints bigger than uintptr. This is after the bounds
  1927  			// check so it's safe.
  1928  			if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1929  				low = c.builder.CreateTrunc(low, c.uintptrType, "")
  1930  			}
  1931  			if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
  1932  				high = c.builder.CreateTrunc(high, c.uintptrType, "")
  1933  			}
  1934  
  1935  			newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
  1936  			newLen := c.builder.CreateSub(high, low, "")
  1937  			str, err := c.getZeroValue(c.mod.GetTypeByName("runtime._string"))
  1938  			if err != nil {
  1939  				return llvm.Value{}, err
  1940  			}
  1941  			str = c.builder.CreateInsertValue(str, newPtr, 0, "")
  1942  			str = c.builder.CreateInsertValue(str, newLen, 1, "")
  1943  			return str, nil
  1944  
  1945  		default:
  1946  			return llvm.Value{}, c.makeError(expr.Pos(), "unknown slice type: "+typ.String())
  1947  		}
  1948  	case *ssa.TypeAssert:
  1949  		return c.parseTypeAssert(frame, expr)
  1950  	case *ssa.UnOp:
  1951  		return c.parseUnOp(frame, expr)
  1952  	default:
  1953  		return llvm.Value{}, c.makeError(expr.Pos(), "todo: unknown expression: "+expr.String())
  1954  	}
  1955  }
  1956  
  1957  func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value, pos token.Pos) (llvm.Value, error) {
  1958  	switch typ := typ.Underlying().(type) {
  1959  	case *types.Basic:
  1960  		if typ.Info()&types.IsInteger != 0 {
  1961  			// Operations on integers
  1962  			signed := typ.Info()&types.IsUnsigned == 0
  1963  			switch op {
  1964  			case token.ADD: // +
  1965  				return c.builder.CreateAdd(x, y, ""), nil
  1966  			case token.SUB: // -
  1967  				return c.builder.CreateSub(x, y, ""), nil
  1968  			case token.MUL: // *
  1969  				return c.builder.CreateMul(x, y, ""), nil
  1970  			case token.QUO: // /
  1971  				if signed {
  1972  					return c.builder.CreateSDiv(x, y, ""), nil
  1973  				} else {
  1974  					return c.builder.CreateUDiv(x, y, ""), nil
  1975  				}
  1976  			case token.REM: // %
  1977  				if signed {
  1978  					return c.builder.CreateSRem(x, y, ""), nil
  1979  				} else {
  1980  					return c.builder.CreateURem(x, y, ""), nil
  1981  				}
  1982  			case token.AND: // &
  1983  				return c.builder.CreateAnd(x, y, ""), nil
  1984  			case token.OR: // |
  1985  				return c.builder.CreateOr(x, y, ""), nil
  1986  			case token.XOR: // ^
  1987  				return c.builder.CreateXor(x, y, ""), nil
  1988  			case token.SHL, token.SHR:
  1989  				sizeX := c.targetData.TypeAllocSize(x.Type())
  1990  				sizeY := c.targetData.TypeAllocSize(y.Type())
  1991  				if sizeX > sizeY {
  1992  					// x and y must have equal sizes, make Y bigger in this case.
  1993  					// y is unsigned, this has been checked by the Go type checker.
  1994  					y = c.builder.CreateZExt(y, x.Type(), "")
  1995  				} else if sizeX < sizeY {
  1996  					// What about shifting more than the integer width?
  1997  					// I'm not entirely sure what the Go spec is on that, but as
  1998  					// Intel CPUs have undefined behavior when shifting more
  1999  					// than the integer width I'm assuming it is also undefined
  2000  					// in Go.
  2001  					y = c.builder.CreateTrunc(y, x.Type(), "")
  2002  				}
  2003  				switch op {
  2004  				case token.SHL: // <<
  2005  					return c.builder.CreateShl(x, y, ""), nil
  2006  				case token.SHR: // >>
  2007  					if signed {
  2008  						return c.builder.CreateAShr(x, y, ""), nil
  2009  					} else {
  2010  						return c.builder.CreateLShr(x, y, ""), nil
  2011  					}
  2012  				default:
  2013  					panic("unreachable")
  2014  				}
  2015  			case token.EQL: // ==
  2016  				return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2017  			case token.NEQ: // !=
  2018  				return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil
  2019  			case token.AND_NOT: // &^
  2020  				// Go specific. Calculate "and not" with x & (~y)
  2021  				inv := c.builder.CreateNot(y, "") // ~y
  2022  				return c.builder.CreateAnd(x, inv, ""), nil
  2023  			case token.LSS: // <
  2024  				if signed {
  2025  					return c.builder.CreateICmp(llvm.IntSLT, x, y, ""), nil
  2026  				} else {
  2027  					return c.builder.CreateICmp(llvm.IntULT, x, y, ""), nil
  2028  				}
  2029  			case token.LEQ: // <=
  2030  				if signed {
  2031  					return c.builder.CreateICmp(llvm.IntSLE, x, y, ""), nil
  2032  				} else {
  2033  					return c.builder.CreateICmp(llvm.IntULE, x, y, ""), nil
  2034  				}
  2035  			case token.GTR: // >
  2036  				if signed {
  2037  					return c.builder.CreateICmp(llvm.IntSGT, x, y, ""), nil
  2038  				} else {
  2039  					return c.builder.CreateICmp(llvm.IntUGT, x, y, ""), nil
  2040  				}
  2041  			case token.GEQ: // >=
  2042  				if signed {
  2043  					return c.builder.CreateICmp(llvm.IntSGE, x, y, ""), nil
  2044  				} else {
  2045  					return c.builder.CreateICmp(llvm.IntUGE, x, y, ""), nil
  2046  				}
  2047  			default:
  2048  				panic("binop on integer: " + op.String())
  2049  			}
  2050  		} else if typ.Info()&types.IsFloat != 0 {
  2051  			// Operations on floats
  2052  			switch op {
  2053  			case token.ADD: // +
  2054  				return c.builder.CreateFAdd(x, y, ""), nil
  2055  			case token.SUB: // -
  2056  				return c.builder.CreateFSub(x, y, ""), nil
  2057  			case token.MUL: // *
  2058  				return c.builder.CreateFMul(x, y, ""), nil
  2059  			case token.QUO: // /
  2060  				return c.builder.CreateFDiv(x, y, ""), nil
  2061  			case token.EQL: // ==
  2062  				return c.builder.CreateFCmp(llvm.FloatUEQ, x, y, ""), nil
  2063  			case token.NEQ: // !=
  2064  				return c.builder.CreateFCmp(llvm.FloatUNE, x, y, ""), nil
  2065  			case token.LSS: // <
  2066  				return c.builder.CreateFCmp(llvm.FloatULT, x, y, ""), nil
  2067  			case token.LEQ: // <=
  2068  				return c.builder.CreateFCmp(llvm.FloatULE, x, y, ""), nil
  2069  			case token.GTR: // >
  2070  				return c.builder.CreateFCmp(llvm.FloatUGT, x, y, ""), nil
  2071  			case token.GEQ: // >=
  2072  				return c.builder.CreateFCmp(llvm.FloatUGE, x, y, ""), nil
  2073  			default:
  2074  				panic("binop on float: " + op.String())
  2075  			}
  2076  		} else if typ.Info()&types.IsComplex != 0 {
  2077  			r1 := c.builder.CreateExtractValue(x, 0, "r1")
  2078  			r2 := c.builder.CreateExtractValue(y, 0, "r2")
  2079  			i1 := c.builder.CreateExtractValue(x, 1, "i1")
  2080  			i2 := c.builder.CreateExtractValue(y, 1, "i2")
  2081  			switch op {
  2082  			case token.EQL: // ==
  2083  				req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
  2084  				ieq := c.builder.CreateFCmp(llvm.FloatOEQ, i1, i2, "")
  2085  				return c.builder.CreateAnd(req, ieq, ""), nil
  2086  			case token.NEQ: // !=
  2087  				req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
  2088  				ieq := c.builder.CreateFCmp(llvm.FloatOEQ, i1, i2, "")
  2089  				neq := c.builder.CreateAnd(req, ieq, "")
  2090  				return c.builder.CreateNot(neq, ""), nil
  2091  			default:
  2092  				return llvm.Value{}, c.makeError(pos, "todo: binop on complex number: "+op.String())
  2093  			}
  2094  		} else if typ.Info()&types.IsBoolean != 0 {
  2095  			// Operations on booleans
  2096  			switch op {
  2097  			case token.EQL: // ==
  2098  				return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2099  			case token.NEQ: // !=
  2100  				return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil
  2101  			default:
  2102  				panic("binop on bool: " + op.String())
  2103  			}
  2104  		} else if typ.Kind() == types.UnsafePointer {
  2105  			// Operations on pointers
  2106  			switch op {
  2107  			case token.EQL: // ==
  2108  				return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2109  			case token.NEQ: // !=
  2110  				return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil
  2111  			default:
  2112  				panic("binop on pointer: " + op.String())
  2113  			}
  2114  		} else if typ.Info()&types.IsString != 0 {
  2115  			// Operations on strings
  2116  			switch op {
  2117  			case token.ADD: // +
  2118  				return c.createRuntimeCall("stringConcat", []llvm.Value{x, y}, ""), nil
  2119  			case token.EQL: // ==
  2120  				return c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, ""), nil
  2121  			case token.NEQ: // !=
  2122  				result := c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "")
  2123  				return c.builder.CreateNot(result, ""), nil
  2124  			case token.LSS: // <
  2125  				return c.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil
  2126  			case token.LEQ: // <=
  2127  				result := c.createRuntimeCall("stringLess", []llvm.Value{y, x}, "")
  2128  				return c.builder.CreateNot(result, ""), nil
  2129  			case token.GTR: // >
  2130  				result := c.createRuntimeCall("stringLess", []llvm.Value{x, y}, "")
  2131  				return c.builder.CreateNot(result, ""), nil
  2132  			case token.GEQ: // >=
  2133  				return c.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil
  2134  			default:
  2135  				panic("binop on string: " + op.String())
  2136  			}
  2137  		} else {
  2138  			return llvm.Value{}, c.makeError(pos, "todo: unknown basic type in binop: "+typ.String())
  2139  		}
  2140  	case *types.Signature:
  2141  		// Get raw scalars from the function value and compare those.
  2142  		// Function values may be implemented in multiple ways, but they all
  2143  		// have some way of getting a scalar value identifying the function.
  2144  		// This is safe: function pointers are generally not comparable
  2145  		// against each other, only against nil. So one of these has to be nil.
  2146  		x = c.extractFuncScalar(x)
  2147  		y = c.extractFuncScalar(y)
  2148  		switch op {
  2149  		case token.EQL: // ==
  2150  			return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2151  		case token.NEQ: // !=
  2152  			return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil
  2153  		default:
  2154  			return llvm.Value{}, c.makeError(pos, "binop on signature: "+op.String())
  2155  		}
  2156  	case *types.Interface:
  2157  		switch op {
  2158  		case token.EQL, token.NEQ: // ==, !=
  2159  			result := c.createRuntimeCall("interfaceEqual", []llvm.Value{x, y}, "")
  2160  			if op == token.NEQ {
  2161  				result = c.builder.CreateNot(result, "")
  2162  			}
  2163  			return result, nil
  2164  		default:
  2165  			return llvm.Value{}, c.makeError(pos, "binop on interface: "+op.String())
  2166  		}
  2167  	case *types.Map, *types.Pointer:
  2168  		// Maps are in general not comparable, but can be compared against nil
  2169  		// (which is a nil pointer). This means they can be trivially compared
  2170  		// by treating them as a pointer.
  2171  		switch op {
  2172  		case token.EQL: // ==
  2173  			return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil
  2174  		case token.NEQ: // !=
  2175  			return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil
  2176  		default:
  2177  			return llvm.Value{}, c.makeError(pos, "todo: binop on pointer: "+op.String())
  2178  		}
  2179  	case *types.Slice:
  2180  		// Slices are in general not comparable, but can be compared against
  2181  		// nil. Assume at least one of them is nil to make the code easier.
  2182  		xPtr := c.builder.CreateExtractValue(x, 0, "")
  2183  		yPtr := c.builder.CreateExtractValue(y, 0, "")
  2184  		switch op {
  2185  		case token.EQL: // ==
  2186  			return c.builder.CreateICmp(llvm.IntEQ, xPtr, yPtr, ""), nil
  2187  		case token.NEQ: // !=
  2188  			return c.builder.CreateICmp(llvm.IntNE, xPtr, yPtr, ""), nil
  2189  		default:
  2190  			return llvm.Value{}, c.makeError(pos, "todo: binop on slice: "+op.String())
  2191  		}
  2192  	case *types.Array:
  2193  		// Compare each array element and combine the result. From the spec:
  2194  		//     Array values are comparable if values of the array element type
  2195  		//     are comparable. Two array values are equal if their corresponding
  2196  		//     elements are equal.
  2197  		result := llvm.ConstInt(c.ctx.Int1Type(), 1, true)
  2198  		for i := 0; i < int(typ.Len()); i++ {
  2199  			xField := c.builder.CreateExtractValue(x, i, "")
  2200  			yField := c.builder.CreateExtractValue(y, i, "")
  2201  			fieldEqual, err := c.parseBinOp(token.EQL, typ.Elem(), xField, yField, pos)
  2202  			if err != nil {
  2203  				return llvm.Value{}, err
  2204  			}
  2205  			result = c.builder.CreateAnd(result, fieldEqual, "")
  2206  		}
  2207  		switch op {
  2208  		case token.EQL: // ==
  2209  			return result, nil
  2210  		case token.NEQ: // !=
  2211  			return c.builder.CreateNot(result, ""), nil
  2212  		default:
  2213  			return llvm.Value{}, c.makeError(pos, "unknown: binop on struct: "+op.String())
  2214  		}
  2215  	case *types.Struct:
  2216  		// Compare each struct field and combine the result. From the spec:
  2217  		//     Struct values are comparable if all their fields are comparable.
  2218  		//     Two struct values are equal if their corresponding non-blank
  2219  		//     fields are equal.
  2220  		result := llvm.ConstInt(c.ctx.Int1Type(), 1, true)
  2221  		for i := 0; i < typ.NumFields(); i++ {
  2222  			if typ.Field(i).Name() == "_" {
  2223  				// skip blank fields
  2224  				continue
  2225  			}
  2226  			fieldType := typ.Field(i).Type()
  2227  			xField := c.builder.CreateExtractValue(x, i, "")
  2228  			yField := c.builder.CreateExtractValue(y, i, "")
  2229  			fieldEqual, err := c.parseBinOp(token.EQL, fieldType, xField, yField, pos)
  2230  			if err != nil {
  2231  				return llvm.Value{}, err
  2232  			}
  2233  			result = c.builder.CreateAnd(result, fieldEqual, "")
  2234  		}
  2235  		switch op {
  2236  		case token.EQL: // ==
  2237  			return result, nil
  2238  		case token.NEQ: // !=
  2239  			return c.builder.CreateNot(result, ""), nil
  2240  		default:
  2241  			return llvm.Value{}, c.makeError(pos, "unknown: binop on struct: "+op.String())
  2242  		}
  2243  	default:
  2244  		return llvm.Value{}, c.makeError(pos, "todo: binop type: "+typ.String())
  2245  	}
  2246  }
  2247  
  2248  func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error) {
  2249  	switch typ := expr.Type().Underlying().(type) {
  2250  	case *types.Basic:
  2251  		llvmType, err := c.getLLVMType(typ)
  2252  		if err != nil {
  2253  			return llvm.Value{}, err
  2254  		}
  2255  		if typ.Info()&types.IsBoolean != 0 {
  2256  			b := constant.BoolVal(expr.Value)
  2257  			n := uint64(0)
  2258  			if b {
  2259  				n = 1
  2260  			}
  2261  			return llvm.ConstInt(llvmType, n, false), nil
  2262  		} else if typ.Info()&types.IsString != 0 {
  2263  			str := constant.StringVal(expr.Value)
  2264  			strLen := llvm.ConstInt(c.uintptrType, uint64(len(str)), false)
  2265  			objname := prefix + "$string"
  2266  			global := llvm.AddGlobal(c.mod, llvm.ArrayType(c.ctx.Int8Type(), len(str)), objname)
  2267  			global.SetInitializer(c.ctx.ConstString(str, false))
  2268  			global.SetLinkage(llvm.InternalLinkage)
  2269  			global.SetGlobalConstant(true)
  2270  			global.SetUnnamedAddr(true)
  2271  			zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
  2272  			strPtr := c.builder.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "")
  2273  			strObj := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._string"), []llvm.Value{strPtr, strLen})
  2274  			return strObj, nil
  2275  		} else if typ.Kind() == types.UnsafePointer {
  2276  			if !expr.IsNil() {
  2277  				value, _ := constant.Uint64Val(expr.Value)
  2278  				return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, value, false), c.i8ptrType), nil
  2279  			}
  2280  			return llvm.ConstNull(c.i8ptrType), nil
  2281  		} else if typ.Info()&types.IsUnsigned != 0 {
  2282  			n, _ := constant.Uint64Val(expr.Value)
  2283  			return llvm.ConstInt(llvmType, n, false), nil
  2284  		} else if typ.Info()&types.IsInteger != 0 { // signed
  2285  			n, _ := constant.Int64Val(expr.Value)
  2286  			return llvm.ConstInt(llvmType, uint64(n), true), nil
  2287  		} else if typ.Info()&types.IsFloat != 0 {
  2288  			n, _ := constant.Float64Val(expr.Value)
  2289  			return llvm.ConstFloat(llvmType, n), nil
  2290  		} else if typ.Kind() == types.Complex64 {
  2291  			r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32]))
  2292  			if err != nil {
  2293  				return llvm.Value{}, err
  2294  			}
  2295  			i, err := c.parseConst(prefix, ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32]))
  2296  			if err != nil {
  2297  				return llvm.Value{}, err
  2298  			}
  2299  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
  2300  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2301  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2302  			return cplx, nil
  2303  		} else if typ.Kind() == types.Complex128 {
  2304  			r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]))
  2305  			if err != nil {
  2306  				return llvm.Value{}, err
  2307  			}
  2308  			i, err := c.parseConst(prefix, ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64]))
  2309  			if err != nil {
  2310  				return llvm.Value{}, err
  2311  			}
  2312  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
  2313  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2314  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2315  			return cplx, nil
  2316  		} else {
  2317  			return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
  2318  		}
  2319  	case *types.Chan:
  2320  		sig, err := c.getLLVMType(expr.Type())
  2321  		if err != nil {
  2322  			return llvm.Value{}, err
  2323  		}
  2324  		return c.getZeroValue(sig)
  2325  	case *types.Signature:
  2326  		if expr.Value != nil {
  2327  			return llvm.Value{}, errors.New("non-nil signature constant")
  2328  		}
  2329  		sig, err := c.getLLVMType(expr.Type())
  2330  		if err != nil {
  2331  			return llvm.Value{}, err
  2332  		}
  2333  		return c.getZeroValue(sig)
  2334  	case *types.Interface:
  2335  		if expr.Value != nil {
  2336  			return llvm.Value{}, errors.New("non-nil interface constant")
  2337  		}
  2338  		// Create a generic nil interface with no dynamic type (typecode=0).
  2339  		fields := []llvm.Value{
  2340  			llvm.ConstInt(c.uintptrType, 0, false),
  2341  			llvm.ConstPointerNull(c.i8ptrType),
  2342  		}
  2343  		itf := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._interface"), fields)
  2344  		return itf, nil
  2345  	case *types.Pointer:
  2346  		if expr.Value != nil {
  2347  			return llvm.Value{}, errors.New("non-nil pointer constant")
  2348  		}
  2349  		llvmType, err := c.getLLVMType(typ)
  2350  		if err != nil {
  2351  			return llvm.Value{}, err
  2352  		}
  2353  		return llvm.ConstPointerNull(llvmType), nil
  2354  	case *types.Slice:
  2355  		if expr.Value != nil {
  2356  			return llvm.Value{}, errors.New("non-nil slice constant")
  2357  		}
  2358  		elemType, err := c.getLLVMType(typ.Elem())
  2359  		if err != nil {
  2360  			return llvm.Value{}, err
  2361  		}
  2362  		llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0))
  2363  		llvmLen := llvm.ConstInt(c.uintptrType, 0, false)
  2364  		slice := c.ctx.ConstStruct([]llvm.Value{
  2365  			llvmPtr, // backing array
  2366  			llvmLen, // len
  2367  			llvmLen, // cap
  2368  		}, false)
  2369  		return slice, nil
  2370  	case *types.Map:
  2371  		if !expr.IsNil() {
  2372  			// I believe this is not allowed by the Go spec.
  2373  			panic("non-nil map constant")
  2374  		}
  2375  		llvmType, err := c.getLLVMType(typ)
  2376  		if err != nil {
  2377  			return llvm.Value{}, err
  2378  		}
  2379  		return c.getZeroValue(llvmType)
  2380  	default:
  2381  		return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
  2382  	}
  2383  }
  2384  
  2385  func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) {
  2386  	llvmTypeFrom := value.Type()
  2387  	llvmTypeTo, err := c.getLLVMType(typeTo)
  2388  	if err != nil {
  2389  		return llvm.Value{}, err
  2390  	}
  2391  
  2392  	// Conversion between unsafe.Pointer and uintptr.
  2393  	isPtrFrom := isPointer(typeFrom.Underlying())
  2394  	isPtrTo := isPointer(typeTo.Underlying())
  2395  	if isPtrFrom && !isPtrTo {
  2396  		return c.builder.CreatePtrToInt(value, llvmTypeTo, ""), nil
  2397  	} else if !isPtrFrom && isPtrTo {
  2398  		if !value.IsABinaryOperator().IsNil() && value.InstructionOpcode() == llvm.Add {
  2399  			// This is probably a pattern like the following:
  2400  			// unsafe.Pointer(uintptr(ptr) + index)
  2401  			// Used in functions like memmove etc. for lack of pointer
  2402  			// arithmetic. Convert it to real pointer arithmatic here.
  2403  			ptr := value.Operand(0)
  2404  			index := value.Operand(1)
  2405  			if !index.IsAPtrToIntInst().IsNil() {
  2406  				// Swap if necessary, if ptr and index are reversed.
  2407  				ptr, index = index, ptr
  2408  			}
  2409  			if !ptr.IsAPtrToIntInst().IsNil() {
  2410  				origptr := ptr.Operand(0)
  2411  				if origptr.Type() == c.i8ptrType {
  2412  					// This pointer can be calculated from the original
  2413  					// ptrtoint instruction with a GEP. The leftover inttoptr
  2414  					// instruction is trivial to optimize away.
  2415  					return c.builder.CreateGEP(origptr, []llvm.Value{index}, ""), nil
  2416  				}
  2417  			}
  2418  		}
  2419  		return c.builder.CreateIntToPtr(value, llvmTypeTo, ""), nil
  2420  	}
  2421  
  2422  	// Conversion between pointers and unsafe.Pointer.
  2423  	if isPtrFrom && isPtrTo {
  2424  		return c.builder.CreateBitCast(value, llvmTypeTo, ""), nil
  2425  	}
  2426  
  2427  	switch typeTo := typeTo.Underlying().(type) {
  2428  	case *types.Basic:
  2429  		sizeFrom := c.targetData.TypeAllocSize(llvmTypeFrom)
  2430  
  2431  		if typeTo.Info()&types.IsString != 0 {
  2432  			switch typeFrom := typeFrom.Underlying().(type) {
  2433  			case *types.Basic:
  2434  				// Assume a Unicode code point, as that is the only possible
  2435  				// value here.
  2436  				// Cast to an i32 value as expected by
  2437  				// runtime.stringFromUnicode.
  2438  				if sizeFrom > 4 {
  2439  					value = c.builder.CreateTrunc(value, c.ctx.Int32Type(), "")
  2440  				} else if sizeFrom < 4 && typeTo.Info()&types.IsUnsigned != 0 {
  2441  					value = c.builder.CreateZExt(value, c.ctx.Int32Type(), "")
  2442  				} else if sizeFrom < 4 {
  2443  					value = c.builder.CreateSExt(value, c.ctx.Int32Type(), "")
  2444  				}
  2445  				return c.createRuntimeCall("stringFromUnicode", []llvm.Value{value}, ""), nil
  2446  			case *types.Slice:
  2447  				switch typeFrom.Elem().(*types.Basic).Kind() {
  2448  				case types.Byte:
  2449  					return c.createRuntimeCall("stringFromBytes", []llvm.Value{value}, ""), nil
  2450  				default:
  2451  					return llvm.Value{}, c.makeError(pos, "todo: convert to string: "+typeFrom.String())
  2452  				}
  2453  			default:
  2454  				return llvm.Value{}, c.makeError(pos, "todo: convert to string: "+typeFrom.String())
  2455  			}
  2456  		}
  2457  
  2458  		typeFrom := typeFrom.Underlying().(*types.Basic)
  2459  		sizeTo := c.targetData.TypeAllocSize(llvmTypeTo)
  2460  
  2461  		if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 {
  2462  			// Conversion between two integers.
  2463  			if sizeFrom > sizeTo {
  2464  				return c.builder.CreateTrunc(value, llvmTypeTo, ""), nil
  2465  			} else if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned
  2466  				return c.builder.CreateZExt(value, llvmTypeTo, ""), nil
  2467  			} else { // if signed
  2468  				return c.builder.CreateSExt(value, llvmTypeTo, ""), nil
  2469  			}
  2470  		}
  2471  
  2472  		if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsFloat != 0 {
  2473  			// Conversion between two floats.
  2474  			if sizeFrom > sizeTo {
  2475  				return c.builder.CreateFPTrunc(value, llvmTypeTo, ""), nil
  2476  			} else if sizeFrom < sizeTo {
  2477  				return c.builder.CreateFPExt(value, llvmTypeTo, ""), nil
  2478  			} else {
  2479  				return value, nil
  2480  			}
  2481  		}
  2482  
  2483  		if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsInteger != 0 {
  2484  			// Conversion from float to int.
  2485  			if typeTo.Info()&types.IsUnsigned != 0 { // if unsigned
  2486  				return c.builder.CreateFPToUI(value, llvmTypeTo, ""), nil
  2487  			} else { // if signed
  2488  				return c.builder.CreateFPToSI(value, llvmTypeTo, ""), nil
  2489  			}
  2490  		}
  2491  
  2492  		if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsFloat != 0 {
  2493  			// Conversion from int to float.
  2494  			if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned
  2495  				return c.builder.CreateUIToFP(value, llvmTypeTo, ""), nil
  2496  			} else { // if signed
  2497  				return c.builder.CreateSIToFP(value, llvmTypeTo, ""), nil
  2498  			}
  2499  		}
  2500  
  2501  		if typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 {
  2502  			// Conversion from complex128 to complex64.
  2503  			r := c.builder.CreateExtractValue(value, 0, "real.f64")
  2504  			i := c.builder.CreateExtractValue(value, 1, "imag.f64")
  2505  			r = c.builder.CreateFPTrunc(r, c.ctx.FloatType(), "real.f32")
  2506  			i = c.builder.CreateFPTrunc(i, c.ctx.FloatType(), "imag.f32")
  2507  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
  2508  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2509  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2510  			return cplx, nil
  2511  		}
  2512  
  2513  		if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {
  2514  			// Conversion from complex64 to complex128.
  2515  			r := c.builder.CreateExtractValue(value, 0, "real.f32")
  2516  			i := c.builder.CreateExtractValue(value, 1, "imag.f32")
  2517  			r = c.builder.CreateFPExt(r, c.ctx.DoubleType(), "real.f64")
  2518  			i = c.builder.CreateFPExt(i, c.ctx.DoubleType(), "imag.f64")
  2519  			cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
  2520  			cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
  2521  			cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
  2522  			return cplx, nil
  2523  		}
  2524  
  2525  		return llvm.Value{}, c.makeError(pos, "todo: convert: basic non-integer type: "+typeFrom.String()+" -> "+typeTo.String())
  2526  
  2527  	case *types.Slice:
  2528  		if basic, ok := typeFrom.(*types.Basic); !ok || basic.Info()&types.IsString == 0 {
  2529  			panic("can only convert from a string to a slice")
  2530  		}
  2531  
  2532  		elemType := typeTo.Elem().Underlying().(*types.Basic) // must be byte or rune
  2533  		switch elemType.Kind() {
  2534  		case types.Byte:
  2535  			return c.createRuntimeCall("stringToBytes", []llvm.Value{value}, ""), nil
  2536  		default:
  2537  			return llvm.Value{}, c.makeError(pos, "todo: convert from string: "+elemType.String())
  2538  		}
  2539  
  2540  	default:
  2541  		return llvm.Value{}, c.makeError(pos, "todo: convert "+typeTo.String()+" <- "+typeFrom.String())
  2542  	}
  2543  }
  2544  
  2545  func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
  2546  	x, err := c.parseExpr(frame, unop.X)
  2547  	if err != nil {
  2548  		return llvm.Value{}, err
  2549  	}
  2550  	switch unop.Op {
  2551  	case token.NOT: // !x
  2552  		return c.builder.CreateNot(x, ""), nil
  2553  	case token.SUB: // -x
  2554  		if typ, ok := unop.X.Type().Underlying().(*types.Basic); ok {
  2555  			if typ.Info()&types.IsInteger != 0 {
  2556  				return c.builder.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil
  2557  			} else if typ.Info()&types.IsFloat != 0 {
  2558  				return c.builder.CreateFSub(llvm.ConstFloat(x.Type(), 0.0), x, ""), nil
  2559  			} else {
  2560  				return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown basic type for negate: "+typ.String())
  2561  			}
  2562  		} else {
  2563  			return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown type for negate: "+unop.X.Type().Underlying().String())
  2564  		}
  2565  	case token.MUL: // *x, dereference pointer
  2566  		valType := unop.X.Type().Underlying().(*types.Pointer).Elem()
  2567  		if c.targetData.TypeAllocSize(x.Type().ElementType()) == 0 {
  2568  			// zero-length data
  2569  			return c.getZeroValue(x.Type().ElementType())
  2570  		} else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
  2571  			// CGo function pointer. The cgo part has rewritten CGo function
  2572  			// pointers as stub global variables of the form:
  2573  			//     var C.add unsafe.Pointer
  2574  			// Instead of a load from the global, create a bitcast of the
  2575  			// function pointer itself.
  2576  			global := c.ir.GetGlobal(unop.X.(*ssa.Global))
  2577  			name := global.LinkName()[:len(global.LinkName())-len("$funcaddr")]
  2578  			fn := c.mod.NamedFunction(name)
  2579  			if fn.IsNil() {
  2580  				return llvm.Value{}, c.makeError(unop.Pos(), "cgo function not found: "+name)
  2581  			}
  2582  			return c.builder.CreateBitCast(fn, c.i8ptrType, ""), nil
  2583  		} else {
  2584  			c.emitNilCheck(frame, x, "deref")
  2585  			load := c.builder.CreateLoad(x, "")
  2586  			if c.ir.IsVolatile(valType) {
  2587  				// Volatile load, for memory-mapped registers.
  2588  				load.SetVolatile(true)
  2589  			}
  2590  			return load, nil
  2591  		}
  2592  	case token.XOR: // ^x, toggle all bits in integer
  2593  		return c.builder.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), ""), nil
  2594  	case token.ARROW: // <-x, receive from channel
  2595  		return c.emitChanRecv(frame, unop)
  2596  	default:
  2597  		return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown unop")
  2598  	}
  2599  }
  2600  
  2601  // IR returns the whole IR as a human-readable string.
  2602  func (c *Compiler) IR() string {
  2603  	return c.mod.String()
  2604  }
  2605  
  2606  func (c *Compiler) Verify() error {
  2607  	return llvm.VerifyModule(c.mod, llvm.PrintMessageAction)
  2608  }
  2609  
  2610  func (c *Compiler) ApplyFunctionSections() {
  2611  	// Put every function in a separate section. This makes it possible for the
  2612  	// linker to remove dead code (-ffunction-sections).
  2613  	llvmFn := c.mod.FirstFunction()
  2614  	for !llvmFn.IsNil() {
  2615  		if !llvmFn.IsDeclaration() {
  2616  			name := llvmFn.Name()
  2617  			llvmFn.SetSection(".text." + name)
  2618  		}
  2619  		llvmFn = llvm.NextFunction(llvmFn)
  2620  	}
  2621  }
  2622  
  2623  // Turn all global constants into global variables. This works around a
  2624  // limitation on Harvard architectures (e.g. AVR), where constant and
  2625  // non-constant pointers point to a different address space.
  2626  func (c *Compiler) NonConstGlobals() {
  2627  	global := c.mod.FirstGlobal()
  2628  	for !global.IsNil() {
  2629  		global.SetGlobalConstant(false)
  2630  		global = llvm.NextGlobal(global)
  2631  	}
  2632  }
  2633  
  2634  // When -wasm-abi flag set to "js" (default),
  2635  // replace i64 in an external function with a stack-allocated i64*, to work
  2636  // around the lack of 64-bit integers in JavaScript (commonly used together with
  2637  // WebAssembly). Once that's resolved, this pass may be avoided.
  2638  // See also the -wasm-abi= flag
  2639  // https://github.com/WebAssembly/design/issues/1172
  2640  func (c *Compiler) ExternalInt64AsPtr() error {
  2641  	int64Type := c.ctx.Int64Type()
  2642  	int64PtrType := llvm.PointerType(int64Type, 0)
  2643  	for fn := c.mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
  2644  		if fn.Linkage() != llvm.ExternalLinkage {
  2645  			// Only change externally visible functions (exports and imports).
  2646  			continue
  2647  		}
  2648  		if strings.HasPrefix(fn.Name(), "llvm.") || strings.HasPrefix(fn.Name(), "runtime.") {
  2649  			// Do not try to modify the signature of internal LLVM functions and
  2650  			// assume that runtime functions are only temporarily exported for
  2651  			// coroutine lowering.
  2652  			continue
  2653  		}
  2654  
  2655  		hasInt64 := false
  2656  		paramTypes := []llvm.Type{}
  2657  
  2658  		// Check return type for 64-bit integer.
  2659  		fnType := fn.Type().ElementType()
  2660  		returnType := fnType.ReturnType()
  2661  		if returnType == int64Type {
  2662  			hasInt64 = true
  2663  			paramTypes = append(paramTypes, int64PtrType)
  2664  			returnType = c.ctx.VoidType()
  2665  		}
  2666  
  2667  		// Check param types for 64-bit integers.
  2668  		for param := fn.FirstParam(); !param.IsNil(); param = llvm.NextParam(param) {
  2669  			if param.Type() == int64Type {
  2670  				hasInt64 = true
  2671  				paramTypes = append(paramTypes, int64PtrType)
  2672  			} else {
  2673  				paramTypes = append(paramTypes, param.Type())
  2674  			}
  2675  		}
  2676  
  2677  		if !hasInt64 {
  2678  			// No i64 in the paramter list.
  2679  			continue
  2680  		}
  2681  
  2682  		// Add $i64wrapper to the real function name as it is only used
  2683  		// internally.
  2684  		// Add a new function with the correct signature that is exported.
  2685  		name := fn.Name()
  2686  		fn.SetName(name + "$i64wrap")
  2687  		externalFnType := llvm.FunctionType(returnType, paramTypes, fnType.IsFunctionVarArg())
  2688  		externalFn := llvm.AddFunction(c.mod, name, externalFnType)
  2689  
  2690  		if fn.IsDeclaration() {
  2691  			// Just a declaration: the definition doesn't exist on the Go side
  2692  			// so it cannot be called from external code.
  2693  			// Update all users to call the external function.
  2694  			// The old $i64wrapper function could be removed, but it may as well
  2695  			// be left in place.
  2696  			for use := fn.FirstUse(); !use.IsNil(); use = use.NextUse() {
  2697  				call := use.User()
  2698  				c.builder.SetInsertPointBefore(call)
  2699  				callParams := []llvm.Value{}
  2700  				var retvalAlloca llvm.Value
  2701  				if fnType.ReturnType() == int64Type {
  2702  					retvalAlloca = c.builder.CreateAlloca(int64Type, "i64asptr")
  2703  					callParams = append(callParams, retvalAlloca)
  2704  				}
  2705  				for i := 0; i < call.OperandsCount()-1; i++ {
  2706  					operand := call.Operand(i)
  2707  					if operand.Type() == int64Type {
  2708  						// Pass a stack-allocated pointer instead of the value
  2709  						// itself.
  2710  						alloca := c.builder.CreateAlloca(int64Type, "i64asptr")
  2711  						c.builder.CreateStore(operand, alloca)
  2712  						callParams = append(callParams, alloca)
  2713  					} else {
  2714  						// Unchanged parameter.
  2715  						callParams = append(callParams, operand)
  2716  					}
  2717  				}
  2718  				if fnType.ReturnType() == int64Type {
  2719  					// Pass a stack-allocated pointer as the first parameter
  2720  					// where the return value should be stored, instead of using
  2721  					// the regular return value.
  2722  					c.builder.CreateCall(externalFn, callParams, call.Name())
  2723  					returnValue := c.builder.CreateLoad(retvalAlloca, "retval")
  2724  					call.ReplaceAllUsesWith(returnValue)
  2725  					call.EraseFromParentAsInstruction()
  2726  				} else {
  2727  					newCall := c.builder.CreateCall(externalFn, callParams, call.Name())
  2728  					call.ReplaceAllUsesWith(newCall)
  2729  					call.EraseFromParentAsInstruction()
  2730  				}
  2731  			}
  2732  		} else {
  2733  			// The function has a definition in Go. This means that it may still
  2734  			// be called both Go and from external code.
  2735  			// Keep existing calls with the existing convention in place (for
  2736  			// better performance), but export a new wrapper function with the
  2737  			// correct calling convention.
  2738  			fn.SetLinkage(llvm.InternalLinkage)
  2739  			fn.SetUnnamedAddr(true)
  2740  			entryBlock := llvm.AddBasicBlock(externalFn, "entry")
  2741  			c.builder.SetInsertPointAtEnd(entryBlock)
  2742  			var callParams []llvm.Value
  2743  			if fnType.ReturnType() == int64Type {
  2744  				return errors.New("not yet implemented: exported function returns i64 with -wasm-abi=js; " +
  2745  					"see https://tinygo.org/compiler-internals/calling-convention/")
  2746  			}
  2747  			for i, origParam := range fn.Params() {
  2748  				paramValue := externalFn.Param(i)
  2749  				if origParam.Type() == int64Type {
  2750  					paramValue = c.builder.CreateLoad(paramValue, "i64")
  2751  				}
  2752  				callParams = append(callParams, paramValue)
  2753  			}
  2754  			retval := c.builder.CreateCall(fn, callParams, "")
  2755  			if retval.Type().TypeKind() == llvm.VoidTypeKind {
  2756  				c.builder.CreateRetVoid()
  2757  			} else {
  2758  				c.builder.CreateRet(retval)
  2759  			}
  2760  		}
  2761  	}
  2762  
  2763  	return nil
  2764  }
  2765  
  2766  // Emit object file (.o).
  2767  func (c *Compiler) EmitObject(path string) error {
  2768  	llvmBuf, err := c.machine.EmitToMemoryBuffer(c.mod, llvm.ObjectFile)
  2769  	if err != nil {
  2770  		return err
  2771  	}
  2772  	return c.writeFile(llvmBuf.Bytes(), path)
  2773  }
  2774  
  2775  // Emit LLVM bitcode file (.bc).
  2776  func (c *Compiler) EmitBitcode(path string) error {
  2777  	data := llvm.WriteBitcodeToMemoryBuffer(c.mod).Bytes()
  2778  	return c.writeFile(data, path)
  2779  }
  2780  
  2781  // Emit LLVM IR source file (.ll).
  2782  func (c *Compiler) EmitText(path string) error {
  2783  	data := []byte(c.mod.String())
  2784  	return c.writeFile(data, path)
  2785  }
  2786  
  2787  // Write the data to the file specified by path.
  2788  func (c *Compiler) writeFile(data []byte, path string) error {
  2789  	// Write output to file
  2790  	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
  2791  	if err != nil {
  2792  		return err
  2793  	}
  2794  	_, err = f.Write(data)
  2795  	if err != nil {
  2796  		return err
  2797  	}
  2798  	return f.Close()
  2799  }