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(
|
||||
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{})
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ type pkgInfo struct {
|
||||
kind int
|
||||
}
|
||||
|
||||
type none struct{}
|
||||
type none = struct{}
|
||||
|
||||
type context struct {
|
||||
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)
|
||||
ret = b.MakeInterface(t, x)
|
||||
ret = b.MakeInterface(t, patchValue(p, x))
|
||||
case *ssa.MakeSlice:
|
||||
var nCap llssa.Expr
|
||||
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.
|
||||
type Patches = map[string]*ssa.Package
|
||||
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) {
|
||||
@@ -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) {
|
||||
pkgProg := pkg.Prog
|
||||
pkgTypes := pkg.Pkg
|
||||
oldTypes := pkgTypes
|
||||
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
|
||||
alt, hasPatch := patches[pkgPath]
|
||||
patch, hasPatch := patches[pkgPath]
|
||||
if hasPatch {
|
||||
pkgTypes = typepatch.Pkg(pkgTypes, alt.Pkg)
|
||||
pkgTypes = patch.Types
|
||||
pkg.Pkg = pkgTypes
|
||||
alt.Pkg = pkgTypes
|
||||
patch.Alt.Pkg = pkgTypes
|
||||
}
|
||||
if pkgPath == llssa.PkgRuntime {
|
||||
prog.SetRuntime(pkgTypes)
|
||||
@@ -781,12 +789,13 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
||||
|
||||
if hasPatch {
|
||||
skips := ctx.skips
|
||||
typepatch.Merge(pkgTypes, oldTypes, skips, ctx.skipall)
|
||||
ctx.skips = nil
|
||||
ctx.state = pkgInPatch
|
||||
if _, ok := skips["init"]; ok || ctx.skipall {
|
||||
ctx.state |= pkgFNoOldInit
|
||||
}
|
||||
processPkg(ctx, ret, alt)
|
||||
processPkg(ctx, ret, patch.Alt)
|
||||
ctx.state = pkgHasPatch
|
||||
ctx.skips = skips
|
||||
}
|
||||
@@ -847,10 +856,29 @@ func globalType(gbl *ssa.Global) types.Type {
|
||||
if t, ok := t.(*types.Named); ok {
|
||||
o := t.Obj()
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
kind, _ := pkgKindByScope(scope)
|
||||
if kind == PkgNormal {
|
||||
if alt, ok := p.patches[pkgPath]; ok {
|
||||
pkg = alt.Pkg
|
||||
if patch, ok := p.patches[pkgPath]; ok {
|
||||
pkg = patch.Alt.Pkg
|
||||
scope = pkg.Scope()
|
||||
if kind, _ = pkgKindByScope(scope); kind != PkgNormal {
|
||||
goto start
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
|
||||
"github.com/goplus/llgo/cl"
|
||||
"github.com/goplus/llgo/internal/packages"
|
||||
"github.com/goplus/llgo/internal/typepatch"
|
||||
"github.com/goplus/llgo/ssa/abi"
|
||||
"github.com/goplus/llgo/xtool/clang"
|
||||
"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) {
|
||||
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 {
|
||||
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) {
|
||||
path := p.PkgPath[len(altPkgPathPrefix):]
|
||||
patches[path] = pkgSSA
|
||||
patches[path] = cl.Patch{Alt: pkgSSA, Types: typepatch.Clone(typs)}
|
||||
if debugBuild || verbose {
|
||||
log.Println("==> Patching", path)
|
||||
}
|
||||
|
||||
@@ -43,20 +43,6 @@ type typesScope struct {
|
||||
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 (
|
||||
tagPatched = 0x17
|
||||
)
|
||||
@@ -79,25 +65,6 @@ func setScope(pkg *types.Package, scope *types.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 {
|
||||
s := (*typesScope)(unsafe.Pointer(scope))
|
||||
return s.elems
|
||||
@@ -108,35 +75,33 @@ func setElems(scope *types.Scope, elems map[string]types.Object) {
|
||||
s.elems = elems
|
||||
}
|
||||
|
||||
func Pkg(pkg, alt *types.Package) *types.Package {
|
||||
ret := *pkg
|
||||
scope := *pkg.Scope()
|
||||
func Clone(alt *types.Package) *types.Package {
|
||||
ret := *alt
|
||||
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)
|
||||
elems := make(map[string]types.Object, len(old))
|
||||
for name, o := range old {
|
||||
elems[name] = o
|
||||
}
|
||||
setElems(&scope, elems)
|
||||
setScope(alt, &scope)
|
||||
|
||||
altScope := alt.Scope()
|
||||
for name, o := range getElems(altScope) {
|
||||
/*
|
||||
switch o := o.(type) {
|
||||
case *types.TypeName:
|
||||
if t, ok := o.Type().(*types.Named); ok {
|
||||
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||
m := t.Method(i)
|
||||
setPkg(m, &ret)
|
||||
for name, o := range getElems(pkg.Scope()) {
|
||||
if _, ok := elems[name]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := skips[name]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
setPkgAndParent(o, &ret, &scope)
|
||||
*/
|
||||
elems[name] = o
|
||||
}
|
||||
setElems(&scope, elems)
|
||||
setScope(&ret, &scope)
|
||||
setPatched(pkg)
|
||||
// setPath(alt, ret.Path())
|
||||
return &ret
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user