compiler: make main function normally to compatible multiple main functions in testing mode
This commit is contained in:
@@ -152,10 +152,6 @@ func TestCompileEx(t *testing.T, src any, fname, expected string, dbg bool) {
|
|||||||
t.Fatal("cl.NewPackage failed:", err)
|
t.Fatal("cl.NewPackage failed:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prog.NeedPyInit { // call PyInit if needed
|
|
||||||
ret.PyInit()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := ret.String(); v != expected && expected != ";" { // expected == ";" means skipping out.ll
|
if v := ret.String(); v != expected && expected != ";" { // expected == ";" means skipping out.ll
|
||||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,10 +127,6 @@ const (
|
|||||||
pkgFNoOldInit = 0x80 // flag if no initFnNameOld
|
pkgFNoOldInit = 0x80 // flag if no initFnNameOld
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) inMain(instr ssa.Instruction) bool {
|
|
||||||
return p.fn.Name() == "main"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
||||||
tn := t.Object().(*types.TypeName)
|
tn := t.Object().(*types.TypeName)
|
||||||
if tn.IsAlias() { // don't need to compile alias type
|
if tn.IsAlias() { // don't need to compile alias type
|
||||||
@@ -186,10 +182,6 @@ func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var {
|
|||||||
return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t)
|
return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
|
||||||
)
|
|
||||||
|
|
||||||
func isCgoExternSymbol(f *ssa.Function) bool {
|
func isCgoExternSymbol(f *ssa.Function) bool {
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
return isCgoCfunc(name) || isCgoCmacro(name)
|
return isCgoCfunc(name) || isCgoCmacro(name)
|
||||||
@@ -247,14 +239,6 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
if name == "main" {
|
|
||||||
argc := types.NewParam(token.NoPos, pkgTypes, "", types.Typ[types.Int32])
|
|
||||||
argv := types.NewParam(token.NoPos, pkgTypes, "", argvTy)
|
|
||||||
params := types.NewTuple(argc, argv)
|
|
||||||
ret := types.NewParam(token.NoPos, pkgTypes, "", p.prog.CInt().RawType())
|
|
||||||
results := types.NewTuple(ret)
|
|
||||||
sig = types.NewSignatureType(nil, nil, nil, params, results, false)
|
|
||||||
}
|
|
||||||
fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, f.Origin() != nil)
|
fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, f.Origin() != nil)
|
||||||
if debugSymbols {
|
if debugSymbols {
|
||||||
fn.Inline(llssa.NoInline)
|
fn.Inline(llssa.NoInline)
|
||||||
@@ -309,9 +293,8 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
|||||||
i := 0
|
i := 0
|
||||||
for {
|
for {
|
||||||
block := f.Blocks[i]
|
block := f.Blocks[i]
|
||||||
doMainInit := (i == 0 && name == "main")
|
|
||||||
doModInit := (i == 1 && isInit)
|
doModInit := (i == 1 && isInit)
|
||||||
p.compileBlock(b, block, off[i], doMainInit, doModInit)
|
p.compileBlock(b, block, off[i], doModInit)
|
||||||
if isCgo {
|
if isCgo {
|
||||||
// just process first block for performance
|
// just process first block for performance
|
||||||
break
|
break
|
||||||
@@ -385,7 +368,7 @@ func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
|
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doModInit bool) llssa.BasicBlock {
|
||||||
var last int
|
var last int
|
||||||
var pyModInit bool
|
var pyModInit bool
|
||||||
var prog = p.prog
|
var prog = p.prog
|
||||||
@@ -408,15 +391,6 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
pkg.AfterInit(b, ret)
|
pkg.AfterInit(b, ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if doMainInit {
|
|
||||||
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
|
||||||
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
|
||||||
argc.InitNil()
|
|
||||||
argv.InitNil()
|
|
||||||
b.Store(argc.Expr, fn.Param(0))
|
|
||||||
b.Store(argv.Expr, fn.Param(1))
|
|
||||||
callRuntimeInit(b, pkg)
|
|
||||||
b.Call(pkg.FuncOf("main.init").Expr)
|
|
||||||
}
|
}
|
||||||
fnName := block.Parent().Name()
|
fnName := block.Parent().Name()
|
||||||
cgoReturned := false
|
cgoReturned := false
|
||||||
@@ -499,11 +473,6 @@ const (
|
|||||||
RuntimeInit = llssa.PkgRuntime + ".init"
|
RuntimeInit = llssa.PkgRuntime + ".init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
|
||||||
fn := pkg.NewFunc(RuntimeInit, llssa.NoArgsNoRet, llssa.InC) // don't need to convert runtime.init
|
|
||||||
b.Call(fn.Expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isAny(t types.Type) bool {
|
func isAny(t types.Type) bool {
|
||||||
if t, ok := t.Underlying().(*types.Interface); ok {
|
if t, ok := t.Underlying().(*types.Interface); ok {
|
||||||
return t.Empty()
|
return t.Empty()
|
||||||
@@ -834,10 +803,6 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
results[i] = p.compileValue(b, r)
|
results[i] = p.compileValue(b, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.inMain(instr) {
|
|
||||||
results = make([]llssa.Expr, 1)
|
|
||||||
results[0] = p.prog.IntVal(0, p.prog.CInt())
|
|
||||||
}
|
|
||||||
b.Return(results...)
|
b.Return(results...)
|
||||||
case *ssa.If:
|
case *ssa.If:
|
||||||
fn := p.fn
|
fn := p.fn
|
||||||
|
|||||||
@@ -426,6 +426,11 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
main, err := genMainModuleFile(llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
args = append(args, main)
|
||||||
|
|
||||||
var aPkg *aPackage
|
var aPkg *aPackage
|
||||||
for _, v := range pkgs {
|
for _, v := range pkgs {
|
||||||
@@ -435,19 +440,9 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dirty := false
|
args = append(args, linkArgs...)
|
||||||
if needRuntime {
|
|
||||||
args = append(args, linkArgs...)
|
|
||||||
} else {
|
|
||||||
dirty = true
|
|
||||||
fn := aPkg.LPkg.FuncOf(cl.RuntimeInit)
|
|
||||||
fn.MakeBody(1).Return()
|
|
||||||
}
|
|
||||||
if needPyInit {
|
|
||||||
dirty = aPkg.LPkg.PyInit()
|
|
||||||
}
|
|
||||||
|
|
||||||
if dirty && needLLFile(mode) {
|
if needLLFile(mode) {
|
||||||
lpkg := aPkg.LPkg
|
lpkg := aPkg.LPkg
|
||||||
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
||||||
}
|
}
|
||||||
@@ -475,7 +470,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
if verbose {
|
if verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
err := ctx.env.Clang().Exec(args...)
|
err = ctx.env.Clang().Exec(args...)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
@@ -505,6 +500,60 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func genMainModuleFile(rtPkgPath, mainPkgPath string, needRuntime, needPyInit bool) (path string, err error) {
|
||||||
|
var (
|
||||||
|
pyInitDecl string
|
||||||
|
pyInit string
|
||||||
|
rtInitDecl string
|
||||||
|
rtInit string
|
||||||
|
)
|
||||||
|
if needRuntime {
|
||||||
|
rtInit = "call void @\"" + rtPkgPath + ".init\"()"
|
||||||
|
rtInitDecl = "declare void @\"" + rtPkgPath + ".init\"()"
|
||||||
|
}
|
||||||
|
if needPyInit {
|
||||||
|
pyInit = "call void @Py_Initialize()"
|
||||||
|
pyInitDecl = "declare void @Py_Initialize()"
|
||||||
|
}
|
||||||
|
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@__llgo_argc = global i32 0, align 4
|
||||||
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
|
||||||
|
%s
|
||||||
|
%s
|
||||||
|
declare void @"%s.init"()
|
||||||
|
declare void @"%s.main"()
|
||||||
|
|
||||||
|
define i32 @main(i32 %%0, ptr %%1) {
|
||||||
|
_llgo_0:
|
||||||
|
%s
|
||||||
|
store i32 %%0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %%1, ptr @__llgo_argv, align 8
|
||||||
|
%s
|
||||||
|
call void @"%s.init"()
|
||||||
|
call void @"%s.main"()
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
`, pyInitDecl, rtInitDecl, mainPkgPath, mainPkgPath,
|
||||||
|
pyInit, rtInit, mainPkgPath, mainPkgPath)
|
||||||
|
|
||||||
|
f, err := os.CreateTemp("", "main*.ll")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_, err = f.Write([]byte(mainCode))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string, err error) {
|
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string, err error) {
|
||||||
pkg := aPkg.Package
|
pkg := aPkg.Package
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
|
|||||||
@@ -226,9 +226,6 @@ func PathOf(pkg *types.Package) string {
|
|||||||
if pkg == nil {
|
if pkg == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if pkg.Name() == "main" {
|
|
||||||
return "main"
|
|
||||||
}
|
|
||||||
return strings.TrimPrefix(pkg.Path(), PatchPathPrefix)
|
return strings.TrimPrefix(pkg.Path(), PatchPathPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -231,18 +231,6 @@ func (p Program) tyGetAttrString() *types.Signature {
|
|||||||
return p.getAttrStr
|
return p.getAttrStr
|
||||||
}
|
}
|
||||||
|
|
||||||
// PyInit initializes Python for a main package.
|
|
||||||
func (p Package) PyInit() bool {
|
|
||||||
if fn := p.FuncOf("main"); fn != nil {
|
|
||||||
b := fn.NewBuilder()
|
|
||||||
b.SetBlockEx(fn.Block(0), AtStart, false)
|
|
||||||
b.callPyInit()
|
|
||||||
b.Dispose()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// PyNewModVar creates a new global variable for a Python module.
|
// PyNewModVar creates a new global variable for a Python module.
|
||||||
func (p Package) PyNewModVar(name string, doInit bool) Global {
|
func (p Package) PyNewModVar(name string, doInit bool) Global {
|
||||||
if v, ok := p.pymods[name]; ok {
|
if v, ok := p.pymods[name]; ok {
|
||||||
|
|||||||
@@ -554,9 +554,6 @@ func FuncName(pkg *types.Package, name string, recv *types.Var, org bool) string
|
|||||||
return PathOf(pkg) + "." + tName + "." + name
|
return PathOf(pkg) + "." + tName + "." + name
|
||||||
}
|
}
|
||||||
ret := FullName(pkg, name)
|
ret := FullName(pkg, name)
|
||||||
if ret == "main.main" {
|
|
||||||
ret = "main"
|
|
||||||
}
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user