importPkg refactor: don't depend token.Pos
This commit is contained in:
2
c/c.go
2
c/c.go
@@ -40,7 +40,7 @@ type integer interface {
|
|||||||
//go:linkname Str llgo.cstr
|
//go:linkname Str llgo.cstr
|
||||||
func Str(string) *Char
|
func Str(string) *Char
|
||||||
|
|
||||||
//go:linkname Advance llgo.advance
|
// llgo:link Advance llgo.advance
|
||||||
func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr }
|
func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr }
|
||||||
|
|
||||||
// llgo:link Index llgo.index
|
// llgo:link Index llgo.index
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func main() {
|
|||||||
|
|
||||||
llgen.Verbose = false
|
llgen.Verbose = false
|
||||||
|
|
||||||
|
llgenDir(dir + "/cl/_testlibc")
|
||||||
llgenDir(dir + "/cl/_testrt")
|
llgenDir(dir + "/cl/_testrt")
|
||||||
llgenDir(dir+"/cl/_testdata", "")
|
llgenDir(dir+"/cl/_testdata", "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@__llgo_argc = global ptr null
|
@__llgo_argc = global ptr null
|
||||||
@__llgo_argv = global ptr null
|
@__llgo_argv = global ptr null
|
||||||
@@ -33,17 +31,11 @@ _llgo_0:
|
|||||||
store ptr %1, ptr @__llgo_argv, align 8
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 10)
|
%2 = call i32 @main.f(i32 100)
|
||||||
%3 = call ptr @"github.com/goplus/llgo/c.Str"(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %2)
|
||||||
%4 = call i32 @main.f(i32 100)
|
|
||||||
%5 = call i32 (ptr, ...) @printf(ptr %3, i32 %4)
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/c.Str"(%"github.com/goplus/llgo/internal/runtime.String")
|
|
||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
|
||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -165,7 +165,9 @@ func TestErrInitLinkname(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var ctx context
|
var ctx context
|
||||||
ctx.initLinkname("foo", "//go:linkname Printf printf", false)
|
ctx.initLinkname("foo", "//go:linkname Printf printf", func(name string) (isVar bool, ok bool) {
|
||||||
|
return false, name == "Printf"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrVarOf(t *testing.T) {
|
func TestErrVarOf(t *testing.T) {
|
||||||
|
|||||||
93
cl/import.go
93
cl/import.go
@@ -29,19 +29,49 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
type contentLines = [][]byte
|
type symInfo struct {
|
||||||
type contentMap = map[string]contentLines
|
file string
|
||||||
|
isVar bool
|
||||||
|
}
|
||||||
|
|
||||||
func contentOf(m contentMap, file string) (lines contentLines, err error) {
|
type pkgSymInfo struct {
|
||||||
if v, ok := m[file]; ok {
|
files map[string][]byte // file => content
|
||||||
return v, nil
|
syms map[string]symInfo // name => isVar
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPkgSymInfo() *pkgSymInfo {
|
||||||
|
return &pkgSymInfo{
|
||||||
|
files: make(map[string][]byte),
|
||||||
|
syms: make(map[string]symInfo),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pkgSymInfo) addSym(fset *token.FileSet, pos token.Pos, name string, isVar bool) {
|
||||||
|
f := fset.File(pos)
|
||||||
|
if fp := f.Position(pos); fp.Line > 2 {
|
||||||
|
file := fp.Filename
|
||||||
|
if _, ok := p.files[file]; !ok {
|
||||||
b, err := os.ReadFile(file)
|
b, err := os.ReadFile(file)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
lines = bytes.Split(b, []byte{'\n'})
|
p.files[file] = b
|
||||||
m[file] = lines
|
}
|
||||||
|
}
|
||||||
|
p.syms[name] = symInfo{file, isVar}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pkgSymInfo) initLinknames(ctx *context, pkgPath string) {
|
||||||
|
for file, b := range p.files {
|
||||||
|
lines := bytes.Split(b, []byte{'\n'})
|
||||||
|
for _, line := range lines {
|
||||||
|
ctx.initLinkname(pkgPath, string(line), func(name string) (isVar bool, ok bool) {
|
||||||
|
if sym, ok := p.syms[name]; ok && file == sym.file {
|
||||||
|
return sym.isVar, true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PkgKindOf returns the kind of a package.
|
// PkgKindOf returns the kind of a package.
|
||||||
@@ -87,23 +117,23 @@ func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
|||||||
i.kind = kind
|
i.kind = kind
|
||||||
fset := p.fset
|
fset := p.fset
|
||||||
names := scope.Names()
|
names := scope.Names()
|
||||||
contents := make(contentMap)
|
syms := newPkgSymInfo()
|
||||||
pkgPath := llssa.PathOf(pkg)
|
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if token.IsExported(name) {
|
if token.IsExported(name) {
|
||||||
obj := scope.Lookup(name)
|
obj := scope.Lookup(name)
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.Func:
|
case *types.Func:
|
||||||
if pos := obj.Pos(); pos != token.NoPos {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
p.initLinknameByPos(fset, pos, pkgPath, contents, false)
|
syms.addSym(fset, pos, name, false)
|
||||||
}
|
}
|
||||||
case *types.Var:
|
case *types.Var:
|
||||||
if pos := obj.Pos(); pos != token.NoPos {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
p.initLinknameByPos(fset, pos, pkgPath, contents, true)
|
syms.addSym(fset, pos, name, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
syms.initLinknames(p, llssa.PathOf(pkg))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
||||||
@@ -112,66 +142,59 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
|||||||
switch decl := decl.(type) {
|
switch decl := decl.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
if decl.Recv == nil {
|
if decl.Recv == nil {
|
||||||
p.initLinknameByDoc(decl.Doc, pkgPath, false)
|
p.initLinknameByDoc(decl.Doc, pkgPath, decl.Name.Name, false)
|
||||||
}
|
}
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
|
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
|
||||||
p.initLinknameByDoc(decl.Doc, pkgPath, true)
|
if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 {
|
||||||
|
p.initLinknameByDoc(decl.Doc, pkgPath, names[0].Name, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, pkgPath string, isVar bool) {
|
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, pkgPath, expName string, isVar bool) {
|
||||||
if doc != nil {
|
if doc != nil {
|
||||||
if n := len(doc.List); n > 0 {
|
if n := len(doc.List); n > 0 {
|
||||||
line := doc.List[n-1].Text
|
line := doc.List[n-1].Text
|
||||||
p.initLinkname(pkgPath, line, isVar)
|
p.initLinkname(pkgPath, line, func(name string) (bool, bool) {
|
||||||
|
return isVar, name == expName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinknameByPos(fset *token.FileSet, pos token.Pos, pkgPath string, contents contentMap, isVar bool) {
|
func (p *context) initLinkname(pkgPath, line string, f func(name string) (isVar bool, ok bool)) {
|
||||||
f := fset.File(pos)
|
|
||||||
if fp := f.Position(pos); fp.Line > 2 {
|
|
||||||
lines, err := contentOf(contents, fp.Filename)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if i := fp.Line - 2; i < len(lines) {
|
|
||||||
line := string(lines[i])
|
|
||||||
p.initLinkname(pkgPath, line, isVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *context) initLinkname(pkgPath, line string, isVar bool) {
|
|
||||||
const (
|
const (
|
||||||
linkname = "//go:linkname "
|
linkname = "//go:linkname "
|
||||||
llgolink = "//llgo:link "
|
llgolink = "//llgo:link "
|
||||||
llgolink2 = "// llgo:link "
|
llgolink2 = "// llgo:link "
|
||||||
)
|
)
|
||||||
if strings.HasPrefix(line, linkname) {
|
if strings.HasPrefix(line, linkname) {
|
||||||
p.initLink(pkgPath, line, len(linkname), isVar)
|
p.initLink(pkgPath, line, len(linkname), f)
|
||||||
} else if strings.HasPrefix(line, llgolink2) {
|
} else if strings.HasPrefix(line, llgolink2) {
|
||||||
p.initLink(pkgPath, line, len(llgolink2), isVar)
|
p.initLink(pkgPath, line, len(llgolink2), f)
|
||||||
} else if strings.HasPrefix(line, llgolink) {
|
} else if strings.HasPrefix(line, llgolink) {
|
||||||
p.initLink(pkgPath, line, len(llgolink), isVar)
|
p.initLink(pkgPath, line, len(llgolink), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLink(pkgPath string, line string, prefix int, isVar bool) {
|
func (p *context) initLink(pkgPath string, line string, prefix int, f func(name string) (isVar bool, ok bool)) {
|
||||||
text := strings.TrimSpace(line[prefix:])
|
text := strings.TrimSpace(line[prefix:])
|
||||||
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
||||||
|
name := text[:idx]
|
||||||
|
if isVar, ok := f(name); ok {
|
||||||
link := strings.TrimLeft(text[idx+1:], " ")
|
link := strings.TrimLeft(text[idx+1:], " ")
|
||||||
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
||||||
name := pkgPath + "." + text[:idx]
|
name := pkgPath + "." + name
|
||||||
p.link[name] = link
|
p.link[name] = link
|
||||||
} else {
|
} else {
|
||||||
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func: pkg.name
|
// func: pkg.name
|
||||||
|
|||||||
Reference in New Issue
Block a user