patch: Clone/Merge
This commit is contained in:
14
_demo/iodemo/io.go
Normal file
14
_demo/iodemo/io.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f(w io.Writer) {
|
||||||
|
w.Write([]byte("Hello, world\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f(os.Stdout)
|
||||||
|
}
|
||||||
@@ -227,7 +227,7 @@ func TestErrImport(t *testing.T) {
|
|||||||
alt.Scope().Insert(
|
alt.Scope().Insert(
|
||||||
types.NewConst(0, alt, "LLGoPackage", types.Typ[types.String], constant.MakeString("noinit")),
|
types.NewConst(0, alt, "LLGoPackage", types.Typ[types.String], constant.MakeString("noinit")),
|
||||||
)
|
)
|
||||||
ctx.patches = Patches{"foo": &ssa.Package{Pkg: alt}}
|
ctx.patches = Patches{"foo": Patch{Alt: &ssa.Package{Pkg: alt}, Types: alt}}
|
||||||
ctx.importPkg(pkg, &pkgInfo{})
|
ctx.importPkg(pkg, &pkgInfo{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ type pkgInfo struct {
|
|||||||
kind int
|
kind int
|
||||||
}
|
}
|
||||||
|
|
||||||
type none struct{}
|
type none = struct{}
|
||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
prog llssa.Program
|
prog llssa.Program
|
||||||
@@ -539,9 +539,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t := p.prog.Type(v.Type(), llssa.InGo)
|
prog := p.prog
|
||||||
|
t := prog.Type(v.Type(), llssa.InGo)
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.MakeInterface(t, x)
|
ret = b.MakeInterface(t, patchValue(p, x))
|
||||||
case *ssa.MakeSlice:
|
case *ssa.MakeSlice:
|
||||||
var nCap llssa.Expr
|
var nCap llssa.Expr
|
||||||
t := p.prog.Type(v.Type(), llssa.InGo)
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
@@ -737,8 +738,14 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Patch is a patch of some package.
|
||||||
|
type Patch struct {
|
||||||
|
Alt *ssa.Package
|
||||||
|
Types *types.Package
|
||||||
|
}
|
||||||
|
|
||||||
// Patches is patches of some packages.
|
// Patches is patches of some packages.
|
||||||
type Patches = map[string]*ssa.Package
|
type Patches = map[string]Patch
|
||||||
|
|
||||||
// NewPackage compiles a Go package to LLVM IR package.
|
// 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) {
|
func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
|
||||||
@@ -749,12 +756,13 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
|
func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
|
||||||
pkgProg := pkg.Prog
|
pkgProg := pkg.Prog
|
||||||
pkgTypes := pkg.Pkg
|
pkgTypes := pkg.Pkg
|
||||||
|
oldTypes := pkgTypes
|
||||||
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
|
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
|
||||||
alt, hasPatch := patches[pkgPath]
|
patch, hasPatch := patches[pkgPath]
|
||||||
if hasPatch {
|
if hasPatch {
|
||||||
pkgTypes = typepatch.Pkg(pkgTypes, alt.Pkg)
|
pkgTypes = patch.Types
|
||||||
pkg.Pkg = pkgTypes
|
pkg.Pkg = pkgTypes
|
||||||
alt.Pkg = pkgTypes
|
patch.Alt.Pkg = pkgTypes
|
||||||
}
|
}
|
||||||
if pkgPath == llssa.PkgRuntime {
|
if pkgPath == llssa.PkgRuntime {
|
||||||
prog.SetRuntime(pkgTypes)
|
prog.SetRuntime(pkgTypes)
|
||||||
@@ -781,12 +789,13 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
|||||||
|
|
||||||
if hasPatch {
|
if hasPatch {
|
||||||
skips := ctx.skips
|
skips := ctx.skips
|
||||||
|
typepatch.Merge(pkgTypes, oldTypes, skips, ctx.skipall)
|
||||||
ctx.skips = nil
|
ctx.skips = nil
|
||||||
ctx.state = pkgInPatch
|
ctx.state = pkgInPatch
|
||||||
if _, ok := skips["init"]; ok || ctx.skipall {
|
if _, ok := skips["init"]; ok || ctx.skipall {
|
||||||
ctx.state |= pkgFNoOldInit
|
ctx.state |= pkgFNoOldInit
|
||||||
}
|
}
|
||||||
processPkg(ctx, ret, alt)
|
processPkg(ctx, ret, patch.Alt)
|
||||||
ctx.state = pkgHasPatch
|
ctx.state = pkgHasPatch
|
||||||
ctx.skips = skips
|
ctx.skips = skips
|
||||||
}
|
}
|
||||||
@@ -847,10 +856,29 @@ func globalType(gbl *ssa.Global) types.Type {
|
|||||||
if t, ok := t.(*types.Named); ok {
|
if t, ok := t.(*types.Named); ok {
|
||||||
o := t.Obj()
|
o := t.Obj()
|
||||||
if pkg := o.Pkg(); typepatch.IsPatched(pkg) {
|
if pkg := o.Pkg(); typepatch.IsPatched(pkg) {
|
||||||
return gbl.Pkg.Pkg.Scope().Lookup(o.Name()).Type()
|
if patch := gbl.Pkg.Pkg.Scope().Lookup(o.Name()); patch != nil {
|
||||||
|
return patch.Type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func patchValue(ctx *context, v llssa.Expr) llssa.Expr {
|
||||||
|
/* TODO(xsw):
|
||||||
|
t := v.RawType()
|
||||||
|
if t, ok := t.(*types.Named); ok {
|
||||||
|
o := t.Obj()
|
||||||
|
if pkg := o.Pkg(); typepatch.IsPatched(pkg) {
|
||||||
|
if patch, ok := ctx.patches[pkg.Path()]; ok {
|
||||||
|
if obj := patch.Types.Scope().Lookup(o.Name()); obj != nil {
|
||||||
|
v.Type = ctx.prog.Type(obj.Type(), llssa.InGo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
|||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
kind, _ := pkgKindByScope(scope)
|
kind, _ := pkgKindByScope(scope)
|
||||||
if kind == PkgNormal {
|
if kind == PkgNormal {
|
||||||
if alt, ok := p.patches[pkgPath]; ok {
|
if patch, ok := p.patches[pkgPath]; ok {
|
||||||
pkg = alt.Pkg
|
pkg = patch.Alt.Pkg
|
||||||
scope = pkg.Scope()
|
scope = pkg.Scope()
|
||||||
if kind, _ = pkgKindByScope(scope); kind != PkgNormal {
|
if kind, _ = pkgKindByScope(scope); kind != PkgNormal {
|
||||||
goto start
|
goto start
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import (
|
|||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
|
"github.com/goplus/llgo/internal/typepatch"
|
||||||
"github.com/goplus/llgo/ssa/abi"
|
"github.com/goplus/llgo/ssa/abi"
|
||||||
"github.com/goplus/llgo/xtool/clang"
|
"github.com/goplus/llgo/xtool/clang"
|
||||||
"github.com/goplus/llgo/xtool/env"
|
"github.com/goplus/llgo/xtool/env"
|
||||||
@@ -449,14 +450,14 @@ func altPkgs(initial []*packages.Package, alts ...string) []string {
|
|||||||
|
|
||||||
func altSSAPkgs(prog *ssa.Program, patches cl.Patches, alts []*packages.Package, verbose bool) {
|
func altSSAPkgs(prog *ssa.Program, patches cl.Patches, alts []*packages.Package, verbose bool) {
|
||||||
packages.Visit(alts, nil, func(p *packages.Package) {
|
packages.Visit(alts, nil, func(p *packages.Package) {
|
||||||
if p.Types != nil && !p.IllTyped {
|
if typs := p.Types; typs != nil && !p.IllTyped {
|
||||||
if debugBuild || verbose {
|
if debugBuild || verbose {
|
||||||
log.Println("==> BuildSSA", p.PkgPath)
|
log.Println("==> BuildSSA", p.PkgPath)
|
||||||
}
|
}
|
||||||
pkgSSA := prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true)
|
pkgSSA := prog.CreatePackage(typs, p.Syntax, p.TypesInfo, true)
|
||||||
if strings.HasPrefix(p.PkgPath, altPkgPathPrefix) {
|
if strings.HasPrefix(p.PkgPath, altPkgPathPrefix) {
|
||||||
path := p.PkgPath[len(altPkgPathPrefix):]
|
path := p.PkgPath[len(altPkgPathPrefix):]
|
||||||
patches[path] = pkgSSA
|
patches[path] = cl.Patch{Alt: pkgSSA, Types: typepatch.Clone(typs)}
|
||||||
if debugBuild || verbose {
|
if debugBuild || verbose {
|
||||||
log.Println("==> Patching", path)
|
log.Println("==> Patching", path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,20 +43,6 @@ type typesScope struct {
|
|||||||
isFunc bool
|
isFunc bool
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
type object struct {
|
|
||||||
parent *types.Scope
|
|
||||||
pos token.Pos
|
|
||||||
pkg *types.Package // TODO(xsw): ensure offset of pkg
|
|
||||||
unused [8]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type iface struct {
|
|
||||||
tab unsafe.Pointer
|
|
||||||
data unsafe.Pointer
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tagPatched = 0x17
|
tagPatched = 0x17
|
||||||
)
|
)
|
||||||
@@ -79,25 +65,6 @@ func setScope(pkg *types.Package, scope *types.Scope) {
|
|||||||
p.scope = scope
|
p.scope = scope
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func setPath(pkg *types.Package, path string) {
|
|
||||||
p := (*typesPackage)(unsafe.Pointer(pkg))
|
|
||||||
p.path = path
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func setPkg(o types.Object, pkg *types.Package) {
|
|
||||||
data := (*iface)(unsafe.Pointer(&o)).data
|
|
||||||
(*object)(data).pkg = pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
func setPkgAndParent(o types.Object, pkg *types.Package, parent *types.Scope) {
|
|
||||||
data := (*iface)(unsafe.Pointer(&o)).data
|
|
||||||
(*object)(data).pkg = pkg
|
|
||||||
(*object)(data).parent = parent
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func getElems(scope *types.Scope) map[string]types.Object {
|
func getElems(scope *types.Scope) map[string]types.Object {
|
||||||
s := (*typesScope)(unsafe.Pointer(scope))
|
s := (*typesScope)(unsafe.Pointer(scope))
|
||||||
return s.elems
|
return s.elems
|
||||||
@@ -108,35 +75,33 @@ func setElems(scope *types.Scope, elems map[string]types.Object) {
|
|||||||
s.elems = elems
|
s.elems = elems
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pkg(pkg, alt *types.Package) *types.Package {
|
func Clone(alt *types.Package) *types.Package {
|
||||||
ret := *pkg
|
ret := *alt
|
||||||
scope := *pkg.Scope()
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func Merge(alt, pkg *types.Package, skips map[string]struct{}, skipall bool) {
|
||||||
|
setPatched(pkg)
|
||||||
|
if skipall {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
scope := *alt.Scope()
|
||||||
old := getElems(&scope)
|
old := getElems(&scope)
|
||||||
elems := make(map[string]types.Object, len(old))
|
elems := make(map[string]types.Object, len(old))
|
||||||
for name, o := range old {
|
for name, o := range old {
|
||||||
elems[name] = o
|
elems[name] = o
|
||||||
}
|
}
|
||||||
|
setElems(&scope, elems)
|
||||||
|
setScope(alt, &scope)
|
||||||
|
|
||||||
altScope := alt.Scope()
|
for name, o := range getElems(pkg.Scope()) {
|
||||||
for name, o := range getElems(altScope) {
|
if _, ok := elems[name]; ok {
|
||||||
/*
|
continue
|
||||||
switch o := o.(type) {
|
}
|
||||||
case *types.TypeName:
|
if _, ok := skips[name]; ok {
|
||||||
if t, ok := o.Type().(*types.Named); ok {
|
continue
|
||||||
for i, n := 0, t.NumMethods(); i < n; i++ {
|
}
|
||||||
m := t.Method(i)
|
|
||||||
setPkg(m, &ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setPkgAndParent(o, &ret, &scope)
|
|
||||||
*/
|
|
||||||
elems[name] = o
|
elems[name] = o
|
||||||
}
|
}
|
||||||
setElems(&scope, elems)
|
|
||||||
setScope(&ret, &scope)
|
|
||||||
setPatched(pkg)
|
|
||||||
// setPath(alt, ret.Path())
|
|
||||||
return &ret
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user