patch: Clone/Merge

This commit is contained in:
xushiwei
2024-06-28 15:14:30 +08:00
parent 2165941026
commit fe18c35dab
6 changed files with 78 additions and 70 deletions

14
_demo/iodemo/io.go Normal file
View 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)
}

View File

@@ -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{})
}

View File

@@ -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
}
// -----------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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
}