build: fix unsafe.Sizeof for llgo:type C

This commit is contained in:
visualfc
2024-07-16 13:55:48 +08:00
parent 21a2f71ad9
commit 830c40440f
11 changed files with 283 additions and 168 deletions

View File

@@ -263,31 +263,25 @@ _llgo_0:
store i64 23, ptr %4, align 4 store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4 store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4 store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8 %7 = getelementptr inbounds i64, ptr %1, i64 0
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0 call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort3a$1")
store ptr @"__llgo_stub.main.sort3a$1", ptr %8, align 8 %8 = load [5 x i64], ptr %1, align 4
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1 br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0 _llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ] %9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%14 = add i64 %13, 1 %10 = add i64 %9, 1
%15 = icmp slt i64 %14, 5 %11 = icmp slt i64 %10, 5
br i1 %15, label %_llgo_2, label %_llgo_3 br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1 _llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0 %12 = icmp slt i64 %10, 0
%17 = icmp sge i64 %14, 5 %13 = icmp sge i64 %10, 5
%18 = or i1 %17, %16 %14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18) call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%19 = getelementptr inbounds i64, ptr %1, i64 %14 %15 = getelementptr inbounds i64, ptr %1, i64 %10
%20 = load i64, ptr %19, align 4 %16 = load i64, ptr %15, align 4
%21 = call i32 (ptr, ...) @printf(ptr @9, i64 %20) %17 = call i32 (ptr, ...) @printf(ptr @9, i64 %16)
br label %_llgo_1 br label %_llgo_1
_llgo_3: ; preds = %_llgo_1 _llgo_3: ; preds = %_llgo_1
@@ -318,30 +312,24 @@ _llgo_0:
store i64 2, ptr %5, align 4 store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4 store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0 %7 = getelementptr inbounds i64, ptr %1, i64 0
%8 = alloca { ptr, ptr }, align 8 call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort3b$1")
%9 = getelementptr inbounds { ptr, ptr }, ptr %8, i32 0, i32 0 %8 = load [5 x i64], ptr %1, align 4
store ptr @"__llgo_stub.main.sort3b$1", ptr %9, align 8
%10 = getelementptr inbounds { ptr, ptr }, ptr %8, i32 0, i32 1
store ptr null, ptr %10, align 8
%11 = load { ptr, ptr }, ptr %8, align 8
call void @qsort(ptr %7, i64 5, i64 8, { ptr, ptr } %11)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1 br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0 _llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ] %9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%14 = add i64 %13, 1 %10 = add i64 %9, 1
%15 = icmp slt i64 %14, 5 %11 = icmp slt i64 %10, 5
br i1 %15, label %_llgo_2, label %_llgo_3 br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1 _llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0 %12 = icmp slt i64 %10, 0
%17 = icmp sge i64 %14, 5 %13 = icmp sge i64 %10, 5
%18 = or i1 %17, %16 %14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18) call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%19 = getelementptr inbounds i64, ptr %1, i64 %14 %15 = getelementptr inbounds i64, ptr %1, i64 %10
%20 = load i64, ptr %19, align 4 %16 = load i64, ptr %15, align 4
%21 = call i32 (ptr, ...) @printf(ptr @11, i64 %20) %17 = call i32 (ptr, ...) @printf(ptr @11, i64 %16)
br label %_llgo_1 br label %_llgo_1
_llgo_3: ; preds = %_llgo_1 _llgo_3: ; preds = %_llgo_1
@@ -371,31 +359,25 @@ _llgo_0:
store i64 23, ptr %4, align 4 store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4 store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4 store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8 %7 = getelementptr inbounds i64, ptr %1, i64 0
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0 call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort4a$1")
store ptr @"__llgo_stub.main.sort4a$1", ptr %8, align 8 %8 = load [5 x i64], ptr %1, align 4
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1 br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0 _llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ] %9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%14 = add i64 %13, 1 %10 = add i64 %9, 1
%15 = icmp slt i64 %14, 5 %11 = icmp slt i64 %10, 5
br i1 %15, label %_llgo_2, label %_llgo_3 br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1 _llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0 %12 = icmp slt i64 %10, 0
%17 = icmp sge i64 %14, 5 %13 = icmp sge i64 %10, 5
%18 = or i1 %17, %16 %14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18) call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%19 = getelementptr inbounds i64, ptr %1, i64 %14 %15 = getelementptr inbounds i64, ptr %1, i64 %10
%20 = load i64, ptr %19, align 4 %16 = load i64, ptr %15, align 4
%21 = call i32 (ptr, ...) @printf(ptr @13, i64 %20) %17 = call i32 (ptr, ...) @printf(ptr @13, i64 %16)
br label %_llgo_1 br label %_llgo_1
_llgo_3: ; preds = %_llgo_1 _llgo_3: ; preds = %_llgo_1
@@ -473,31 +455,25 @@ _llgo_0:
store i64 23, ptr %4, align 4 store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4 store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4 store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8 %7 = getelementptr inbounds i64, ptr %1, i64 0
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0 call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort5a$1")
store ptr @"__llgo_stub.main.sort5a$1", ptr %8, align 8 %8 = load [5 x i64], ptr %1, align 4
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1 br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0 _llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ] %9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%14 = add i64 %13, 1 %10 = add i64 %9, 1
%15 = icmp slt i64 %14, 5 %11 = icmp slt i64 %10, 5
br i1 %15, label %_llgo_2, label %_llgo_3 br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1 _llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0 %12 = icmp slt i64 %10, 0
%17 = icmp sge i64 %14, 5 %13 = icmp sge i64 %10, 5
%18 = or i1 %17, %16 %14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18) call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%19 = getelementptr inbounds i64, ptr %1, i64 %14 %15 = getelementptr inbounds i64, ptr %1, i64 %10
%20 = load i64, ptr %19, align 4 %16 = load i64, ptr %15, align 4
%21 = call i32 (ptr, ...) @printf(ptr @17, i64 %20) %17 = call i32 (ptr, ...) @printf(ptr @17, i64 %16)
br label %_llgo_1 br label %_llgo_1
_llgo_3: ; preds = %_llgo_1 _llgo_3: ; preds = %_llgo_1
@@ -570,27 +546,3 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare void @qsort(ptr, i64, i64, ptr) declare void @qsort(ptr, i64, i64, ptr)
declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1)
define linkonce i32 @"__llgo_stub.main.sort3a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort3a$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort3b$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort3b$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort4a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort4a$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort5a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort5a$1"(ptr %1, ptr %2)
ret i32 %3
}

