Files
llgo/compiler/ssa/package.go

796 lines
18 KiB
Go
Raw Normal View History

2024-04-15 04:00:38 +08:00
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2024-04-15 17:12:30 +08:00
package ssa
2024-04-15 04:00:38 +08:00
import (
"fmt"
2024-05-05 18:48:09 +08:00
"go/token"
2024-04-15 04:00:38 +08:00
"go/types"
"runtime"
2024-05-26 16:18:24 +08:00
"strconv"
2024-06-02 21:54:51 +08:00
"unsafe"
2024-04-15 04:00:38 +08:00
"github.com/goplus/llgo/compiler/internal/env"
2025-01-07 21:49:08 +08:00
"github.com/goplus/llgo/compiler/ssa/abi"
2024-04-15 05:48:48 +08:00
"github.com/goplus/llvm"
2024-05-06 00:17:39 +08:00
"golang.org/x/tools/go/types/typeutil"
2024-04-15 04:00:38 +08:00
)
const (
PkgPython = "github.com/goplus/llgo/py"
PkgRuntime = env.LLGoRuntimePkg + "/internal/runtime"
)
2024-04-21 16:04:05 +08:00
// -----------------------------------------------------------------------------
2024-04-21 15:12:57 +08:00
type dbgFlags = int
const (
DbgFlagInstruction dbgFlags = 1 << iota
DbgFlagAll = DbgFlagInstruction
)
var (
debugInstr bool
)
// SetDebug sets debug flags.
func SetDebug(dbgFlags dbgFlags) {
debugInstr = (dbgFlags & DbgFlagInstruction) != 0
}
2024-04-19 00:05:57 +08:00
// -----------------------------------------------------------------------------
2024-04-20 23:57:55 +08:00
// InitFlags is a set of flags for initializing the LLVM library.
2024-04-19 00:05:57 +08:00
type InitFlags int
const (
InitNativeTarget InitFlags = 1 << iota
InitAllTargets
InitAllTargetInfos
InitAllTargetMCs
InitNativeAsmPrinter
InitAllAsmPrinters
InitAllAsmParsers
InitNative = InitNativeTarget | InitNativeAsmPrinter
InitAll = InitAllTargets | InitAllAsmParsers | InitAllAsmPrinters | InitAllTargetInfos | InitAllTargetMCs
)
2024-04-20 23:57:55 +08:00
// Initialize initializes the LLVM library.
2024-04-19 00:05:57 +08:00
func Initialize(flags InitFlags) {
if flags&InitAllTargetInfos != 0 {
llvm.InitializeAllTargetInfos()
}
if flags&InitAllTargets != 0 {
llvm.InitializeAllTargets()
}
if flags&InitAllTargetMCs != 0 {
llvm.InitializeAllTargetMCs()
}
if flags&InitAllAsmParsers != 0 {
llvm.InitializeAllAsmParsers()
}
if flags&InitAllAsmPrinters != 0 {
llvm.InitializeAllAsmPrinters()
}
if flags&InitNativeTarget != 0 {
llvm.InitializeNativeTarget()
}
if flags&InitNativeAsmPrinter != 0 {
llvm.InitializeNativeAsmPrinter()
}
}
// -----------------------------------------------------------------------------
2024-04-18 01:23:01 +08:00
type aProgram struct {
2024-05-05 12:11:51 +08:00
ctx llvm.Context
typs typeutil.Map // rawType -> Type
2024-05-28 16:59:47 +08:00
sizes types.Sizes // provided by Go compiler
2024-05-05 12:11:51 +08:00
gocvt goTypes
2024-04-15 17:12:30 +08:00
2024-11-25 11:17:06 +08:00
patchType func(types.Type) types.Type
rt *types.Package
2024-04-27 17:39:25 +08:00
rtget func() *types.Package
2024-04-27 13:57:21 +08:00
py *types.Package
pyget func() *types.Package
2024-04-15 17:12:30 +08:00
target *Target
td llvm.TargetData
2024-04-16 00:43:29 +08:00
// tm llvm.TargetMachine
2024-05-31 14:22:17 +08:00
named map[string]llvm.Type
fnnamed map[string]int
2024-04-15 04:00:38 +08:00
intType llvm.Type
2024-04-18 15:03:10 +08:00
int1Type llvm.Type
2024-04-15 04:00:38 +08:00
int8Type llvm.Type
int16Type llvm.Type
int32Type llvm.Type
int64Type llvm.Type
2024-04-16 03:05:20 +08:00
voidType llvm.Type
voidPtrTy llvm.Type
2024-04-18 15:03:10 +08:00
c64Type llvm.Type
c128Type llvm.Type
2024-05-04 07:47:18 +08:00
rtStringTy llvm.Type
2024-05-22 13:47:21 +08:00
rtEfaceTy llvm.Type
rtIfaceTy llvm.Type
2024-05-04 07:47:18 +08:00
rtSliceTy llvm.Type
rtMapTy llvm.Type
2024-07-02 20:12:12 +08:00
rtChanTy llvm.Type
2024-04-27 18:13:16 +08:00
anyTy Type
voidTy Type
voidPtr Type
voidPPtr Type
boolTy Type
cstrTy Type
cintTy Type
cintPtr Type
stringTy Type
2024-04-28 07:08:01 +08:00
uintptrTy Type
intTy Type
uintTy Type
2024-04-28 07:08:01 +08:00
f64Ty Type
f32Ty Type
c128Ty Type
c64Ty Type
byteTy Type
i32Ty Type
u32Ty Type
i64Ty Type
u64Ty Type
2024-06-02 14:29:35 +08:00
pyObjPtr Type
pyObjPPtr Type
2024-06-02 14:29:35 +08:00
abiTyPtr Type
abiTyPPtr Type
deferTy Type
deferPtr Type
pyImpTy *types.Signature
pyNewList *types.Signature
pyListSetI *types.Signature
pyNewTuple *types.Signature
pyTupleSetI *types.Signature
2024-06-02 14:29:35 +08:00
floatFromDbl *types.Signature
callNoArgs *types.Signature
callOneArg *types.Signature
callFOArgs *types.Signature
loadPyModS *types.Signature
getAttrStr *types.Signature
pyUniStr *types.Signature
2024-04-29 00:49:17 +08:00
mallocTy *types.Signature
freeTy *types.Signature
memsetInlineTy *types.Signature
2024-06-02 14:29:35 +08:00
createKeyTy *types.Signature
getSpecTy *types.Signature
setSpecTy *types.Signature
routineTy *types.Signature
2024-06-02 14:29:35 +08:00
destructTy *types.Signature
sigsetjmpTy *types.Signature
sigljmpTy *types.Signature
2024-05-15 08:44:00 +08:00
paramObjPtr_ *types.Var
linkname map[string]string // pkgPath.nameInPkg => linkname
2024-05-15 08:44:00 +08:00
2024-05-28 17:55:26 +08:00
ptrSize int
2024-05-12 15:42:50 +08:00
NeedRuntime bool
NeedPyInit bool
is32Bits bool
2024-04-15 04:00:38 +08:00
}
2024-04-20 23:57:55 +08:00
// A Program presents a program.
2024-04-18 01:23:01 +08:00
type Program = *aProgram
2024-04-18 01:18:41 +08:00
2024-04-20 23:57:55 +08:00
// NewProgram creates a new program.
2024-04-18 01:18:41 +08:00
func NewProgram(target *Target) Program {
2024-04-15 17:12:30 +08:00
if target == nil {
target = &Target{
GOOS: runtime.GOOS,
GOARCH: runtime.GOARCH,
}
2024-04-15 17:12:30 +08:00
}
2024-04-15 04:00:38 +08:00
ctx := llvm.NewContext()
2024-05-26 21:57:07 +08:00
td := target.targetData() // TODO(xsw): target config
2024-05-03 23:10:02 +08:00
/*
arch := target.GOARCH
if arch == "" {
arch = runtime.GOARCH
}
sizes := types.SizesFor("gc", arch)
// TODO(xsw): Finalize may cause panic, so comment it.
ctx.Finalize()
*/
is32Bits := (td.PointerSize() == 4 || target.GOARCH == "x86") // TODO(xsw): remove temp code
return &aProgram{
ctx: ctx, gocvt: newGoTypes(),
target: target, td: td, is32Bits: is32Bits,
2024-05-31 14:22:17 +08:00
ptrSize: td.PointerSize(), named: make(map[string]llvm.Type), fnnamed: make(map[string]int),
linkname: make(map[string]string),
}
2024-04-15 04:00:38 +08:00
}
2024-11-25 11:17:06 +08:00
func (p Program) SetPatch(patchType func(types.Type) types.Type) {
p.patchType = patchType
}
func (p Program) patch(typ types.Type) types.Type {
if p.patchType != nil {
return p.patchType(typ)
}
return typ
}
2024-04-27 17:39:25 +08:00
// SetRuntime sets the runtime.
// Its type can be *types.Package or func() *types.Package.
func (p Program) SetRuntime(runtime any) {
switch v := runtime.(type) {
case *types.Package:
p.rt = v
case func() *types.Package:
p.rtget = v
}
2024-04-27 13:57:21 +08:00
}
func (p Program) SetTypeBackground(fullName string, bg Background) {
p.gocvt.typbg.Store(fullName, bg)
}
func (p Program) SetLinkname(name, link string) {
p.linkname[name] = link
}
func (p Program) Linkname(name string) (link string, ok bool) {
link, ok = p.linkname[name]
return
}
func (p Program) runtime() *types.Package {
2024-04-27 13:57:21 +08:00
if p.rt == nil {
p.rt = p.rtget()
2024-04-27 13:57:21 +08:00
}
2024-05-12 15:42:50 +08:00
p.NeedRuntime = true
2024-04-27 13:57:21 +08:00
return p.rt
}
2024-04-27 18:13:16 +08:00
func (p Program) rtNamed(name string) *types.Named {
if rt := p.runtime(); rt != nil {
if rtScope := rt.Scope(); rtScope != nil {
if obj := rtScope.Lookup(name); obj != nil {
t := obj.Type()
for {
if alias, ok := t.(*types.Alias); ok {
t = types.Unalias(alias)
} else {
break
}
}
t, _ = p.gocvt.cvtNamed(t.(*types.Named))
return t.(*types.Named)
}
}
}
panic(fmt.Errorf("runtime type (%s) not found, install from pre-built package or set LLGO_ROOT", name))
2024-04-27 17:39:25 +08:00
}
2024-04-27 18:13:16 +08:00
func (p Program) rtType(name string) Type {
2024-05-05 12:11:51 +08:00
return p.rawType(p.rtNamed(name))
2024-04-27 18:13:16 +08:00
}
func (p Program) rtEface() llvm.Type {
2024-05-22 13:47:21 +08:00
if p.rtEfaceTy.IsNil() {
p.rtEfaceTy = p.rtType("Eface").ll
2024-04-27 18:13:16 +08:00
}
2024-05-22 13:47:21 +08:00
return p.rtEfaceTy
2024-04-27 18:13:16 +08:00
}
func (p Program) rtIface() llvm.Type {
if p.rtIfaceTy.IsNil() {
p.rtIfaceTy = p.rtType("Iface").ll
}
return p.rtIfaceTy
}
2024-05-01 07:26:51 +08:00
func (p Program) rtMap() llvm.Type {
if p.rtMapTy.IsNil() {
p.rtMapTy = p.rtType("Map").ll
}
return p.rtMapTy
}
2024-04-27 18:13:16 +08:00
func (p Program) rtSlice() llvm.Type {
if p.rtSliceTy.IsNil() {
p.rtSliceTy = p.rtType("Slice").ll
}
return p.rtSliceTy
}
func (p Program) rtString() llvm.Type {
if p.rtStringTy.IsNil() {
p.rtStringTy = p.rtType("String").ll
}
return p.rtStringTy
}
2024-07-02 20:12:12 +08:00
func (p Program) rtChan() llvm.Type {
if p.rtChanTy.IsNil() {
p.rtChanTy = p.rtType("Chan").ll
}
return p.rtChanTy
}
func (p Program) tyComplex64() llvm.Type {
if p.c64Type.IsNil() {
ctx := p.ctx
f32 := ctx.FloatType()
p.c64Type = ctx.StructType([]llvm.Type{f32, f32}, false)
}
return p.c64Type
}
func (p Program) tyComplex128() llvm.Type {
if p.c128Type.IsNil() {
ctx := p.ctx
f64 := ctx.DoubleType()
p.c128Type = ctx.StructType([]llvm.Type{f64, f64}, false)
}
return p.c128Type
}
2024-04-20 23:57:55 +08:00
// NewPackage creates a new package.
2024-04-18 15:03:10 +08:00
func (p Program) NewPackage(name, pkgPath string) Package {
2024-04-15 05:48:48 +08:00
mod := p.ctx.NewModule(pkgPath)
// TODO(xsw): Finalize may cause panic, so comment it.
// mod.Finalize()
2024-04-21 15:12:57 +08:00
gbls := make(map[string]Global)
2024-05-05 18:48:09 +08:00
fns := make(map[string]Function)
stubs := make(map[string]Function)
2024-05-12 23:08:44 +08:00
pyobjs := make(map[string]PyObjRef)
2024-05-12 11:11:19 +08:00
pymods := make(map[string]Global)
strs := make(map[string]llvm.Value)
goStrs := make(map[string]llvm.Value)
2024-10-10 16:07:52 +08:00
chkabi := make(map[types.Type]bool)
2024-09-19 10:29:11 +08:00
glbDbgVars := make(map[Expr]bool)
2024-05-12 15:42:50 +08:00
p.NeedRuntime = false
2024-05-12 11:11:19 +08:00
// Don't need reset p.needPyInit here
// p.needPyInit = false
ret := &aPackage{
mod: mod, vars: gbls, fns: fns, stubs: stubs,
pyobjs: pyobjs, pymods: pymods, strs: strs, goStrs: goStrs,
chkabi: chkabi, Prog: p,
2024-09-19 10:29:11 +08:00
di: nil, cu: nil, glbDbgVars: glbDbgVars,
}
2024-05-23 01:34:48 +08:00
ret.abi.Init(pkgPath)
return ret
}
2024-05-26 16:18:24 +08:00
// Struct returns a struct type.
func (p Program) Struct(typs ...Type) Type {
2024-05-23 01:34:48 +08:00
els := make([]*types.Var, len(typs))
for i, t := range typs {
2024-05-26 16:18:24 +08:00
els[i] = types.NewParam(token.NoPos, nil, "_llgo_f"+strconv.Itoa(i), t.raw.Type)
}
2024-05-26 16:18:24 +08:00
return p.rawType(types.NewStruct(els, nil))
}
2024-06-02 21:54:51 +08:00
// Defer returns runtime.Defer type.
func (p Program) Defer() Type {
if p.deferTy == nil {
p.deferTy = p.rtType("Defer")
}
return p.deferTy
}
// DeferPtr returns *runtime.Defer type.
2024-06-02 14:29:35 +08:00
func (p Program) DeferPtr() Type {
if p.deferPtr == nil {
p.deferPtr = p.Pointer(p.Defer())
}
return p.deferPtr
}
2024-06-02 21:54:51 +08:00
// AbiTypePtr returns *abi.Type type.
func (p Program) AbiTypePtr() Type {
2024-06-02 14:29:35 +08:00
if p.abiTyPtr == nil {
p.abiTyPtr = p.rawType(types.NewPointer(p.rtNamed("Type")))
}
2024-06-02 14:29:35 +08:00
return p.abiTyPtr
}
2024-06-02 21:54:51 +08:00
// AbiTypePtrPtr returns **abi.Type type.
func (p Program) AbiTypePtrPtr() Type {
2024-06-02 14:29:35 +08:00
if p.abiTyPPtr == nil {
p.abiTyPPtr = p.Pointer(p.AbiTypePtr())
2024-05-22 13:47:21 +08:00
}
2024-06-02 14:29:35 +08:00
return p.abiTyPPtr
2024-04-18 01:18:41 +08:00
}
2024-04-20 23:57:55 +08:00
// Void returns void type.
2024-04-19 00:05:57 +08:00
func (p Program) Void() Type {
if p.voidTy == nil {
2024-05-05 12:11:51 +08:00
p.voidTy = &aType{p.tyVoid(), rawType{types.Typ[types.Invalid]}, vkInvalid}
2024-04-19 00:05:57 +08:00
}
return p.voidTy
}
// VoidPtr returns *void type.
2024-05-03 23:10:02 +08:00
func (p Program) VoidPtr() Type {
if p.voidPtr == nil {
2024-05-05 12:11:51 +08:00
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
2024-05-03 23:10:02 +08:00
}
return p.voidPtr
}
// VoidPtrPtr returns **void type.
2024-05-27 09:46:07 +08:00
func (p Program) VoidPtrPtr() Type {
if p.voidPPtr == nil {
p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer]))
}
return p.voidPPtr
}
2024-04-20 23:57:55 +08:00
// Bool returns bool type.
2024-04-18 15:03:10 +08:00
func (p Program) Bool() Type {
if p.boolTy == nil {
2024-05-05 12:11:51 +08:00
p.boolTy = p.rawType(types.Typ[types.Bool])
2024-04-18 15:03:10 +08:00
}
return p.boolTy
}
// CStr returns *int8 type.
2024-04-30 08:23:55 +08:00
func (p Program) CStr() Type {
if p.cstrTy == nil { // *int8
2024-05-05 12:11:51 +08:00
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
}
return p.cstrTy
}
// String returns string type.
func (p Program) String() Type {
if p.stringTy == nil {
2024-05-05 12:11:51 +08:00
p.stringTy = p.rawType(types.Typ[types.String])
}
return p.stringTy
}
2024-06-02 15:24:42 +08:00
// Any returns the any (empty interface) type.
2024-04-27 13:57:21 +08:00
func (p Program) Any() Type {
if p.anyTy == nil {
2024-05-05 12:11:51 +08:00
p.anyTy = p.rawType(tyAny)
2024-04-27 13:57:21 +08:00
}
return p.anyTy
}
2024-06-03 01:32:25 +08:00
/*
2024-06-02 15:24:42 +08:00
// Eface returns the empty interface type.
// It is equivalent to Any.
func (p Program) Eface() Type {
return p.Any()
}
*/
2024-06-02 15:24:42 +08:00
2024-06-02 14:29:35 +08:00
// CIntPtr returns *c.Int type.
func (p Program) CIntPtr() Type {
if p.cintPtr == nil {
p.cintPtr = p.Pointer(p.CInt())
}
return p.cintPtr
}
// CInt returns c.Int type.
2024-05-15 08:44:00 +08:00
func (p Program) CInt() Type {
if p.cintTy == nil { // C.int
p.cintTy = p.rawType(types.Typ[types.Int32]) // TODO(xsw): support 64-bit
}
return p.cintTy
}
2024-04-20 23:57:55 +08:00
// Int returns int type.
2024-04-18 15:03:10 +08:00
func (p Program) Int() Type {
if p.intTy == nil {
2024-05-05 12:11:51 +08:00
p.intTy = p.rawType(types.Typ[types.Int])
2024-04-18 15:03:10 +08:00
}
return p.intTy
}
// Uint returns uint type.
func (p Program) Uint() Type {
if p.uintTy == nil {
p.uintTy = p.rawType(types.Typ[types.Uint])
}
return p.uintTy
}
2024-04-28 07:08:01 +08:00
// Uintptr returns uintptr type.
func (p Program) Uintptr() Type {
if p.uintptrTy == nil {
2024-05-05 12:11:51 +08:00
p.uintptrTy = p.rawType(types.Typ[types.Uintptr])
2024-04-28 07:08:01 +08:00
}
return p.uintptrTy
}
2024-04-20 23:57:55 +08:00
// Float64 returns float64 type.
2024-04-18 15:03:10 +08:00
func (p Program) Float64() Type {
if p.f64Ty == nil {
2024-05-05 12:11:51 +08:00
p.f64Ty = p.rawType(types.Typ[types.Float64])
2024-04-18 15:03:10 +08:00
}
return p.f64Ty
2024-04-15 04:00:38 +08:00
}
// Float32 returns float32 type.
func (p Program) Float32() Type {
if p.f32Ty == nil {
p.f32Ty = p.rawType(types.Typ[types.Float32])
}
return p.f32Ty
}
// Complex128 returns complex128 type.
func (p Program) Complex128() Type {
if p.c128Ty == nil {
p.c128Ty = p.rawType(types.Typ[types.Complex128])
}
return p.c128Ty
}
// Complex64 returns complex64 type.
func (p Program) Complex64() Type {
if p.c64Ty == nil {
p.c64Ty = p.rawType(types.Typ[types.Complex64])
}
return p.c64Ty
}
// Byte returns byte type.
func (p Program) Byte() Type {
if p.byteTy == nil {
p.byteTy = p.rawType(types.Typ[types.Byte])
}
return p.byteTy
}
// Int32 returns int32 type.
func (p Program) Int32() Type {
if p.i32Ty == nil {
p.i32Ty = p.rawType(types.Typ[types.Int32])
}
return p.i32Ty
}
// Uint32 returns uint32 type.
func (p Program) Uint32() Type {
if p.u32Ty == nil {
p.u32Ty = p.rawType(types.Typ[types.Uint32])
}
return p.u32Ty
}
// Int64 returns int64 type.
func (p Program) Int64() Type {
if p.i64Ty == nil {
p.i64Ty = p.rawType(types.Typ[types.Int64])
}
return p.i64Ty
}
// Uint64 returns uint64 type.
func (p Program) Uint64() Type {
if p.u64Ty == nil {
p.u64Ty = p.rawType(types.Typ[types.Uint64])
}
return p.u64Ty
}
2024-04-19 00:05:57 +08:00
// -----------------------------------------------------------------------------
2024-04-15 04:00:38 +08:00
// A Package is a single analyzed Go package containing Members for
// all package-level functions, variables, constants and types it
// declares. These may be accessed directly via Members, or via the
// type-specific accessor methods Func, Type, Var and Const.
//
// Members also contains entries for "init" (the synthetic package
// initializer) and "init#%d", the nth declared init function,
// and unspecified other things too.
2024-04-18 01:23:01 +08:00
type aPackage struct {
2024-05-31 07:35:22 +08:00
mod llvm.Module
abi abi.Builder
2024-06-02 21:54:51 +08:00
Prog Program
2024-05-31 07:35:22 +08:00
2024-09-22 08:46:37 +08:00
di diBuilder
cu CompilationUnit
2024-09-19 10:29:11 +08:00
glbDbgVars map[Expr]bool
2024-09-22 08:46:37 +08:00
vars map[string]Global
fns map[string]Function
stubs map[string]Function
pyobjs map[string]PyObjRef
pymods map[string]Global
strs map[string]llvm.Value
goStrs map[string]llvm.Value
2024-10-10 16:07:52 +08:00
chkabi map[types.Type]bool
2024-09-22 08:46:37 +08:00
afterb unsafe.Pointer
patch func(types.Type) types.Type
fnlink func(string) string
2024-05-31 07:35:22 +08:00
iRoutine int
2024-04-15 04:00:38 +08:00
}
2024-04-18 01:23:01 +08:00
type Package = *aPackage
2024-04-18 01:18:41 +08:00
2024-04-27 17:39:25 +08:00
func (p Package) rtFunc(fnName string) Expr {
fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
2024-04-27 17:39:25 +08:00
name := FullName(fn.Pkg(), fnName)
2024-05-05 12:11:51 +08:00
sig := fn.Type().(*types.Signature)
return p.NewFunc(name, sig, InGo).Expr
}
func (p Package) cFunc(fullName string, sig *types.Signature) Expr {
return p.NewFunc(fullName, sig, InC).Expr
}
2024-06-15 10:41:28 +08:00
const (
closureCtx = "__llgo_ctx"
closureStub = "__llgo_stub."
)
2024-07-29 13:53:56 +08:00
func (p Package) closureStub(b Builder, t types.Type, v Expr) Expr {
2024-05-05 18:48:09 +08:00
name := v.impl.Name()
prog := b.Prog
nilVal := prog.Nil(prog.VoidPtr()).impl
2024-05-05 18:48:09 +08:00
if fn, ok := p.stubs[name]; ok {
v = fn.Expr
} else {
sig := v.raw.Type.(*types.Signature)
n := sig.Params().Len()
2024-05-05 19:44:16 +08:00
nret := sig.Results().Len()
2024-06-15 10:41:28 +08:00
ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer])
2024-05-05 18:48:09 +08:00
sig = FuncAddCtx(ctx, sig)
2024-06-15 10:41:28 +08:00
fn := p.NewFunc(closureStub+name, sig, InC)
2024-05-06 00:17:39 +08:00
fn.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
2024-05-05 18:48:09 +08:00
args := make([]Expr, n)
for i := 0; i < n; i++ {
args[i] = fn.Param(i + 1)
}
b := fn.MakeBody(1)
2024-05-05 19:44:16 +08:00
call := b.Call(v, args...)
2024-05-06 16:40:52 +08:00
call.impl.SetTailCall(true)
2024-05-05 19:44:16 +08:00
switch nret {
case 0:
b.impl.CreateRetVoid()
default: // TODO(xsw): support multiple return values
b.impl.CreateRet(call.impl)
}
2024-05-05 18:48:09 +08:00
p.stubs[name] = fn
v = fn.Expr
}
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
}
2024-04-21 15:12:57 +08:00
// -----------------------------------------------------------------------------
2024-05-25 01:11:35 +08:00
// Path returns the package path.
func (p Package) Path() string {
return p.abi.Pkg
}
2024-04-20 23:57:55 +08:00
// String returns a string representation of the package.
2024-04-18 15:03:10 +08:00
func (p Package) String() string {
2024-04-16 00:43:29 +08:00
return p.mod.String()
}
2024-06-30 11:53:12 +08:00
// SetPatch sets a patch function.
func (p Package) SetPatch(fn func(types.Type) types.Type) {
p.patch = fn
}
// SetResolveLinkname sets a function to resolve linkname.
func (p Package) SetResolveLinkname(fn func(string) string) {
p.fnlink = fn
}
2024-06-02 21:54:51 +08:00
// -----------------------------------------------------------------------------
func (p Package) afterBuilder() Builder {
if p.afterb == nil {
2024-06-04 20:02:45 +08:00
fn := p.NewFunc(p.Path()+".init$after", NoArgsNoRet, InC)
2024-06-02 21:54:51 +08:00
fnb := fn.MakeBody(1)
p.afterb = unsafe.Pointer(fnb)
}
return Builder(p.afterb)
}
// AfterInit is called after the package is initialized (init all packages that depends on).
func (p Package) AfterInit(b Builder, ret BasicBlock) {
p.keyInit(deferKey)
2024-06-02 21:54:51 +08:00
doAfterb := p.afterb != nil
2024-05-24 03:22:10 +08:00
doPyLoadModSyms := p.pyHasModSyms()
2024-06-02 21:54:51 +08:00
if doAfterb || doPyLoadModSyms {
2024-05-24 09:20:58 +08:00
b.SetBlockEx(ret, afterInit, false)
2024-06-02 21:54:51 +08:00
if doAfterb {
afterb := Builder(p.afterb)
afterb.Return()
b.Call(afterb.Func.Expr)
2024-05-24 03:22:10 +08:00
}
if doPyLoadModSyms {
p.pyLoadModSyms(b)
2024-05-24 02:09:57 +08:00
}
}
}
func (p Package) InitDebugSymbols(name, pkgPath string, positioner Positioner) {
p.di = newDIBuilder(p.Prog, p, positioner)
2024-09-13 17:15:36 +08:00
p.cu = p.di.createCompileUnit(name, pkgPath)
}
2024-06-02 21:54:51 +08:00
// -----------------------------------------------------------------------------
2024-04-16 00:43:29 +08:00
/*
2024-04-15 17:12:30 +08:00
type CodeGenFileType = llvm.CodeGenFileType
const (
AssemblyFile = llvm.AssemblyFile
ObjectFile = llvm.ObjectFile
)
func (p *Package) CodeGen(ft CodeGenFileType) (ret []byte, err error) {
buf, err := p.prog.targetMachine().EmitToMemoryBuffer(p.mod, ft)
if err != nil {
return
}
ret = buf.Bytes()
buf.Dispose()
return
}
func (p *Package) Bitcode() []byte {
2024-04-15 04:00:38 +08:00
buf := llvm.WriteBitcodeToMemoryBuffer(p.mod)
2024-04-15 05:48:48 +08:00
ret := buf.Bytes()
buf.Dispose()
return ret
}
func (p *Package) WriteTo(w io.Writer) (int64, error) {
2024-04-15 17:12:30 +08:00
n, err := w.Write(p.Bitcode())
2024-04-15 04:00:38 +08:00
return int64(n), err
}
func (p *Package) WriteFile(file string) (err error) {
f, err := os.Create(file)
if err != nil {
return
}
defer f.Close()
return llvm.WriteBitcodeToFile(p.mod, f)
}
2024-04-16 00:43:29 +08:00
*/
2024-04-19 00:05:57 +08:00
// -----------------------------------------------------------------------------