github.com/goplus/llgo@v0.8.3/ssa/package.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 ssa
    18  
    19  import (
    20  	"go/token"
    21  	"go/types"
    22  
    23  	"github.com/goplus/llvm"
    24  	"golang.org/x/tools/go/types/typeutil"
    25  )
    26  
    27  const (
    28  	PkgPython  = "github.com/goplus/llgo/py"
    29  	PkgRuntime = "github.com/goplus/llgo/internal/runtime"
    30  )
    31  
    32  // -----------------------------------------------------------------------------
    33  
    34  type dbgFlags = int
    35  
    36  const (
    37  	DbgFlagInstruction dbgFlags = 1 << iota
    38  
    39  	DbgFlagAll = DbgFlagInstruction
    40  )
    41  
    42  var (
    43  	debugInstr bool
    44  )
    45  
    46  // SetDebug sets debug flags.
    47  func SetDebug(dbgFlags dbgFlags) {
    48  	debugInstr = (dbgFlags & DbgFlagInstruction) != 0
    49  }
    50  
    51  // -----------------------------------------------------------------------------
    52  
    53  // InitFlags is a set of flags for initializing the LLVM library.
    54  type InitFlags int
    55  
    56  const (
    57  	InitNativeTarget InitFlags = 1 << iota
    58  	InitAllTargets
    59  	InitAllTargetInfos
    60  	InitAllTargetMCs
    61  
    62  	InitNativeAsmPrinter
    63  	InitAllAsmPrinters
    64  
    65  	InitAllAsmParsers
    66  
    67  	InitNative = InitNativeTarget | InitNativeAsmPrinter
    68  	InitAll    = InitAllTargets | InitAllAsmParsers | InitAllAsmPrinters | InitAllTargetInfos | InitAllTargetMCs
    69  )
    70  
    71  // Initialize initializes the LLVM library.
    72  func Initialize(flags InitFlags) {
    73  	if flags&InitAllTargetInfos != 0 {
    74  		llvm.InitializeAllTargetInfos()
    75  	}
    76  	if flags&InitAllTargets != 0 {
    77  		llvm.InitializeAllTargets()
    78  	}
    79  	if flags&InitAllTargetMCs != 0 {
    80  		llvm.InitializeAllTargetMCs()
    81  	}
    82  	if flags&InitAllAsmParsers != 0 {
    83  		llvm.InitializeAllAsmParsers()
    84  	}
    85  	if flags&InitAllAsmPrinters != 0 {
    86  		llvm.InitializeAllAsmPrinters()
    87  	}
    88  	if flags&InitNativeTarget != 0 {
    89  		llvm.InitializeNativeTarget()
    90  	}
    91  	if flags&InitNativeAsmPrinter != 0 {
    92  		llvm.InitializeNativeAsmPrinter()
    93  	}
    94  }
    95  
    96  // -----------------------------------------------------------------------------
    97  
    98  type aProgram struct {
    99  	ctx   llvm.Context
   100  	typs  typeutil.Map // rawType -> Type
   101  	gocvt goTypes
   102  
   103  	rt    *types.Package
   104  	rtget func() *types.Package
   105  
   106  	py    *types.Package
   107  	pyget func() *types.Package
   108  
   109  	target *Target
   110  	td     llvm.TargetData
   111  	// tm  llvm.TargetMachine
   112  	named map[string]llvm.Type
   113  
   114  	intType   llvm.Type
   115  	int1Type  llvm.Type
   116  	int8Type  llvm.Type
   117  	int16Type llvm.Type
   118  	int32Type llvm.Type
   119  	int64Type llvm.Type
   120  	voidType  llvm.Type
   121  	voidPtrTy llvm.Type
   122  
   123  	rtStringTy llvm.Type
   124  	rtIfaceTy  llvm.Type
   125  	rtSliceTy  llvm.Type
   126  	rtMapTy    llvm.Type
   127  
   128  	anyTy     Type
   129  	voidTy    Type
   130  	voidPtr   Type
   131  	boolTy    Type
   132  	cstrTy    Type
   133  	cintTy    Type
   134  	stringTy  Type
   135  	uintptrTy Type
   136  	intTy     Type
   137  	uintTy    Type
   138  	f64Ty     Type
   139  	byteTy    Type
   140  	i32Ty     Type
   141  	u32Ty     Type
   142  	i64Ty     Type
   143  	u64Ty     Type
   144  	pyObjPtr  Type
   145  	pyObjPPtr Type
   146  
   147  	pyImpTy    *types.Signature
   148  	pyNewList  *types.Signature
   149  	pyListSetI *types.Signature
   150  	callArgs   *types.Signature
   151  	callNoArgs *types.Signature
   152  	callOneArg *types.Signature
   153  	callFOArgs *types.Signature
   154  	loadPyModS *types.Signature
   155  	getAttrStr *types.Signature
   156  
   157  	paramObjPtr_ *types.Var
   158  
   159  	NeedRuntime bool
   160  	NeedPyInit  bool
   161  }
   162  
   163  // A Program presents a program.
   164  type Program = *aProgram
   165  
   166  // NewProgram creates a new program.
   167  func NewProgram(target *Target) Program {
   168  	if target == nil {
   169  		target = &Target{}
   170  	}
   171  	ctx := llvm.NewContext()
   172  	td := llvm.NewTargetData("") // TODO(xsw): target config
   173  	/*
   174  		arch := target.GOARCH
   175  		if arch == "" {
   176  			arch = runtime.GOARCH
   177  		}
   178  		sizes := types.SizesFor("gc", arch)
   179  
   180  		// TODO(xsw): Finalize may cause panic, so comment it.
   181  		ctx.Finalize()
   182  	*/
   183  	return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td, named: make(map[string]llvm.Type)}
   184  }
   185  
   186  // SetPython sets the Python package.
   187  // Its type can be *types.Package or func() *types.Package.
   188  func (p Program) SetPython(py any) {
   189  	switch v := py.(type) {
   190  	case *types.Package:
   191  		p.py = v
   192  	case func() *types.Package:
   193  		p.pyget = v
   194  	}
   195  }
   196  
   197  // SetRuntime sets the runtime.
   198  // Its type can be *types.Package or func() *types.Package.
   199  func (p Program) SetRuntime(runtime any) {
   200  	switch v := runtime.(type) {
   201  	case *types.Package:
   202  		p.rt = v
   203  	case func() *types.Package:
   204  		p.rtget = v
   205  	}
   206  }
   207  
   208  func (p Program) runtime() *types.Package {
   209  	if p.rt == nil {
   210  		p.rt = p.rtget()
   211  	}
   212  	p.NeedRuntime = true
   213  	return p.rt
   214  }
   215  
   216  func (p Program) python() *types.Package {
   217  	if p.py == nil {
   218  		p.py = p.pyget()
   219  	}
   220  	return p.py
   221  }
   222  
   223  func (p Program) rtNamed(name string) *types.Named {
   224  	t := p.runtime().Scope().Lookup(name).Type().(*types.Named)
   225  	t, _ = p.gocvt.cvtNamed(t)
   226  	return t
   227  }
   228  
   229  func (p Program) pyNamed(name string) *types.Named {
   230  	// TODO(xsw): does python type need to convert?
   231  	t := p.python().Scope().Lookup(name).Type().(*types.Named)
   232  	return t
   233  }
   234  
   235  func (p Program) rtType(name string) Type {
   236  	return p.rawType(p.rtNamed(name))
   237  }
   238  
   239  func (p Program) rtIface() llvm.Type {
   240  	if p.rtIfaceTy.IsNil() {
   241  		p.rtIfaceTy = p.rtType("Interface").ll
   242  	}
   243  	return p.rtIfaceTy
   244  }
   245  
   246  func (p Program) rtMap() llvm.Type {
   247  	if p.rtMapTy.IsNil() {
   248  		p.rtMapTy = p.rtType("Map").ll
   249  	}
   250  	return p.rtMapTy
   251  }
   252  
   253  func (p Program) rtSlice() llvm.Type {
   254  	if p.rtSliceTy.IsNil() {
   255  		p.rtSliceTy = p.rtType("Slice").ll
   256  	}
   257  	return p.rtSliceTy
   258  }
   259  
   260  func (p Program) rtString() llvm.Type {
   261  	if p.rtStringTy.IsNil() {
   262  		p.rtStringTy = p.rtType("String").ll
   263  	}
   264  	return p.rtStringTy
   265  }
   266  
   267  // NewPackage creates a new package.
   268  func (p Program) NewPackage(name, pkgPath string) Package {
   269  	mod := p.ctx.NewModule(pkgPath)
   270  	// TODO(xsw): Finalize may cause panic, so comment it.
   271  	// mod.Finalize()
   272  	gbls := make(map[string]Global)
   273  	fns := make(map[string]Function)
   274  	stubs := make(map[string]Function)
   275  	pyobjs := make(map[string]PyObjRef)
   276  	pymods := make(map[string]Global)
   277  	p.NeedRuntime = false
   278  	// Don't need reset p.needPyInit here
   279  	// p.needPyInit = false
   280  	return &aPackage{mod, gbls, fns, stubs, pyobjs, pymods, p}
   281  }
   282  
   283  // PyObjectPtrPtr returns the **py.Object type.
   284  func (p Program) PyObjectPtrPtr() Type {
   285  	if p.pyObjPPtr == nil {
   286  		p.pyObjPPtr = p.Pointer(p.PyObjectPtr())
   287  	}
   288  	return p.pyObjPPtr
   289  }
   290  
   291  // PyObjectPtr returns the *py.Object type.
   292  func (p Program) PyObjectPtr() Type {
   293  	if p.pyObjPtr == nil {
   294  		objPtr := types.NewPointer(p.pyNamed("Object"))
   295  		p.pyObjPtr = p.rawType(objPtr)
   296  	}
   297  	return p.pyObjPtr
   298  }
   299  
   300  // Void returns void type.
   301  func (p Program) Void() Type {
   302  	if p.voidTy == nil {
   303  		p.voidTy = &aType{p.tyVoid(), rawType{types.Typ[types.Invalid]}, vkInvalid}
   304  	}
   305  	return p.voidTy
   306  }
   307  
   308  func (p Program) VoidPtr() Type {
   309  	if p.voidPtr == nil {
   310  		p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
   311  	}
   312  	return p.voidPtr
   313  }
   314  
   315  // Bool returns bool type.
   316  func (p Program) Bool() Type {
   317  	if p.boolTy == nil {
   318  		p.boolTy = p.rawType(types.Typ[types.Bool])
   319  	}
   320  	return p.boolTy
   321  }
   322  
   323  func (p Program) CStr() Type {
   324  	if p.cstrTy == nil { // *int8
   325  		p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
   326  	}
   327  	return p.cstrTy
   328  }
   329  
   330  func (p Program) String() Type {
   331  	if p.stringTy == nil {
   332  		p.stringTy = p.rawType(types.Typ[types.String])
   333  	}
   334  	return p.stringTy
   335  }
   336  
   337  // Any returns any type.
   338  func (p Program) Any() Type {
   339  	if p.anyTy == nil {
   340  		p.anyTy = p.rawType(tyAny)
   341  	}
   342  	return p.anyTy
   343  }
   344  
   345  func (p Program) CInt() Type {
   346  	if p.cintTy == nil { // C.int
   347  		p.cintTy = p.rawType(types.Typ[types.Int32]) // TODO(xsw): support 64-bit
   348  	}
   349  	return p.cintTy
   350  }
   351  
   352  // Int returns int type.
   353  func (p Program) Int() Type {
   354  	if p.intTy == nil {
   355  		p.intTy = p.rawType(types.Typ[types.Int])
   356  	}
   357  	return p.intTy
   358  }
   359  
   360  // Uint returns uint type.
   361  func (p Program) Uint() Type {
   362  	if p.uintTy == nil {
   363  		p.uintTy = p.rawType(types.Typ[types.Uint])
   364  	}
   365  	return p.uintTy
   366  }
   367  
   368  // Uintptr returns uintptr type.
   369  func (p Program) Uintptr() Type {
   370  	if p.uintptrTy == nil {
   371  		p.uintptrTy = p.rawType(types.Typ[types.Uintptr])
   372  	}
   373  	return p.uintptrTy
   374  }
   375  
   376  // Float64 returns float64 type.
   377  func (p Program) Float64() Type {
   378  	if p.f64Ty == nil {
   379  		p.f64Ty = p.rawType(types.Typ[types.Float64])
   380  	}
   381  	return p.f64Ty
   382  }
   383  
   384  // Byte returns byte type.
   385  func (p Program) Byte() Type {
   386  	if p.byteTy == nil {
   387  		p.byteTy = p.rawType(types.Typ[types.Byte])
   388  	}
   389  	return p.byteTy
   390  }
   391  
   392  // Int32 returns int32 type.
   393  func (p Program) Int32() Type {
   394  	if p.i32Ty == nil {
   395  		p.i32Ty = p.rawType(types.Typ[types.Int32])
   396  	}
   397  	return p.i32Ty
   398  }
   399  
   400  // Uint32 returns uint32 type.
   401  func (p Program) Uint32() Type {
   402  	if p.u32Ty == nil {
   403  		p.u32Ty = p.rawType(types.Typ[types.Uint32])
   404  	}
   405  	return p.u32Ty
   406  }
   407  
   408  // Int64 returns int64 type.
   409  func (p Program) Int64() Type {
   410  	if p.i64Ty == nil {
   411  		p.i64Ty = p.rawType(types.Typ[types.Int64])
   412  	}
   413  	return p.i64Ty
   414  }
   415  
   416  // Uint64 returns uint64 type.
   417  func (p Program) Uint64() Type {
   418  	if p.u64Ty == nil {
   419  		p.u64Ty = p.rawType(types.Typ[types.Uint64])
   420  	}
   421  	return p.u64Ty
   422  }
   423  
   424  // -----------------------------------------------------------------------------
   425  
   426  // A Package is a single analyzed Go package containing Members for
   427  // all package-level functions, variables, constants and types it
   428  // declares.  These may be accessed directly via Members, or via the
   429  // type-specific accessor methods Func, Type, Var and Const.
   430  //
   431  // Members also contains entries for "init" (the synthetic package
   432  // initializer) and "init#%d", the nth declared init function,
   433  // and unspecified other things too.
   434  type aPackage struct {
   435  	mod    llvm.Module
   436  	vars   map[string]Global
   437  	fns    map[string]Function
   438  	stubs  map[string]Function
   439  	pyobjs map[string]PyObjRef
   440  	pymods map[string]Global
   441  	Prog   Program
   442  }
   443  
   444  type Package = *aPackage
   445  
   446  /*
   447  // NewConst creates a new named constant.
   448  func (p Package) NewConst(name string, val constant.Value) NamedConst {
   449  	return &aNamedConst{}
   450  }
   451  */
   452  
   453  func (p Package) rtFunc(fnName string) Expr {
   454  	fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
   455  	name := FullName(fn.Pkg(), fnName)
   456  	sig := fn.Type().(*types.Signature)
   457  	return p.NewFunc(name, sig, InGo).Expr
   458  }
   459  
   460  func (p Package) pyFunc(fullName string, sig *types.Signature) Expr {
   461  	p.Prog.NeedPyInit = true
   462  	return p.NewFunc(fullName, sig, InC).Expr
   463  }
   464  
   465  func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
   466  	name := v.impl.Name()
   467  	prog := b.Prog
   468  	nilVal := prog.Null(prog.VoidPtr()).impl
   469  	if fn, ok := p.stubs[name]; ok {
   470  		v = fn.Expr
   471  	} else {
   472  		sig := v.raw.Type.(*types.Signature)
   473  		n := sig.Params().Len()
   474  		nret := sig.Results().Len()
   475  		ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer])
   476  		sig = FuncAddCtx(ctx, sig)
   477  		fn := p.NewFunc(ClosureStub+name, sig, InC)
   478  		fn.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
   479  		args := make([]Expr, n)
   480  		for i := 0; i < n; i++ {
   481  			args[i] = fn.Param(i + 1)
   482  		}
   483  		b := fn.MakeBody(1)
   484  		call := b.Call(v, args...)
   485  		call.impl.SetTailCall(true)
   486  		switch nret {
   487  		case 0:
   488  			b.impl.CreateRetVoid()
   489  		default: // TODO(xsw): support multiple return values
   490  			b.impl.CreateRet(call.impl)
   491  		}
   492  		p.stubs[name] = fn
   493  		v = fn.Expr
   494  	}
   495  	return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
   496  }
   497  
   498  // -----------------------------------------------------------------------------
   499  
   500  // String returns a string representation of the package.
   501  func (p Package) String() string {
   502  	return p.mod.String()
   503  }
   504  
   505  /*
   506  type CodeGenFileType = llvm.CodeGenFileType
   507  
   508  const (
   509  	AssemblyFile = llvm.AssemblyFile
   510  	ObjectFile   = llvm.ObjectFile
   511  )
   512  
   513  func (p *Package) CodeGen(ft CodeGenFileType) (ret []byte, err error) {
   514  	buf, err := p.prog.targetMachine().EmitToMemoryBuffer(p.mod, ft)
   515  	if err != nil {
   516  		return
   517  	}
   518  	ret = buf.Bytes()
   519  	buf.Dispose()
   520  	return
   521  }
   522  
   523  func (p *Package) Bitcode() []byte {
   524  	buf := llvm.WriteBitcodeToMemoryBuffer(p.mod)
   525  	ret := buf.Bytes()
   526  	buf.Dispose()
   527  	return ret
   528  }
   529  
   530  func (p *Package) WriteTo(w io.Writer) (int64, error) {
   531  	n, err := w.Write(p.Bitcode())
   532  	return int64(n), err
   533  }
   534  
   535  func (p *Package) WriteFile(file string) (err error) {
   536  	f, err := os.Create(file)
   537  	if err != nil {
   538  		return
   539  	}
   540  	defer f.Close()
   541  	return llvm.WriteBitcodeToFile(p.mod, f)
   542  }
   543  */
   544  
   545  // -----------------------------------------------------------------------------
   546  
   547  func (p Program) paramObjPtr() *types.Var {
   548  	if p.paramObjPtr_ == nil {
   549  		objPtr := p.PyObjectPtr().raw.Type
   550  		p.paramObjPtr_ = types.NewParam(token.NoPos, nil, "", objPtr)
   551  	}
   552  	return p.paramObjPtr_
   553  }
   554  
   555  // func(*char) *Object
   556  func (p Program) tyImportPyModule() *types.Signature {
   557  	if p.pyImpTy == nil {
   558  		charPtr := types.NewPointer(types.Typ[types.Int8])
   559  		params := types.NewTuple(types.NewParam(token.NoPos, nil, "", charPtr))
   560  		results := types.NewTuple(p.paramObjPtr())
   561  		p.pyImpTy = types.NewSignatureType(nil, nil, nil, params, results, false)
   562  	}
   563  	return p.pyImpTy
   564  }
   565  
   566  // func(*Object) *Object
   567  func (p Program) tyCallNoArgs() *types.Signature {
   568  	if p.callNoArgs == nil {
   569  		params := types.NewTuple(p.paramObjPtr())
   570  		p.callNoArgs = types.NewSignatureType(nil, nil, nil, params, params, false)
   571  	}
   572  	return p.callNoArgs
   573  }
   574  
   575  // func(*Object, *Object) *Object
   576  func (p Program) tyCallOneArg() *types.Signature {
   577  	if p.callOneArg == nil {
   578  		paramObjPtr := p.paramObjPtr()
   579  		params := types.NewTuple(paramObjPtr, paramObjPtr)
   580  		results := types.NewTuple(paramObjPtr)
   581  		p.callOneArg = types.NewSignatureType(nil, nil, nil, params, results, false)
   582  	}
   583  	return p.callOneArg
   584  }
   585  
   586  // func(*Object, ...) *Object
   587  func (p Program) tyCallFunctionObjArgs() *types.Signature {
   588  	if p.callFOArgs == nil {
   589  		paramObjPtr := p.paramObjPtr()
   590  		params := types.NewTuple(paramObjPtr, VArg())
   591  		results := types.NewTuple(paramObjPtr)
   592  		p.callFOArgs = types.NewSignatureType(nil, nil, nil, params, results, true)
   593  	}
   594  	return p.callFOArgs
   595  }
   596  
   597  /*
   598  // func(*Object, *Object, *Object) *Object
   599  func (p Program) tyCall() *types.Signature {
   600  	if p.callArgs == nil {
   601  		paramObjPtr := p.paramObjPtr()
   602  		params := types.NewTuple(paramObjPtr, paramObjPtr, paramObjPtr)
   603  		results := types.NewTuple(paramObjPtr)
   604  		p.callArgs = types.NewSignatureType(nil, nil, nil, params, results, false)
   605  	}
   606  	return p.callArgs
   607  }
   608  */
   609  
   610  // func(*Object, uintptr, *Object) cint
   611  func (p Program) tyListSetItem() *types.Signature {
   612  	if p.pyListSetI == nil {
   613  		paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type)
   614  		paramCInt := types.NewParam(token.NoPos, nil, "", p.CInt().raw.Type)
   615  		paramObjPtr := p.paramObjPtr()
   616  		params := types.NewTuple(paramObjPtr, paramUintptr, paramObjPtr)
   617  		results := types.NewTuple(paramCInt)
   618  		p.pyListSetI = types.NewSignatureType(nil, nil, nil, params, results, false)
   619  	}
   620  	return p.pyListSetI
   621  }
   622  
   623  // func(uintptr) *Object
   624  func (p Program) tyNewList() *types.Signature {
   625  	if p.pyNewList == nil {
   626  		paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type)
   627  		params := types.NewTuple(paramUintptr)
   628  		results := types.NewTuple(p.paramObjPtr())
   629  		p.pyNewList = types.NewSignatureType(nil, nil, nil, params, results, false)
   630  	}
   631  	return p.pyNewList
   632  }
   633  
   634  // func(float64) *Object
   635  func (p Program) tyFloatFromDouble() *types.Signature {
   636  	if p.callArgs == nil {
   637  		paramObjPtr := p.paramObjPtr()
   638  		paramFloat := types.NewParam(token.NoPos, nil, "", p.Float64().raw.Type)
   639  		params := types.NewTuple(paramFloat)
   640  		results := types.NewTuple(paramObjPtr)
   641  		p.callArgs = types.NewSignatureType(nil, nil, nil, params, results, false)
   642  	}
   643  	return p.callArgs
   644  }
   645  
   646  // func(*Object, ...)
   647  func (p Program) tyLoadPyModSyms() *types.Signature {
   648  	if p.loadPyModS == nil {
   649  		paramObjPtr := p.paramObjPtr()
   650  		params := types.NewTuple(paramObjPtr, VArg())
   651  		p.loadPyModS = types.NewSignatureType(nil, nil, nil, params, nil, true)
   652  	}
   653  	return p.loadPyModS
   654  }
   655  
   656  // func(*Objecg, *char) *Object
   657  func (p Program) tyGetAttrString() *types.Signature {
   658  	if p.getAttrStr == nil {
   659  		charPtr := types.NewPointer(types.Typ[types.Int8])
   660  		paramObjPtr := p.paramObjPtr()
   661  		params := types.NewTuple(paramObjPtr, types.NewParam(token.NoPos, nil, "", charPtr))
   662  		results := types.NewTuple(paramObjPtr)
   663  		p.getAttrStr = types.NewSignatureType(nil, nil, nil, params, results, false)
   664  	}
   665  	return p.getAttrStr
   666  }
   667  
   668  // PyInit initializes Python for a main package.
   669  func (p Package) PyInit() bool {
   670  	if fn := p.FuncOf("main"); fn != nil {
   671  		b := fn.NewBuilder()
   672  		b.SetBlockEx(fn.Block(0), AtStart).callPyInit()
   673  		b.Dispose()
   674  		return true
   675  	}
   676  	return false
   677  }
   678  
   679  // PyNewModVar creates a new global variable for a Python module.
   680  func (p Package) PyNewModVar(name string, doInit bool) Global {
   681  	if v, ok := p.pymods[name]; ok {
   682  		return v
   683  	}
   684  	prog := p.Prog
   685  	objPtr := prog.PyObjectPtrPtr().raw.Type
   686  	g := p.NewVar(name, objPtr, InC)
   687  	if doInit {
   688  		g.Init(prog.Null(g.Type))
   689  		g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
   690  	}
   691  	p.pymods[name] = g
   692  	return g
   693  }
   694  
   695  // PyImportMod imports a Python module.
   696  func (b Builder) PyImportMod(path string) Expr {
   697  	pkg := b.Func.Pkg
   698  	fnImp := pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule())
   699  	return b.Call(fnImp, b.CStr(path))
   700  }
   701  
   702  // PyLoadModSyms loads python objects from specified module.
   703  func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr {
   704  	pkg := b.Func.Pkg
   705  	fnLoad := pkg.pyFunc("llgoLoadPyModSyms", b.Prog.tyLoadPyModSyms())
   706  	modPtr := pkg.PyNewModVar(modName, false).Expr
   707  	mod := b.Load(modPtr)
   708  	args := make([]Expr, 1, len(objs)*2+2)
   709  	args[0] = mod
   710  	nbase := len(modName) + 1
   711  	for _, o := range objs {
   712  		fullName := o.impl.Name()
   713  		name := fullName[nbase:]
   714  		args = append(args, b.CStr(name))
   715  		args = append(args, o.Expr)
   716  	}
   717  	prog := b.Prog
   718  	args = append(args, prog.Null(prog.CStr()))
   719  	return b.Call(fnLoad, args...)
   720  }
   721  
   722  func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) {
   723  	prog := b.Prog
   724  	pkg := b.Func.Pkg
   725  	fn = b.Load(fn)
   726  	sig := fn.raw.Type.(*types.Signature)
   727  	params := sig.Params()
   728  	n := params.Len()
   729  	switch n {
   730  	case 0:
   731  		call := pkg.pyFunc("PyObject_CallNoArgs", prog.tyCallNoArgs())
   732  		ret = b.Call(call, fn)
   733  	case 1:
   734  		if !sig.Variadic() {
   735  			call := pkg.pyFunc("PyObject_CallOneArg", prog.tyCallOneArg())
   736  			return b.Call(call, fn, args[0])
   737  		}
   738  		fallthrough
   739  	default:
   740  		call := pkg.pyFunc("PyObject_CallFunctionObjArgs", prog.tyCallFunctionObjArgs())
   741  		n = len(args)
   742  		callargs := make([]Expr, n+2)
   743  		callargs[0] = fn
   744  		copy(callargs[1:], args)
   745  		callargs[n+1] = prog.PyNull()
   746  		ret = b.Call(call, callargs...)
   747  	}
   748  	return
   749  }
   750  
   751  // PyNewList(n uintptr) *Object
   752  func (b Builder) PyNewList(n Expr) (ret Expr) {
   753  	prog := b.Prog
   754  	pkg := b.Func.Pkg
   755  	fn := pkg.pyFunc("PyList_New", prog.tyNewList())
   756  	return b.Call(fn, n)
   757  }
   758  
   759  // PyListSetItem(list *Object, index uintptr, item *Object) c.Int
   760  func (b Builder) PyListSetItem(list, index, item Expr) (ret Expr) {
   761  	prog := b.Prog
   762  	pkg := b.Func.Pkg
   763  	fn := pkg.pyFunc("PyList_SetItem", prog.tyListSetItem())
   764  	return b.Call(fn, list, index, item)
   765  }
   766  
   767  // PyList(args ...Expr) *Object
   768  func (b Builder) PyList(args ...Expr) (ret Expr) {
   769  	prog := b.Prog
   770  	n := len(args)
   771  	uintPtr := prog.Uintptr()
   772  	list := b.PyNewList(prog.IntVal(uint64(n), uintPtr))
   773  	for i, arg := range args {
   774  		b.PyListSetItem(list, prog.IntVal(uint64(i), uintPtr), b.PyVal(arg))
   775  	}
   776  	return list
   777  }
   778  
   779  // PyVal(v any) *Object
   780  func (b Builder) PyVal(v Expr) (ret Expr) {
   781  	switch t := v.raw.Type.(type) {
   782  	case *types.Basic:
   783  		switch t.Kind() {
   784  		case types.Float64:
   785  			return b.PyFloat(v)
   786  		default:
   787  			panic("PyVal: todo")
   788  		}
   789  	default:
   790  		return v
   791  	}
   792  }
   793  
   794  // PyFloat(fltVal float64) *Object
   795  func (b Builder) PyFloat(fltVal Expr) (ret Expr) {
   796  	prog := b.Prog
   797  	pkg := b.Func.Pkg
   798  	fn := pkg.pyFunc("PyFloat_FromDouble", prog.tyFloatFromDouble())
   799  	return b.Call(fn, fltVal)
   800  }
   801  
   802  // callPyInit calls Py_Initialize.
   803  func (b Builder) callPyInit() (ret Expr) {
   804  	fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet)
   805  	return b.Call(fn)
   806  }
   807  
   808  var (
   809  	NoArgsNoRet = types.NewSignatureType(nil, nil, nil, nil, nil, false)
   810  )
   811  
   812  // -----------------------------------------------------------------------------