30
cl/_testrt/unsafe/in.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"unsafe"
)
//llgo:type C
type T func()
type M struct {
v int
fn T
}
type N struct {
v int
fn func()
}
func main() {
if unsafe.Sizeof(*(*T)(nil)) != unsafe.Sizeof(0) {
panic("error")
}
if unsafe.Sizeof(*(*M)(nil)) != unsafe.Sizeof([2]int{}) {
panic("error")
}
if unsafe.Sizeof(*(*N)(nil)) != unsafe.Sizeof([3]int{}) {
panic("error")
}
}

123
cl/_testrt/unsafe/out.ll Normal file
View File

@@ -0,0 +1,123 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
@"main.init$guard" = global i1 false, align 1
@__llgo_argc = global i32 0, align 4
@__llgo_argv = global ptr null, align 8
@0 = private unnamed_addr constant [5 x i8] c"error", align 1
@_llgo_string = linkonce global ptr null, align 8
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i32 @main(i32 %0, ptr %1) {
_llgo_0:
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
br i1 false, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0
store ptr @0, ptr %3, align 8
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
store i64 5, ptr %4, align 4
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
%6 = load ptr, ptr @_llgo_string, align 8
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %5, ptr %7, align 8
%8 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 0
store ptr %6, ptr %9, align 8
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 1
store ptr %7, ptr %10, align 8
%11 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, align 8
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %11)
unreachable
_llgo_2: ; preds = %_llgo_0
br i1 false, label %_llgo_3, label %_llgo_4
_llgo_3: ; preds = %_llgo_2
%12 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 0
store ptr @0, ptr %13, align 8
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 1
store i64 5, ptr %14, align 4
%15 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8
%16 = load ptr, ptr @_llgo_string, align 8
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %15, ptr %17, align 8
%18 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %18, i32 0, i32 0
store ptr %16, ptr %19, align 8
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %18, i32 0, i32 1
store ptr %17, ptr %20, align 8
%21 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %18, align 8
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %21)
unreachable
_llgo_4: ; preds = %_llgo_2
br i1 false, label %_llgo_5, label %_llgo_6
_llgo_5: ; preds = %_llgo_4
%22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0
store ptr @0, ptr %23, align 8
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1
store i64 5, ptr %24, align 4
%25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8
%26 = load ptr, ptr @_llgo_string, align 8
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %25, ptr %27, align 8
%28 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
%29 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %28, i32 0, i32 0
store ptr %26, ptr %29, align 8
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %28, i32 0, i32 1
store ptr %27, ptr %30, align 8
%31 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %28, align 8
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %31)
unreachable
_llgo_6: ; preds = %_llgo_4
ret i32 0
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null
br i1 %1, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
store ptr %2, ptr @_llgo_string, align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface")

