This commit is contained in:
13
cl/_testdata/cpkg/in.go
Normal file
13
cl/_testdata/cpkg/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package C
|
||||||
|
|
||||||
|
func Xadd(a, b int) int {
|
||||||
|
return add(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Double(x float64) float64 {
|
||||||
|
return 2 * x
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
35
cl/_testdata/cpkg/out.ll
Normal file
35
cl/_testdata/cpkg/out.ll
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/cl/_testdata/cpkg'
|
||||||
|
source_filename = "github.com/goplus/llgo/cl/_testdata/cpkg"
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/cl/_testdata/cpkg.init$guard" = global i1 false, align 1
|
||||||
|
|
||||||
|
define double @Double(double %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = fmul double 2.000000e+00, %0
|
||||||
|
ret double %1
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @add(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = call i64 @"github.com/goplus/llgo/cl/_testdata/cpkg.add"(i64 %0, i64 %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testdata/cpkg.add"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testdata/cpkg.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testdata/cpkg.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/cl/_testdata/cpkg.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
@@ -1005,7 +1005,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
|||||||
cgoSymbols: make([]string, 0, 128),
|
cgoSymbols: make([]string, 0, 128),
|
||||||
}
|
}
|
||||||
ctx.initPyModule()
|
ctx.initPyModule()
|
||||||
ctx.initFiles(pkgPath, files)
|
ctx.initFiles(pkgPath, files, pkgName == "C")
|
||||||
ctx.prog.SetPatch(ctx.patchType)
|
ctx.prog.SetPatch(ctx.patchType)
|
||||||
ret.SetPatch(ctx.patchType)
|
ret.SetPatch(ctx.patchType)
|
||||||
ret.SetResolveLinkname(ctx.resolveLinkname)
|
ret.SetResolveLinkname(ctx.resolveLinkname)
|
||||||
|
|||||||
54
cl/import.go
54
cl/import.go
@@ -174,13 +174,18 @@ start:
|
|||||||
syms.initLinknames(p)
|
syms.initLinknames(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
func (p *context) initFiles(pkgPath string, files []*ast.File, cPkg bool) {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
for _, decl := range file.Decls {
|
for _, decl := range file.Decls {
|
||||||
switch decl := decl.(type) {
|
switch decl := decl.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
fullName, inPkgName := astFuncName(pkgPath, decl)
|
fullName, inPkgName := astFuncName(pkgPath, decl)
|
||||||
p.initLinknameByDoc(decl.Doc, fullName, inPkgName, false)
|
if !p.initLinknameByDoc(decl.Doc, fullName, inPkgName, false) && cPkg {
|
||||||
|
// package C (https://github.com/goplus/llgo/issues/1165)
|
||||||
|
if decl.Recv == nil && token.IsExported(inPkgName) {
|
||||||
|
p.prog.SetLinkname(fullName, strings.TrimPrefix(inPkgName, "X"))
|
||||||
|
}
|
||||||
|
}
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
switch decl.Tok {
|
switch decl.Tok {
|
||||||
case token.VAR:
|
case token.VAR:
|
||||||
@@ -266,51 +271,58 @@ 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) bool {
|
||||||
if doc != nil {
|
if doc != nil {
|
||||||
for n := len(doc.List) - 1; n >= 0; n-- {
|
for n := len(doc.List) - 1; n >= 0; n-- {
|
||||||
line := doc.List[n].Text
|
line := doc.List[n].Text
|
||||||
found := p.initLinkname(line, func(name string) (_ string, _, ok bool) {
|
ret := p.initLinkname(line, func(name string) (_ string, _, ok bool) {
|
||||||
return fullName, isVar, name == inPkgName
|
return fullName, isVar, name == inPkgName
|
||||||
})
|
})
|
||||||
if !found {
|
if ret != unknownDirective {
|
||||||
break
|
return ret == hasLinkname
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok bool)) bool {
|
const (
|
||||||
|
noDirective = iota
|
||||||
|
hasLinkname
|
||||||
|
unknownDirective = -1
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok bool)) int {
|
||||||
const (
|
const (
|
||||||
linkname = "//go:linkname "
|
linkname = "//go:linkname "
|
||||||
llgolink = "//llgo:link "
|
llgolink = "//llgo:link "
|
||||||
llgolink2 = "// llgo:link "
|
llgolink2 = "// llgo:link "
|
||||||
exportName = "//export "
|
export = "//export "
|
||||||
directive = "//go:"
|
directive = "//go:"
|
||||||
)
|
)
|
||||||
if strings.HasPrefix(line, linkname) {
|
if strings.HasPrefix(line, linkname) {
|
||||||
p.initLink(line, len(linkname), f)
|
p.initLink(line, len(linkname), f)
|
||||||
return true
|
return hasLinkname
|
||||||
} else if strings.HasPrefix(line, llgolink2) {
|
} else if strings.HasPrefix(line, llgolink2) {
|
||||||
p.initLink(line, len(llgolink2), f)
|
p.initLink(line, len(llgolink2), f)
|
||||||
return true
|
return hasLinkname
|
||||||
} else if strings.HasPrefix(line, llgolink) {
|
} else if strings.HasPrefix(line, llgolink) {
|
||||||
p.initLink(line, len(llgolink), f)
|
p.initLink(line, len(llgolink), f)
|
||||||
return true
|
return hasLinkname
|
||||||
} else if strings.HasPrefix(line, exportName) {
|
} else if strings.HasPrefix(line, export) {
|
||||||
p.initCgoExport(line, len(exportName), f)
|
p.initCgoExport(line, len(export), f)
|
||||||
return true
|
return hasLinkname
|
||||||
} else if strings.HasPrefix(line, directive) {
|
} else if strings.HasPrefix(line, directive) {
|
||||||
// skip unknown annotation but continue to parse the next annotation
|
// skip unknown annotation but continue to parse the next annotation
|
||||||
return true
|
return unknownDirective
|
||||||
}
|
}
|
||||||
return false
|
return noDirective
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initCgoExport(line string, prefix int, f func(inPkgName string) (fullName string, isVar, ok bool)) {
|
func (p *context) initCgoExport(line string, prefix int, f func(inPkgName string) (fullName string, isVar, ok bool)) {
|
||||||
name := strings.TrimSpace(line[prefix:])
|
name := strings.TrimSpace(line[prefix:])
|
||||||
if fullName, _, ok := f(name); ok {
|
if fullName, _, ok := f(name); ok {
|
||||||
p.cgoExports[fullName] = name
|
p.cgoExports[fullName] = name // TODO(xsw): why not use prog.SetLinkname?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
prog := llssa.NewProgram(target)
|
prog := llssa.NewProgram(target)
|
||||||
sizes := func(sizes types.Sizes, compiler, arch string) types.Sizes {
|
sizes := func(sizes types.Sizes, compiler, arch string) types.Sizes {
|
||||||
if arch == "wasm" {
|
if arch == "wasm" {
|
||||||
sizes = &types.StdSizes{4, 4}
|
sizes = &types.StdSizes{WordSize: 4, MaxAlign: 4}
|
||||||
}
|
}
|
||||||
return prog.TypeSizes(sizes)
|
return prog.TypeSizes(sizes)
|
||||||
}
|
}
|
||||||
@@ -803,7 +803,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
|
|||||||
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
||||||
}
|
}
|
||||||
if IsCheckEnable() {
|
if IsCheckEnable() {
|
||||||
if err, msg := llcCheck(ctx.env, pkg.ExportFile); err != nil {
|
if msg, err := llcCheck(ctx.env, pkg.ExportFile); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "==> lcc %v: %v\n%v\n", pkg.PkgPath, pkg.ExportFile, msg)
|
fmt.Fprintf(os.Stderr, "==> lcc %v: %v\n%v\n", pkg.PkgPath, pkg.ExportFile, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,7 +811,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func llcCheck(env *llvm.Env, exportFile string) (err error, msg string) {
|
func llcCheck(env *llvm.Env, exportFile string) (msg string, err error) {
|
||||||
bin := filepath.Join(env.BinDir(), "llc")
|
bin := filepath.Join(env.BinDir(), "llc")
|
||||||
cmd := exec.Command(bin, "-filetype=null", exportFile)
|
cmd := exec.Command(bin, "-filetype=null", exportFile)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@@ -904,6 +904,7 @@ func createSSAPkg(prog *ssa.Program, p *packages.Package, verbose bool) *ssa.Pac
|
|||||||
return pkgSSA
|
return pkgSSA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
var (
|
var (
|
||||||
// TODO(xsw): complete build flags
|
// TODO(xsw): complete build flags
|
||||||
buildFlags = map[string]bool{
|
buildFlags = map[string]bool{
|
||||||
@@ -922,6 +923,7 @@ var (
|
|||||||
"-ldflags": true, // --ldflags 'flag list': arguments to pass on each go tool link invocation
|
"-ldflags": true, // --ldflags 'flag list': arguments to pass on each go tool link invocation
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
const llgoDebug = "LLGO_DEBUG"
|
const llgoDebug = "LLGO_DEBUG"
|
||||||
const llgoDbgSyms = "LLGO_DEBUG_SYMBOLS"
|
const llgoDbgSyms = "LLGO_DEBUG_SYMBOLS"
|
||||||
|
|||||||
@@ -26,12 +26,14 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
var (
|
var (
|
||||||
// TODO(xsw): complete clean flags
|
// TODO(xsw): complete clean flags
|
||||||
cleanFlags = map[string]bool{
|
cleanFlags = map[string]bool{
|
||||||
"-v": false, // -v: print the paths of packages as they are clean
|
"-v": false, // -v: print the paths of packages as they are clean
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
func Clean(patterns []string, conf *Config) {
|
func Clean(patterns []string, conf *Config) {
|
||||||
if conf.Goos == "" {
|
if conf.Goos == "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user