Skip to content

Commit

Permalink
cl: context
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Jul 14, 2024
1 parent 9156466 commit da8aab0
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 25 deletions.
1 change: 1 addition & 0 deletions cl/builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ func TestIgnoreName(t *testing.T) {

func TestErrImport(t *testing.T) {
var ctx context
ctx.Context = NewContext(nil, nil, nil)
pkg := types.NewPackage("foo", "foo")
ctx.importPkg(pkg, nil)

Expand Down
44 changes: 32 additions & 12 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,42 @@ type pkgInfo struct {
kind int
}

type Context struct {
prog llssa.Program
patches Patches
syntax map[*types.Package]none // syntax map
kinds map[*types.Package]int // kind map
link map[string]string // link map
check func(pkgPath string) ([]*ast.File, bool)
}

func NewContext(prog llssa.Program, patches Patches, fn func(pkgPath string) ([]*ast.File, bool)) *Context {
return &Context{
prog: prog,
patches: patches,
syntax: make(map[*types.Package]none),
kinds: make(map[*types.Package]int),
link: make(map[string]string),
check: fn,
}
}

type none = struct{}

type context struct {
prog llssa.Program
*Context
pkg llssa.Package
fn llssa.Function
fset *token.FileSet
goProg *ssa.Program
goTyps *types.Package
goPkg *ssa.Package
pyMod string
link map[string]string // pkgPath.nameInPkg => linkname
skips map[string]none
loaded map[*types.Package]*pkgInfo // loaded packages
bvals map[ssa.Value]llssa.Expr // block values
vargs map[*ssa.Alloc][]llssa.Expr // varargs

patches Patches
blkInfos []blocks.Info

inits []func()
Expand Down Expand Up @@ -771,43 +789,44 @@ type Patches = map[string]Patch

// NewPackage compiles a Go package to LLVM IR package.
func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
return NewPackageEx(prog, nil, pkg, files)
return NewPackageEx(NewContext(prog, nil, nil), pkg, files, nil)
}

// NewPackageEx compiles a Go package to LLVM IR package.
func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
func NewPackageEx(c *Context, pkg *ssa.Package, files []*ast.File, altFiles []*ast.File) (ret llssa.Package, err error) {
pkgProg := pkg.Prog
pkgTypes := pkg.Pkg
oldTypes := pkgTypes
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
patch, hasPatch := patches[pkgPath]
patch, hasPatch := c.patches[pkgPath]
if hasPatch {
pkgTypes = patch.Types
pkg.Pkg = pkgTypes
patch.Alt.Pkg = pkgTypes
}
if pkgPath == llssa.PkgRuntime {
prog.SetRuntime(pkgTypes)
c.prog.SetRuntime(pkgTypes)
}
ret = prog.NewPackage(pkgName, pkgPath)
ret = c.prog.NewPackage(pkgName, pkgPath)

ctx := &context{
prog: prog,
Context: c,
pkg: ret,
fset: pkgProg.Fset,
goProg: pkgProg,
goTyps: pkgTypes,
goPkg: pkg,
patches: patches,
link: make(map[string]string),
skips: make(map[string]none),
vargs: make(map[*ssa.Alloc][]llssa.Expr),
loaded: map[*types.Package]*pkgInfo{
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
},
}

if len(altFiles) > 0 {
ctx.parsePatchSyntax(pkgPath, altFiles)
}
ctx.initPyModule()
ctx.initFiles(pkgPath, files)
ret.SetPatch(ctx.patchType)

if hasPatch {
Expand All @@ -823,6 +842,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
ctx.skips = skips
}
if !ctx.skipall {
c.ParsePkgSyntax(pkgTypes, files)
processPkg(ctx, ret, pkg)
}
for len(ctx.inits) > 0 {
Expand Down
39 changes: 33 additions & 6 deletions cl/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ func pkgKindByScope(scope *types.Scope) (int, string) {
}

func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
if kind, ok := p.kinds[pkg]; ok {
i.kind = kind
return
}
pkgPath := llssa.PathOf(pkg)
scope := pkg.Scope()
kind, _ := pkgKindByScope(scope)
Expand All @@ -143,6 +147,14 @@ func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
}
start:
i.kind = kind
p.kinds[pkg] = kind

if p.check != nil {
if files, ok := p.check(pkg.Path()); ok {
p.ParsePkgSyntax(pkg, files)
return
}
}
fset := p.fset
names := scope.Names()
syms := newPkgSymInfo()
Expand Down Expand Up @@ -173,7 +185,7 @@ start:
syms.initLinknames(p)
}

func (p *context) initFiles(pkgPath string, files []*ast.File) {
func (p *context) parsePatchSyntax(pkgPath string, files []*ast.File) {
for _, file := range files {
for _, decl := range file.Decls {
switch decl := decl.(type) {
Expand Down Expand Up @@ -235,7 +247,7 @@ func (p *context) collectSkip(line string, prefix int) {
}
}

func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar bool) {
func (p *Context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar bool) {
if doc != nil {
if n := len(doc.List); n > 0 {
line := doc.List[n-1].Text
Expand All @@ -246,7 +258,7 @@ func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName s
}
}

func (p *context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok bool)) {
func (p *Context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok bool)) {
const (
linkname = "//go:linkname "
llgolink = "//llgo:link "
Expand All @@ -261,7 +273,7 @@ func (p *context) initLinkname(line string, f func(inPkgName string) (fullName s
}
}

func (p *context) initLink(line string, prefix int, f func(inPkgName string) (fullName string, isVar, ok bool)) {
func (p *Context) initLink(line string, prefix int, f func(inPkgName string) (fullName string, isVar, ok bool)) {
text := strings.TrimSpace(line[prefix:])
if idx := strings.IndexByte(text, ' '); idx > 0 {
inPkgName := text[:idx]
Expand Down Expand Up @@ -550,14 +562,29 @@ func (p *context) initPyModule() {
}

// ParsePkgSyntax parses AST of a package to check llgo:type in type declaration.
func ParsePkgSyntax(prog llssa.Program, pkg *types.Package, files []*ast.File) {
func (ctx *Context) ParsePkgSyntax(pkg *types.Package, files []*ast.File) {
if _, ok := ctx.syntax[pkg]; ok {
return
}
ctx.syntax[pkg] = none{}
pkgPath := llssa.PathOf(pkg)
for _, file := range files {
for _, decl := range file.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
fullName, inPkgName := astFuncName(pkgPath, decl)
ctx.initLinknameByDoc(decl.Doc, fullName, inPkgName, false)
case *ast.GenDecl:
switch decl.Tok {
case token.VAR:
if len(decl.Specs) == 1 {
if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 {
inPkgName := names[0].Name
ctx.initLinknameByDoc(decl.Doc, pkgPath+"."+inPkgName, inPkgName, true)
}
}
case token.TYPE:
handleTypeDecl(prog, pkg, decl)
handleTypeDecl(ctx.prog, pkg, decl)
}
}
}
Expand Down
24 changes: 17 additions & 7 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package build

import (
"fmt"
"go/ast"
"go/constant"
"go/token"
"go/types"
Expand Down Expand Up @@ -169,12 +170,16 @@ func Do(args []string, conf *Config) {
prog.SetPython(func() *types.Package {
return dedup.Check(llssa.PkgPython).Types
})

progSSA := ssa.NewProgram(initial[0].Fset, ssaBuildMode)
patches := make(cl.Patches, len(altPkgPaths))
altSSAPkgs(progSSA, patches, altPkgs[1:], verbose)

ctx := &context{llvm.New(""), progSSA, prog, dedup, patches, make(map[string]none), initial, mode}
c := cl.NewContext(prog, patches, func(pkgPath string) ([]*ast.File, bool) {
if c := dedup.Check(pkgPath); c != nil {
return c.Syntax, true
}
return nil, false
})
ctx := &context{c, llvm.New(""), progSSA, prog, dedup, patches, make(map[string]none), initial, mode}
pkgs := buildAllPkgs(ctx, initial, verbose)

var llFiles []string
Expand Down Expand Up @@ -221,6 +226,7 @@ const (
)

type context struct {
ctx *cl.Context
env *llvm.Env
progSSA *ssa.Program
prog llssa.Program
Expand Down Expand Up @@ -252,7 +258,9 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
case cl.PkgDeclOnly:
// skip packages that only contain declarations
// and set no export file
cl.ParsePkgSyntax(ctx.prog, pkg.Types, pkg.Syntax)
if !canSkipToBuild(pkg.PkgPath) {
ctx.ctx.ParsePkgSyntax(pkg.Types, pkg.Syntax)
}
pkg.ExportFile = ""
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
if len(pkg.GoFiles) > 0 {
Expand Down Expand Up @@ -421,17 +429,17 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) {
pkg.ExportFile = ""
return
}
var syntax = pkg.Syntax
var syntax []*ast.File
if altPkg := aPkg.AltPkg; altPkg != nil {
syntax = append(syntax, altPkg.Syntax...)
syntax = altPkg.Syntax
}
showDetail := verbose && pkgExists(ctx.initial, pkg)
if showDetail {
llssa.SetDebug(llssa.DbgFlagAll)
cl.SetDebug(cl.DbgFlagAll)
}

ret, err := cl.NewPackageEx(ctx.prog, ctx.patches, aPkg.SSA, syntax)
ret, err := cl.NewPackageEx(ctx.ctx, aPkg.SSA, pkg.Syntax, syntax)
if showDetail {
llssa.SetDebug(0)
cl.SetDebug(0)
Expand Down Expand Up @@ -676,6 +684,8 @@ func canSkipToBuild(pkgPath string) bool {
switch pkgPath {
case "unsafe":
return true
case "runtime/cgo":
return true
default:
return strings.HasPrefix(pkgPath, "internal/") ||
strings.HasPrefix(pkgPath, "runtime/internal/")
Expand Down

0 comments on commit da8aab0

Please sign in to comment.