View File

@@ -196,8 +196,6 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) {
p.collectSkipNames(line) p.collectSkipNames(line)
} }
} }
case token.TYPE:
handleTypeDecl(p.prog, p.goTyps, decl)
} }
} }
} }
@@ -568,9 +566,7 @@ func handleTypeDecl(prog llssa.Program, pkg *types.Package, decl *ast.GenDecl) {
if len(decl.Specs) == 1 { if len(decl.Specs) == 1 {
if bg := typeBackground(decl.Doc); bg != "" { if bg := typeBackground(decl.Doc); bg != "" {
inPkgName := decl.Specs[0].(*ast.TypeSpec).Name.Name inPkgName := decl.Specs[0].(*ast.TypeSpec).Name.Name
if obj := pkg.Scope().Lookup(inPkgName); obj != nil { prog.SetTypeBackground(pkg.Path()+"."+inPkgName, toBackground(bg))
prog.Type(obj.Type(), toBackground(bg))
}
} }
} }
} }

View File

@@ -18,6 +18,7 @@ package build
import ( import (
"fmt" "fmt"
"go/ast"
"go/constant" "go/constant"
"go/token" "go/token"
"go/types" "go/types"
@@ -136,6 +137,12 @@ func Do(args []string, conf *Config) {
prog := llssa.NewProgram(nil) prog := llssa.NewProgram(nil)
sizes := prog.TypeSizes sizes := prog.TypeSizes
dedup := packages.NewDeduper() dedup := packages.NewDeduper()
dedup.SetPreload(func(pkg *types.Package, files []*ast.File) {
if canSkipToBuild(pkg.Path()) {
return
}
cl.ParsePkgSyntax(prog, pkg, files)
})
if patterns == nil { if patterns == nil {
patterns = []string{"."} patterns = []string{"."}
@@ -256,7 +263,6 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
case cl.PkgDeclOnly: case cl.PkgDeclOnly:
// skip packages that only contain declarations // skip packages that only contain declarations
// and set no export file // and set no export file
cl.ParsePkgSyntax(ctx.prog, pkg.Types, pkg.Syntax)
pkg.ExportFile = "" pkg.ExportFile = ""
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule: case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
if len(pkg.GoFiles) > 0 { if len(pkg.GoFiles) > 0 {

View File

@@ -17,17 +17,10 @@
package llgen package llgen
import ( import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"os" "os"
"github.com/goplus/gogen/packages"
"github.com/goplus/llgo/cl" "github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/mod" "github.com/goplus/llgo/internal/mod"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa" llssa "github.com/goplus/llgo/ssa"
) )
@@ -45,51 +38,11 @@ func PkgPath(dir string) string {
} }
func Do(pkgPath, inFile, outFile string) { func Do(pkgPath, inFile, outFile string) {
ret := Gen(pkgPath, inFile, nil) ret := genFrom(inFile, pkgPath)
err := os.WriteFile(outFile, []byte(ret), 0644) err := os.WriteFile(outFile, []byte(ret), 0644)
check(err) check(err)
} }
func Gen(pkgPath, inFile string, src any) string {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, inFile, src, parser.ParseComments)
check(err)
files := []*ast.File{f}
name := f.Name.Name
if pkgPath == "" {
pkgPath = name
}
pkg := types.NewPackage(pkgPath, name)
imp := packages.NewImporter(fset)
ssaPkg, _, err := ssautil.BuildPackage(
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
check(err)
if Verbose {
ssaPkg.WriteTo(os.Stderr)
}
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
ret, _ := imp.Import(llssa.PkgRuntime)
return ret
})
prog.SetPython(func() *types.Package {
ret, _ := imp.Import(llssa.PkgPython)
return ret
})
ret, err := cl.NewPackage(prog, ssaPkg, files)
check(err)
if prog.NeedPyInit { // call PyInit if needed
ret.PyInit()
}
return ret.String()
}
func check(err error) { func check(err error) {
if err != nil { if err != nil {
panic(err) panic(err)

View File

@@ -17,6 +17,7 @@
package llgen package llgen
import ( import (
"go/ast"
"go/types" "go/types"
"os" "os"
"os/exec" "os/exec"
@@ -60,12 +61,32 @@ func initRtAndPy(prog llssa.Program, cfg *packages.Config) {
} }
func GenFrom(fileOrPkg string) string { func GenFrom(fileOrPkg string) string {
return genFrom(fileOrPkg, "")
}
func genFrom(fileOrPkg string, pkgPath string) string {
prog := llssa.NewProgram(nil) prog := llssa.NewProgram(nil)
cfg := &packages.Config{ cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps, Mode: loadSyntax | packages.NeedDeps,
} }
initial, err := packages.LoadEx(nil, prog.TypeSizes, cfg, fileOrPkg)
dedup := packages.NewDeduper()
dedup.SetPkgPath(func(path, name string) string {
if path == "command-line-arguments" {
if pkgPath != "" {
path = pkgPath
} else {
path = name
}
}
return path
})
dedup.SetPreload(func(pkg *types.Package, files []*ast.File) {
cl.ParsePkgSyntax(prog, pkg, files)
})
initial, err := packages.LoadEx(dedup, prog.TypeSizes, cfg, fileOrPkg)
check(err) check(err)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) _, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)

View File

@@ -111,6 +111,8 @@ type Cached struct {
type aDeduper struct { type aDeduper struct {
cache sync.Map cache sync.Map
setpath func(path string, name string) string
preload func(pkg *types.Package, syntax []*ast.File)
} }
type Deduper = *aDeduper type Deduper = *aDeduper
@@ -119,6 +121,14 @@ func NewDeduper() Deduper {
return &aDeduper{} return &aDeduper{}
} }
func (p Deduper) SetPreload(fn func(pkg *types.Package, syntax []*ast.File)) {
p.preload = fn
}
func (p Deduper) SetPkgPath(fn func(path, name string) string) {
p.setpath = fn
}
func (p Deduper) Check(pkgPath string) *Cached { func (p Deduper) Check(pkgPath string) *Cached {
if v, ok := p.cache.Load(pkgPath); ok { if v, ok := p.cache.Load(pkgPath); ok {
return v.(*Cached) return v.(*Cached)
@@ -186,6 +196,9 @@ func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) {
}) })
} }
}() }()
if dedup.setpath != nil {
lpkg.PkgPath = dedup.setpath(lpkg.PkgPath, lpkg.Name)
}
} }
// Call NewPackage directly with explicit name. // Call NewPackage directly with explicit name.
@@ -369,6 +382,10 @@ func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) {
panic("unreachable") panic("unreachable")
}) })
if dedup != nil && dedup.preload != nil {
dedup.preload(lpkg.Types, lpkg.Syntax)
}
// type-check // type-check
tc := &types.Config{ tc := &types.Config{
Importer: importer, Importer: importer,

View File

@@ -236,6 +236,10 @@ func (p Program) SetRuntime(runtime any) {
} }
} }
func (p Program) SetTypeBackground(fullName string, bg Background) {
p.gocvt.typbg[fullName] = bg
}
func (p Program) runtime() *types.Package { func (p Program) runtime() *types.Package {
if p.rt == nil { if p.rt == nil {
p.rt = p.rtget() p.rt = p.rtget()

View File

@@ -103,7 +103,7 @@ func (p *goProgram) Offsetsof(fields []*types.Var) (ret []int64) {
ret = p.sizes.Offsetsof(fields) ret = p.sizes.Offsetsof(fields)
for i, f := range fields { for i, f := range fields {
ret[i] += extra ret[i] += extra
extra += extraSize(f.Type(), ptrSize) extra += p.extraSize(f.Type(), ptrSize)
} }
return return
} }
@@ -114,26 +114,34 @@ func (p *goProgram) Offsetsof(fields []*types.Var) (ret []int64) {
func (p *goProgram) Sizeof(T types.Type) int64 { func (p *goProgram) Sizeof(T types.Type) int64 {
prog := Program(p) prog := Program(p)
ptrSize := int64(prog.PointerSize()) ptrSize := int64(prog.PointerSize())
baseSize := prog.sizes.Sizeof(T) + extraSize(T, ptrSize) baseSize := prog.sizes.Sizeof(T) + p.extraSize(T, ptrSize)
if _, ok := T.Underlying().(*types.Struct); ok { switch T.Underlying().(type) {
case *types.Struct, *types.Array:
return align(baseSize, prog.sizes.Alignof(T)) return align(baseSize, prog.sizes.Alignof(T))
} }
return baseSize return baseSize
} }
func extraSize(t types.Type, ptrSize int64) (ret int64) { func (p *goProgram) extraSize(typ types.Type, ptrSize int64) (ret int64) {
switch t := t.Underlying().(type) { retry:
switch t := typ.(type) {
case *types.Named:
if p.gocvt.typbg[t.String()] == InC {
return 0
}
typ = t.Underlying()
goto retry
case *types.Signature: case *types.Signature:
return ptrSize return ptrSize
case *types.Struct: case *types.Struct:
n := t.NumFields() n := t.NumFields()
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
f := t.Field(i) f := t.Field(i)
ret += extraSize(f.Type(), ptrSize) ret += p.extraSize(f.Type(), ptrSize)
} }
return return
case *types.Array: case *types.Array:
return extraSize(t.Elem(), ptrSize) * t.Len() return p.extraSize(t.Elem(), ptrSize) * t.Len()
} }
return 0 return 0
} }

View File

@@ -27,11 +27,13 @@ import (
type goTypes struct { type goTypes struct {
typs map[unsafe.Pointer]unsafe.Pointer typs map[unsafe.Pointer]unsafe.Pointer
typbg map[string]Background
} }
func newGoTypes() goTypes { func newGoTypes() goTypes {
typs := make(map[unsafe.Pointer]unsafe.Pointer) typs := make(map[unsafe.Pointer]unsafe.Pointer)
return goTypes{typs} typbk := make(map[string]Background)
return goTypes{typs, typbk}
} }
type Background int type Background int
@@ -93,6 +95,9 @@ func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) {
case *types.Struct: case *types.Struct:
return p.cvtStruct(t) return p.cvtStruct(t)
case *types.Named: case *types.Named:
if p.typbg[t.String()] == InC {
break
}
return p.cvtNamed(t) return p.cvtNamed(t)
case *types.Signature: case *types.Signature:
return p.cvtClosure(t), true return p.cvtClosure(t), true