github.com/goplus/llgo@v0.8.3/cl/compile.go (about)

     1  /*
     2   * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cl
    18  
    19  import (
    20  	"fmt"
    21  	"go/ast"
    22  	"go/constant"
    23  	"go/token"
    24  	"go/types"
    25  	"log"
    26  	"os"
    27  	"sort"
    28  	"strings"
    29  
    30  	llssa "github.com/goplus/llgo/ssa"
    31  	"golang.org/x/tools/go/ssa"
    32  )
    33  
    34  // -----------------------------------------------------------------------------
    35  
    36  type dbgFlags = int
    37  
    38  const (
    39  	DbgFlagInstruction dbgFlags = 1 << iota
    40  	DbgFlagGoSSA
    41  
    42  	DbgFlagAll = DbgFlagInstruction | DbgFlagGoSSA
    43  )
    44  
    45  var (
    46  	debugInstr bool
    47  	debugGoSSA bool
    48  )
    49  
    50  // SetDebug sets debug flags.
    51  func SetDebug(dbgFlags dbgFlags) {
    52  	debugInstr = (dbgFlags & DbgFlagInstruction) != 0
    53  	debugGoSSA = (dbgFlags & DbgFlagGoSSA) != 0
    54  }
    55  
    56  // -----------------------------------------------------------------------------
    57  
    58  const (
    59  	fnNormal = iota
    60  	fnHasVArg
    61  	fnIgnore
    62  )
    63  
    64  func (p *context) funcKind(vfn ssa.Value) int {
    65  	if fn, ok := vfn.(*ssa.Function); ok {
    66  		params := fn.Signature.Params()
    67  		n := params.Len()
    68  		if n == 0 {
    69  			if fn.Signature.Recv() == nil {
    70  				if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
    71  					return fnIgnore
    72  				}
    73  			}
    74  		} else {
    75  			last := params.At(n - 1)
    76  			if last.Name() == llssa.NameValist {
    77  				return fnHasVArg
    78  			}
    79  		}
    80  	}
    81  	return fnNormal
    82  }
    83  
    84  func (p *context) pkgNoInit(pkg *types.Package) bool {
    85  	p.ensureLoaded(pkg)
    86  	if i, ok := p.loaded[pkg]; ok {
    87  		return i.kind >= PkgNoInit
    88  	}
    89  	return false
    90  }
    91  
    92  func ignoreName(name string) bool {
    93  	/* TODO(xsw): confirm this is not needed more
    94  	if name == "unsafe.init" {
    95  		return true
    96  	}
    97  	*/
    98  	if strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") ||
    99  		strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
   100  		strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
   101  		strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") ||
   102  		strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "errors.") {
   103  		return true // TODO(xsw)
   104  	}
   105  	return inPkg(name, "runtime") || inPkg(name, "sync")
   106  }
   107  
   108  func inPkg(name, pkg string) bool {
   109  	if len(name) > len(pkg) && strings.HasPrefix(name, pkg) {
   110  		c := name[len(pkg)]
   111  		return c == '.' || c == '/'
   112  	}
   113  	return false
   114  }
   115  
   116  // -----------------------------------------------------------------------------
   117  
   118  type instrOrValue interface {
   119  	ssa.Instruction
   120  	ssa.Value
   121  }
   122  
   123  const (
   124  	PkgNormal = iota
   125  	PkgLLGo
   126  	PkgPyModule   // py.<module>
   127  	PkgNoInit     // noinit: a package that don't need to be initialized
   128  	PkgDeclOnly   // decl: a package that only have declarations
   129  	PkgLinkIR     // link llvm ir (.ll)
   130  	PkgLinkExtern // link external object (.a/.so/.dll/.dylib/etc.)
   131  	// PkgLinkBitCode // link bitcode (.bc)
   132  )
   133  
   134  type pkgInfo struct {
   135  	kind int
   136  }
   137  
   138  type context struct {
   139  	prog   llssa.Program
   140  	pkg    llssa.Package
   141  	fn     llssa.Function
   142  	fset   *token.FileSet
   143  	goProg *ssa.Program
   144  	goTyps *types.Package
   145  	goPkg  *ssa.Package
   146  	pyMod  string
   147  	link   map[string]string           // pkgPath.nameInPkg => linkname
   148  	loaded map[*types.Package]*pkgInfo // loaded packages
   149  	bvals  map[ssa.Value]llssa.Expr    // block values
   150  	vargs  map[*ssa.Alloc][]llssa.Expr // varargs
   151  	inits  []func()
   152  	phis   []func()
   153  }
   154  
   155  func (p *context) inMain(instr ssa.Instruction) bool {
   156  	return instr.Parent().Name() == "main"
   157  }
   158  
   159  func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
   160  	tn := t.Object().(*types.TypeName)
   161  	if tn.IsAlias() { // don't need to compile alias type
   162  		return
   163  	}
   164  	tnName := tn.Name()
   165  	typ := tn.Type()
   166  	name := llssa.FullName(tn.Pkg(), tnName)
   167  	if ignoreName(name) {
   168  		return
   169  	}
   170  	if debugInstr {
   171  		log.Println("==> NewType", name, typ)
   172  	}
   173  	p.compileMethods(pkg, typ)
   174  	p.compileMethods(pkg, types.NewPointer(typ))
   175  }
   176  
   177  func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
   178  	prog := p.goProg
   179  	mthds := prog.MethodSets.MethodSet(typ)
   180  	for i, n := 0, mthds.Len(); i < n; i++ {
   181  		mthd := mthds.At(i)
   182  		if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
   183  			p.compileFuncDecl(pkg, ssaMthd)
   184  		}
   185  	}
   186  }
   187  
   188  // Global variable.
   189  func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
   190  	typ := gbl.Type()
   191  	name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
   192  	if vtype == pyVar || ignoreName(name) || checkCgo(gbl.Name()) {
   193  		return
   194  	}
   195  	if debugInstr {
   196  		log.Println("==> NewVar", name, typ)
   197  	}
   198  	g := pkg.NewVar(name, typ, llssa.Background(vtype))
   199  	if vtype == goVar {
   200  		g.Init(p.prog.Null(g.Type))
   201  	}
   202  }
   203  
   204  func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var {
   205  	n := len(vars)
   206  	flds := make([]*types.Var, n)
   207  	for i, v := range vars {
   208  		flds[i] = types.NewField(token.NoPos, pkg, v.Name(), v.Type(), false)
   209  	}
   210  	t := types.NewPointer(types.NewStruct(flds, nil))
   211  	return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t)
   212  }
   213  
   214  var (
   215  	argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
   216  )
   217  
   218  func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
   219  	pkgTypes, name, ftype := p.funcName(f, true)
   220  	if ftype != goFunc {
   221  		/*
   222  			if ftype == pyFunc {
   223  				// TODO(xsw): pyMod == ""
   224  				fnName := pysymPrefix + p.pyMod + "." + name
   225  				return nil, pkg.NewPyFunc(fnName, f.Signature, call), pyFunc
   226  			}
   227  		*/
   228  		return nil, nil, ignoredFunc
   229  	}
   230  	fn := pkg.FuncOf(name)
   231  	if fn != nil && fn.HasBody() {
   232  		return fn, nil, goFunc
   233  	}
   234  
   235  	var sig = f.Signature
   236  	var hasCtx = len(f.FreeVars) > 0
   237  	if hasCtx {
   238  		if debugInstr {
   239  			log.Println("==> NewClosure", name, "type:", sig)
   240  		}
   241  		ctx := makeClosureCtx(pkgTypes, f.FreeVars)
   242  		sig = llssa.FuncAddCtx(ctx, sig)
   243  	} else {
   244  		if debugInstr {
   245  			log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype)
   246  		}
   247  	}
   248  	if fn == nil {
   249  		if name == "main" {
   250  			argc := types.NewParam(token.NoPos, pkgTypes, "", types.Typ[types.Int32])
   251  			argv := types.NewParam(token.NoPos, pkgTypes, "", argvTy)
   252  			params := types.NewTuple(argc, argv)
   253  			ret := types.NewParam(token.NoPos, pkgTypes, "", p.prog.CInt().RawType())
   254  			results := types.NewTuple(ret)
   255  			sig = types.NewSignatureType(nil, nil, nil, params, results, false)
   256  		}
   257  		fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx)
   258  	}
   259  
   260  	if nblk := len(f.Blocks); nblk > 0 {
   261  		fn.MakeBlocks(nblk) // to set fn.HasBody() = true
   262  		p.inits = append(p.inits, func() {
   263  			p.fn = fn
   264  			defer func() {
   265  				p.fn = nil
   266  			}()
   267  			p.phis = nil
   268  			if debugGoSSA {
   269  				f.WriteTo(os.Stderr)
   270  			}
   271  			if debugInstr {
   272  				log.Println("==> FuncBody", name)
   273  			}
   274  			b := fn.NewBuilder()
   275  			p.bvals = make(map[ssa.Value]llssa.Expr)
   276  			off := make([]int, len(f.Blocks))
   277  			for i, block := range f.Blocks {
   278  				off[i] = p.compilePhis(b, block)
   279  			}
   280  			for i, block := range f.Blocks {
   281  				doMainInit := (i == 0 && name == "main")
   282  				doModInit := (i == 1 && f.Name() == "init" && sig.Recv() == nil)
   283  				p.compileBlock(b, block, off[i], doMainInit, doModInit)
   284  			}
   285  			for _, phi := range p.phis {
   286  				phi()
   287  			}
   288  		})
   289  	}
   290  	return fn, nil, goFunc
   291  }
   292  
   293  // funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
   294  // or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
   295  func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObjRef, ftype int) {
   296  	pkgTypes, name, ftype := p.funcName(fn, false)
   297  	switch ftype {
   298  	case pyFunc:
   299  		if kind, mod := pkgKindByScope(pkgTypes.Scope()); kind == PkgPyModule {
   300  			pkg := p.pkg
   301  			fnName := pysymPrefix + mod + "." + name
   302  			if pyFn = pkg.PyObjOf(fnName); pyFn == nil {
   303  				pyFn = pkg.PyNewFunc(fnName, fn.Signature, true)
   304  				return
   305  			}
   306  		}
   307  		ftype = ignoredFunc
   308  	case llgoInstr:
   309  		switch name {
   310  		case "cstr":
   311  			ftype = llgoCstr
   312  		case "advance":
   313  			ftype = llgoAdvance
   314  		case "index":
   315  			ftype = llgoIndex
   316  		case "alloca":
   317  			ftype = llgoAlloca
   318  		case "allocaCStr":
   319  			ftype = llgoAllocaCStr
   320  		case "stringData":
   321  			ftype = llgoStringData
   322  		case "pyList":
   323  			ftype = llgoPyList
   324  		case "unreachable":
   325  			ftype = llgoUnreachable
   326  		default:
   327  			panic("unknown llgo instruction: " + name)
   328  		}
   329  	default:
   330  		pkg := p.pkg
   331  		if aFn = pkg.FuncOf(name); aFn == nil {
   332  			if len(fn.FreeVars) > 0 {
   333  				return nil, nil, ignoredFunc
   334  			}
   335  			sig := fn.Signature
   336  			aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
   337  		}
   338  	}
   339  	return
   340  }
   341  
   342  func modOf(name string) string {
   343  	if pos := strings.LastIndexByte(name, '.'); pos > 0 {
   344  		return name[:pos]
   345  	}
   346  	return ""
   347  }
   348  
   349  func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
   350  	var last int
   351  	var pyModInit bool
   352  	var prog = p.prog
   353  	var pkg = p.pkg
   354  	var instrs = block.Instrs[n:]
   355  	var ret = p.fn.Block(block.Index)
   356  	b.SetBlock(ret)
   357  	if doModInit {
   358  		if pyModInit = p.pyMod != ""; pyModInit {
   359  			last = len(instrs) - 1
   360  			instrs = instrs[:last]
   361  		} else {
   362  			// TODO(xsw): confirm pyMod don't need to call LoadPyModSyms
   363  			p.inits = append(p.inits, func() {
   364  				if objs := pkg.PyObjs(); len(objs) > 0 {
   365  					mods := make(map[string][]llssa.PyObjRef)
   366  					for name, obj := range objs {
   367  						modName := modOf(name)
   368  						mods[modName] = append(mods[modName], obj)
   369  					}
   370  
   371  					// sort by module name
   372  					modNames := make([]string, 0, len(mods))
   373  					for modName := range mods {
   374  						modNames = append(modNames, modName)
   375  					}
   376  					sort.Strings(modNames)
   377  
   378  					b.SetBlockEx(ret, llssa.AfterInit)
   379  					for _, modName := range modNames {
   380  						objs := mods[modName]
   381  						b.PyLoadModSyms(modName, objs...)
   382  					}
   383  				}
   384  			})
   385  		}
   386  	} else if doMainInit {
   387  		fn := p.fn
   388  		argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
   389  		argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
   390  		argc.Init(prog.Null(argc.Type))
   391  		argv.Init(prog.Null(argv.Type))
   392  		b.Store(argc.Expr, fn.Param(0))
   393  		b.Store(argv.Expr, fn.Param(1))
   394  		callRuntimeInit(b, pkg)
   395  		b.Call(pkg.FuncOf("main.init").Expr)
   396  	}
   397  	for _, instr := range instrs {
   398  		p.compileInstr(b, instr)
   399  	}
   400  	if pyModInit {
   401  		jump := block.Instrs[n+last].(*ssa.Jump)
   402  		jumpTo := p.jumpTo(jump)
   403  		modPath := p.pyMod
   404  		modName := pysymPrefix + modPath
   405  		modPtr := pkg.PyNewModVar(modName, true).Expr
   406  		mod := b.Load(modPtr)
   407  		cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
   408  		newBlk := p.fn.MakeBlock()
   409  		b.If(cond, jumpTo, newBlk)
   410  		b.SetBlock(newBlk)
   411  		b.Store(modPtr, b.PyImportMod(modPath))
   412  		b.Jump(jumpTo)
   413  	}
   414  	return ret
   415  }
   416  
   417  const (
   418  	RuntimeInit = llssa.PkgRuntime + ".init"
   419  )
   420  
   421  func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
   422  	fn := pkg.NewFunc(RuntimeInit, llssa.NoArgsNoRet, llssa.InC) // don't need to convert runtime.init
   423  	b.Call(fn.Expr)
   424  }
   425  
   426  func isAny(t types.Type) bool {
   427  	if t, ok := t.(*types.Interface); ok {
   428  		return t.Empty()
   429  	}
   430  	return false
   431  }
   432  
   433  func intVal(v ssa.Value) int64 {
   434  	if c, ok := v.(*ssa.Const); ok {
   435  		if iv, exact := constant.Int64Val(c.Value); exact {
   436  			return iv
   437  		}
   438  	}
   439  	panic("intVal: ssa.Value is not a const int")
   440  }
   441  
   442  func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
   443  	if va, vok := vx.(*ssa.Alloc); vok {
   444  		ret, ok = p.vargs[va] // varargs: this is a varargs index
   445  	}
   446  	return
   447  }
   448  
   449  func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
   450  	if v.Comment == "varargs" { // this maybe a varargs allocation
   451  		if arr, ok := t.Elem().(*types.Array); ok {
   452  			if isAny(arr.Elem()) && isVargs(p, v) {
   453  				p.vargs[v] = make([]llssa.Expr, arr.Len())
   454  				return true
   455  			}
   456  		}
   457  	}
   458  	return false
   459  }
   460  
   461  func isVargs(ctx *context, v *ssa.Alloc) bool {
   462  	refs := *v.Referrers()
   463  	n := len(refs)
   464  	lastref := refs[n-1]
   465  	if i, ok := lastref.(*ssa.Slice); ok {
   466  		if refs = *i.Referrers(); len(refs) == 1 {
   467  			if call, ok := refs[0].(*ssa.Call); ok {
   468  				return ctx.funcKind(call.Call.Value) == fnHasVArg
   469  			}
   470  		}
   471  	}
   472  	return false
   473  }
   474  
   475  // func cstr(string) *int8
   476  func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   477  	if len(args) == 1 {
   478  		if c, ok := args[0].(*ssa.Const); ok {
   479  			if v := c.Value; v.Kind() == constant.String {
   480  				sv := constant.StringVal(v)
   481  				return b.CStr(sv)
   482  			}
   483  		}
   484  	}
   485  	panic("cstr(<string-literal>): invalid arguments")
   486  }
   487  
   488  // func index(arr *T, idx int) T
   489  func (p *context) index(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   490  	return b.Load(p.advance(b, args))
   491  }
   492  
   493  // func advance(ptr *T, offset int) *T
   494  func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   495  	if len(args) == 2 {
   496  		ptr := p.compileValue(b, args[0])
   497  		offset := p.compileValue(b, args[1])
   498  		return b.Advance(ptr, offset)
   499  	}
   500  	panic("advance(p ptr, offset int): invalid arguments")
   501  }
   502  
   503  // func alloca(size uintptr) unsafe.Pointer
   504  func (p *context) alloca(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   505  	if len(args) == 1 {
   506  		n := p.compileValue(b, args[0])
   507  		return b.Alloca(n)
   508  	}
   509  	panic("alloca(size uintptr): invalid arguments")
   510  }
   511  
   512  // func allocaCStr(s string) *int8
   513  func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   514  	if len(args) == 1 {
   515  		s := p.compileValue(b, args[0])
   516  		return b.AllocaCStr(s)
   517  	}
   518  	panic("allocaCStr(s string): invalid arguments")
   519  }
   520  
   521  // func stringData(s string) *int8
   522  func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
   523  	if len(args) == 1 {
   524  		s := p.compileValue(b, args[0])
   525  		return b.StringData(s)
   526  	}
   527  	panic("stringData(s string): invalid arguments")
   528  }
   529  
   530  func isPhi(i ssa.Instruction) bool {
   531  	_, ok := i.(*ssa.Phi)
   532  	return ok
   533  }
   534  
   535  func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
   536  	ret := p.fn.Block(block.Index)
   537  	b.SetBlockEx(ret, llssa.AtEnd)
   538  	if ninstr := len(block.Instrs); ninstr > 0 {
   539  		if isPhi(block.Instrs[0]) {
   540  			n := 1
   541  			for n < ninstr && isPhi(block.Instrs[n]) {
   542  				n++
   543  			}
   544  			rets := make([]llssa.Expr, n)
   545  			for i := 0; i < n; i++ {
   546  				iv := block.Instrs[i].(*ssa.Phi)
   547  				rets[i] = p.compilePhi(b, iv)
   548  			}
   549  			for i := 0; i < n; i++ {
   550  				iv := block.Instrs[i].(*ssa.Phi)
   551  				p.bvals[iv] = rets[i].Do(b)
   552  			}
   553  			return n
   554  		}
   555  	}
   556  	return 0
   557  }
   558  
   559  func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
   560  	phi := b.Phi(p.prog.Type(v.Type(), llssa.InGo))
   561  	ret = phi.Expr
   562  	p.phis = append(p.phis, func() {
   563  		preds := v.Block().Preds
   564  		bblks := make([]llssa.BasicBlock, len(preds))
   565  		for i, pred := range preds {
   566  			bblks[i] = p.fn.Block(pred.Index)
   567  		}
   568  		edges := v.Edges
   569  		phi.AddIncoming(b, bblks, func(i int) llssa.Expr {
   570  			return p.compileValue(b, edges[i])
   571  		})
   572  	})
   573  	return
   574  }
   575  
   576  func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue bool) (ret llssa.Expr) {
   577  	if asValue {
   578  		if v, ok := p.bvals[iv]; ok {
   579  			return v
   580  		}
   581  		log.Panicln("unreachable:", iv)
   582  	}
   583  	switch v := iv.(type) {
   584  	case *ssa.Call:
   585  		cv := v.Call.Value
   586  		kind := p.funcKind(cv)
   587  		if kind == fnIgnore {
   588  			return
   589  		}
   590  		args := v.Call.Args
   591  		if debugGoSSA {
   592  			log.Println(">>> Call", cv, args)
   593  		}
   594  		switch cv := cv.(type) {
   595  		case *ssa.Builtin:
   596  			fn := cv.Name()
   597  			if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
   598  				arg := args[0]
   599  				ret = p.compileValue(b, arg)
   600  				// log.Println("wrapnilchk:", ret.TypeOf())
   601  			} else {
   602  				args := p.compileValues(b, args, kind)
   603  				ret = b.BuiltinCall(fn, args...)
   604  			}
   605  		case *ssa.Function:
   606  			aFn, pyFn, ftype := p.compileFunction(cv)
   607  			switch ftype {
   608  			case goFunc, cFunc:
   609  				args := p.compileValues(b, args, kind)
   610  				ret = b.Call(aFn.Expr, args...)
   611  			case pyFunc:
   612  				args := p.compileValues(b, args, kind)
   613  				ret = b.Call(pyFn.Expr, args...)
   614  			case llgoPyList:
   615  				args := p.compileValues(b, args, fnHasVArg)
   616  				ret = b.PyList(args...)
   617  			case llgoCstr:
   618  				ret = cstr(b, args)
   619  			case llgoAdvance:
   620  				ret = p.advance(b, args)
   621  			case llgoIndex:
   622  				ret = p.index(b, args)
   623  			case llgoAlloca:
   624  				ret = p.alloca(b, args)
   625  			case llgoAllocaCStr:
   626  				ret = p.allocaCStr(b, args)
   627  			case llgoStringData:
   628  				ret = p.stringData(b, args)
   629  			case llgoUnreachable: // func unreachable()
   630  				b.Unreachable()
   631  			default:
   632  				panic("todo")
   633  			}
   634  		default:
   635  			fn := p.compileValue(b, cv)
   636  			args := p.compileValues(b, args, kind)
   637  			ret = b.Call(fn, args...)
   638  		}
   639  	case *ssa.BinOp:
   640  		x := p.compileValue(b, v.X)
   641  		y := p.compileValue(b, v.Y)
   642  		ret = b.BinOp(v.Op, x, y)
   643  	case *ssa.UnOp:
   644  		x := p.compileValue(b, v.X)
   645  		ret = b.UnOp(v.Op, x)
   646  	case *ssa.ChangeType:
   647  		t := v.Type()
   648  		x := p.compileValue(b, v.X)
   649  		ret = b.ChangeType(p.prog.Type(t, llssa.InGo), x)
   650  	case *ssa.Convert:
   651  		t := v.Type()
   652  		x := p.compileValue(b, v.X)
   653  		ret = b.Convert(p.prog.Type(t, llssa.InGo), x)
   654  	case *ssa.FieldAddr:
   655  		x := p.compileValue(b, v.X)
   656  		ret = b.FieldAddr(x, v.Field)
   657  	case *ssa.Alloc:
   658  		t := v.Type().(*types.Pointer)
   659  		if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation
   660  			return
   661  		}
   662  		elem := p.prog.Type(t.Elem(), llssa.InGo)
   663  		ret = b.Alloc(elem, v.Heap)
   664  	case *ssa.IndexAddr:
   665  		vx := v.X
   666  		if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
   667  			return
   668  		}
   669  		x := p.compileValue(b, vx)
   670  		idx := p.compileValue(b, v.Index)
   671  		ret = b.IndexAddr(x, idx)
   672  	case *ssa.Index:
   673  		x := p.compileValue(b, v.X)
   674  		idx := p.compileValue(b, v.Index)
   675  		ret = b.Index(x, idx, func(e llssa.Expr) (ret llssa.Expr) {
   676  			if e == x {
   677  				if n, ok := v.X.(*ssa.UnOp); ok {
   678  					return p.compileValue(b, n.X)
   679  				}
   680  			}
   681  			panic(fmt.Errorf("todo: addr of %v", e))
   682  		})
   683  	case *ssa.Lookup:
   684  		x := p.compileValue(b, v.X)
   685  		idx := p.compileValue(b, v.Index)
   686  		ret = b.Lookup(x, idx, v.CommaOk)
   687  	case *ssa.Slice:
   688  		vx := v.X
   689  		if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
   690  			return
   691  		}
   692  		var low, high, max llssa.Expr
   693  		x := p.compileValue(b, vx)
   694  		if v.Low != nil {
   695  			low = p.compileValue(b, v.Low)
   696  		}
   697  		if v.High != nil {
   698  			high = p.compileValue(b, v.High)
   699  		}
   700  		if v.Max != nil {
   701  			max = p.compileValue(b, v.Max)
   702  		}
   703  		ret = b.Slice(x, low, high, max)
   704  	case *ssa.MakeInterface:
   705  		if refs := *v.Referrers(); len(refs) == 1 {
   706  			if ref, ok := refs[0].(*ssa.Store); ok {
   707  				if va, ok := ref.Addr.(*ssa.IndexAddr); ok {
   708  					if _, ok = p.isVArgs(va.X); ok { // varargs: this is a varargs store
   709  						return
   710  					}
   711  				}
   712  			}
   713  		}
   714  		t := p.prog.Type(v.Type(), llssa.InGo)
   715  		x := p.compileValue(b, v.X)
   716  		ret = b.MakeInterface(t, x)
   717  	case *ssa.MakeSlice:
   718  		var nCap llssa.Expr
   719  		t := p.prog.Type(v.Type(), llssa.InGo)
   720  		nLen := p.compileValue(b, v.Len)
   721  		if v.Cap != nil {
   722  			nCap = p.compileValue(b, v.Cap)
   723  		}
   724  		ret = b.MakeSlice(t, nLen, nCap)
   725  	case *ssa.MakeMap:
   726  		var nReserve llssa.Expr
   727  		t := p.prog.Type(v.Type(), llssa.InGo)
   728  		if v.Reserve != nil {
   729  			nReserve = p.compileValue(b, v.Reserve)
   730  		}
   731  		ret = b.MakeMap(t, nReserve)
   732  	case *ssa.MakeClosure:
   733  		fn := p.compileValue(b, v.Fn)
   734  		bindings := p.compileValues(b, v.Bindings, 0)
   735  		ret = b.MakeClosure(fn, bindings)
   736  	case *ssa.TypeAssert:
   737  		x := p.compileValue(b, v.X)
   738  		t := p.prog.Type(v.AssertedType, llssa.InGo)
   739  		ret = b.TypeAssert(x, t, v.CommaOk)
   740  	case *ssa.Extract:
   741  		x := p.compileValue(b, v.Tuple)
   742  		ret = b.Extract(x, v.Index)
   743  	default:
   744  		panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
   745  	}
   746  	p.bvals[iv] = ret
   747  	return ret
   748  }
   749  
   750  func (p *context) jumpTo(v *ssa.Jump) llssa.BasicBlock {
   751  	fn := p.fn
   752  	succs := v.Block().Succs
   753  	return fn.Block(succs[0].Index)
   754  }
   755  
   756  func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
   757  	if iv, ok := instr.(instrOrValue); ok {
   758  		p.compileInstrOrValue(b, iv, false)
   759  		return
   760  	}
   761  	switch v := instr.(type) {
   762  	case *ssa.Store:
   763  		va := v.Addr
   764  		if va, ok := va.(*ssa.IndexAddr); ok {
   765  			if args, ok := p.isVArgs(va.X); ok { // varargs: this is a varargs store
   766  				idx := intVal(va.Index)
   767  				val := v.Val
   768  				if vi, ok := val.(*ssa.MakeInterface); ok {
   769  					val = vi.X
   770  				}
   771  				args[idx] = p.compileValue(b, val)
   772  				return
   773  			}
   774  		}
   775  		ptr := p.compileValue(b, va)
   776  		val := p.compileValue(b, v.Val)
   777  		b.Store(ptr, val)
   778  	case *ssa.Jump:
   779  		jmpb := p.jumpTo(v)
   780  		b.Jump(jmpb)
   781  	case *ssa.Return:
   782  		var results []llssa.Expr
   783  		if n := len(v.Results); n > 0 {
   784  			results = make([]llssa.Expr, n)
   785  			for i, r := range v.Results {
   786  				results[i] = p.compileValue(b, r)
   787  			}
   788  		}
   789  		if p.inMain(instr) {
   790  			results = make([]llssa.Expr, 1)
   791  			results[0] = p.prog.IntVal(0, p.prog.CInt())
   792  		}
   793  		b.Return(results...)
   794  	case *ssa.If:
   795  		fn := p.fn
   796  		cond := p.compileValue(b, v.Cond)
   797  		succs := v.Block().Succs
   798  		thenb := fn.Block(succs[0].Index)
   799  		elseb := fn.Block(succs[1].Index)
   800  		b.If(cond, thenb, elseb)
   801  	case *ssa.MapUpdate:
   802  		m := p.compileValue(b, v.Map)
   803  		key := p.compileValue(b, v.Key)
   804  		val := p.compileValue(b, v.Value)
   805  		b.MapUpdate(m, key, val)
   806  	case *ssa.Panic:
   807  		arg := p.compileValue(b, v.X).Do(b)
   808  		b.Panic(arg)
   809  	default:
   810  		panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
   811  	}
   812  }
   813  
   814  func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) {
   815  	// v.Pkg == nil: means auto generated function?
   816  	if v.Pkg == p.goPkg || v.Pkg == nil {
   817  		// function in this package
   818  		goFn, pyFn, kind = p.compileFuncDecl(p.pkg, v)
   819  		if kind != ignoredFunc {
   820  			return
   821  		}
   822  	}
   823  	return p.funcOf(v)
   824  }
   825  
   826  func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
   827  	if iv, ok := v.(instrOrValue); ok {
   828  		return p.compileInstrOrValue(b, iv, true)
   829  	}
   830  	switch v := v.(type) {
   831  	case *ssa.Parameter:
   832  		fn := v.Parent()
   833  		for idx, param := range fn.Params {
   834  			if param == v {
   835  				return p.fn.Param(idx)
   836  			}
   837  		}
   838  	case *ssa.Function:
   839  		aFn, pyFn, _ := p.compileFunction(v)
   840  		if aFn != nil {
   841  			return aFn.Expr
   842  		}
   843  		return pyFn.Expr
   844  	case *ssa.Global:
   845  		return p.varOf(b, v)
   846  	case *ssa.Const:
   847  		t := types.Default(v.Type())
   848  		return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
   849  	case *ssa.FreeVar:
   850  		fn := v.Parent()
   851  		for idx, freeVar := range fn.FreeVars {
   852  			if freeVar == v {
   853  				return p.fn.FreeVar(b, idx)
   854  			}
   855  		}
   856  	}
   857  	panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
   858  }
   859  
   860  func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []llssa.Expr {
   861  	_ = b
   862  	switch v := v.(type) {
   863  	case *ssa.Slice: // varargs: this is a varargs slice
   864  		if args, ok := p.isVArgs(v.X); ok {
   865  			return append(ret, args...)
   866  		}
   867  	case *ssa.Const:
   868  		if v.Value == nil {
   869  			return ret
   870  		}
   871  	}
   872  	panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v))
   873  }
   874  
   875  func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) []llssa.Expr {
   876  	n := len(vals) - hasVArg
   877  	ret := make([]llssa.Expr, n)
   878  	for i := 0; i < n; i++ {
   879  		ret[i] = p.compileValue(b, vals[i]).Do(b)
   880  	}
   881  	if hasVArg > 0 {
   882  		ret = p.compileVArg(ret, b, vals[n])
   883  	}
   884  	return ret
   885  }
   886  
   887  // -----------------------------------------------------------------------------
   888  
   889  // NewPackage compiles a Go package to LLVM IR package.
   890  func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
   891  	type namedMember struct {
   892  		name string
   893  		val  ssa.Member
   894  	}
   895  
   896  	members := make([]*namedMember, 0, len(pkg.Members))
   897  	for name, v := range pkg.Members {
   898  		members = append(members, &namedMember{name, v})
   899  	}
   900  	sort.Slice(members, func(i, j int) bool {
   901  		return members[i].name < members[j].name
   902  	})
   903  
   904  	pkgProg := pkg.Prog
   905  	pkgTypes := pkg.Pkg
   906  	pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
   907  	if pkgPath == llssa.PkgRuntime {
   908  		prog.SetRuntime(pkgTypes)
   909  	}
   910  	ret = prog.NewPackage(pkgName, pkgPath)
   911  
   912  	ctx := &context{
   913  		prog:   prog,
   914  		pkg:    ret,
   915  		fset:   pkgProg.Fset,
   916  		goProg: pkgProg,
   917  		goTyps: pkgTypes,
   918  		goPkg:  pkg,
   919  		link:   make(map[string]string),
   920  		vargs:  make(map[*ssa.Alloc][]llssa.Expr),
   921  		loaded: map[*types.Package]*pkgInfo{
   922  			types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
   923  		},
   924  	}
   925  	ctx.initPyModule()
   926  	ctx.initFiles(pkgPath, files)
   927  	for _, m := range members {
   928  		member := m.val
   929  		switch member := member.(type) {
   930  		case *ssa.Function:
   931  			if member.TypeParams() != nil || member.TypeArgs() != nil {
   932  				// TODO(xsw): don't compile generic functions
   933  				// Do not try to build generic (non-instantiated) functions.
   934  				continue
   935  			}
   936  			ctx.compileFuncDecl(ret, member)
   937  		case *ssa.Type:
   938  			ctx.compileType(ret, member)
   939  		case *ssa.Global:
   940  			ctx.compileGlobal(ret, member)
   941  		}
   942  	}
   943  	for len(ctx.inits) > 0 {
   944  		inits := ctx.inits
   945  		ctx.inits = nil
   946  		for _, ini := range inits {
   947  			ini()
   948  		}
   949  	}
   950  	return
   951  }
   952  
   953  // -----------------------------------------------------------------------------