Merge pull request #879 from cpunion/fix-type-patching

Fix type patching
This commit is contained in:
xushiwei
2024-11-25 11:52:48 +08:00
committed by GitHub
4 changed files with 66 additions and 18 deletions

View File

@@ -0,0 +1,31 @@
package main
import (
"io"
"os"
"sync"
"unsafe"
llsync "github.com/goplus/llgo/c/pthread/sync"
)
type L struct {
mu sync.Mutex
s string
i int
w io.Writer
}
func main() {
l := &L{s: "hello", i: 123, w: os.Stdout}
println("sizeof(L):", unsafe.Sizeof(L{}))
println("sizeof(sync.Mutex):", unsafe.Sizeof(sync.Mutex{}))
println("sizeof(llsync.Mutex):", unsafe.Sizeof(llsync.Mutex{}))
println("l:", l, "l.s:", l.s, "l.i:", l.i, "l.w:", l.w)
l.mu.Lock()
println("locked")
println("l:", l, "l.s:", l.s, "l.i:", l.i, "l.w:", l.w)
l.w.Write([]byte(l.s))
l.w.Write([]byte("\n"))
l.mu.Unlock()
}

View File

@@ -368,7 +368,7 @@ func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
v := p.compileValue(b, param) v := p.compileValue(b, param)
ty := param.Type() ty := param.Type()
argNo := i + 1 argNo := i + 1
div := b.DIVarParam(p.fn, pos, param.Name(), p.prog.Type(ty, llssa.InGo), argNo) div := b.DIVarParam(p.fn, pos, param.Name(), p.type_(ty, llssa.InGo), argNo)
b.DIParam(variable, v, div, p.fn, pos, p.fn.Block(0)) b.DIParam(variable, v, div, p.fn, pos, p.fn.Block(0))
} }
} }
@@ -585,7 +585,7 @@ func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
} }
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) { func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
phi := b.Phi(p.prog.Type(v.Type(), llssa.InGo)) phi := b.Phi(p.type_(v.Type(), llssa.InGo))
ret = phi.Expr ret = phi.Expr
p.phis = append(p.phis, func() { p.phis = append(p.phis, func() {
preds := v.Block().Preds preds := v.Block().Preds
@@ -626,11 +626,11 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
case *ssa.ChangeType: case *ssa.ChangeType:
t := v.Type() t := v.Type()
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.ChangeType(p.prog.Type(t, llssa.InGo), x) ret = b.ChangeType(p.type_(t, llssa.InGo), x)
case *ssa.Convert: case *ssa.Convert:
t := v.Type() t := v.Type()
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.Convert(p.prog.Type(t, llssa.InGo), x) ret = b.Convert(p.type_(t, llssa.InGo), x)
case *ssa.FieldAddr: case *ssa.FieldAddr:
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.FieldAddr(x, v.Field) ret = b.FieldAddr(x, v.Field)
@@ -639,7 +639,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation
return return
} }
elem := p.prog.Type(t.Elem(), llssa.InGo) elem := p.type_(t.Elem(), llssa.InGo)
ret = b.Alloc(elem, v.Heap) ret = b.Alloc(elem, v.Heap)
case *ssa.IndexAddr: case *ssa.IndexAddr:
vx := v.X vx := v.X
@@ -699,18 +699,17 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
} }
} }
} }
prog := p.prog t := p.type_(v.Type(), llssa.InGo)
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, x)
case *ssa.MakeSlice: case *ssa.MakeSlice:
t := p.prog.Type(v.Type(), llssa.InGo) t := p.type_(v.Type(), llssa.InGo)
nLen := p.compileValue(b, v.Len) nLen := p.compileValue(b, v.Len)
nCap := p.compileValue(b, v.Cap) nCap := p.compileValue(b, v.Cap)
ret = b.MakeSlice(t, nLen, nCap) ret = b.MakeSlice(t, nLen, nCap)
case *ssa.MakeMap: case *ssa.MakeMap:
var nReserve llssa.Expr var nReserve llssa.Expr
t := p.prog.Type(v.Type(), llssa.InGo) t := p.type_(v.Type(), llssa.InGo)
if v.Reserve != nil { if v.Reserve != nil {
nReserve = p.compileValue(b, v.Reserve) nReserve = p.compileValue(b, v.Reserve)
} }
@@ -721,7 +720,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
ret = b.MakeClosure(fn, bindings) ret = b.MakeClosure(fn, bindings)
case *ssa.TypeAssert: case *ssa.TypeAssert:
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
t := p.prog.Type(v.AssertedType, llssa.InGo) t := p.type_(v.AssertedType, llssa.InGo)
ret = b.TypeAssert(x, t, v.CommaOk) ret = b.TypeAssert(x, t, v.CommaOk)
case *ssa.Extract: case *ssa.Extract:
x := p.compileValue(b, v.Tuple) x := p.compileValue(b, v.Tuple)
@@ -732,21 +731,21 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
case *ssa.Next: case *ssa.Next:
var typ llssa.Type var typ llssa.Type
if !v.IsString { if !v.IsString {
typ = p.prog.Type(v.Iter.(*ssa.Range).X.Type(), llssa.InGo) typ = p.type_(v.Iter.(*ssa.Range).X.Type(), llssa.InGo)
} }
iter := p.compileValue(b, v.Iter) iter := p.compileValue(b, v.Iter)
ret = b.Next(typ, iter, v.IsString) ret = b.Next(typ, iter, v.IsString)
case *ssa.ChangeInterface: case *ssa.ChangeInterface:
t := v.Type() t := v.Type()
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.ChangeInterface(p.prog.Type(t, llssa.InGo), x) ret = b.ChangeInterface(p.type_(t, llssa.InGo), x)
case *ssa.Field: case *ssa.Field:
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.Field(x, v.Field) ret = b.Field(x, v.Field)
case *ssa.MakeChan: case *ssa.MakeChan:
t := v.Type() t := v.Type()
size := p.compileValue(b, v.Size) size := p.compileValue(b, v.Size)
ret = b.MakeChan(p.prog.Type(t, llssa.InGo), size) ret = b.MakeChan(p.type_(t, llssa.InGo), size)
case *ssa.Select: case *ssa.Select:
states := make([]*llssa.SelectState, len(v.States)) states := make([]*llssa.SelectState, len(v.States))
for i, s := range v.States { for i, s := range v.States {
@@ -760,7 +759,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
} }
ret = b.Select(states, v.Blocking) ret = b.Select(states, v.Blocking)
case *ssa.SliceToArrayPointer: case *ssa.SliceToArrayPointer:
t := b.Prog.Type(v.Type(), llssa.InGo) t := p.type_(v.Type(), llssa.InGo)
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.SliceToArrayPointer(x, t) ret = b.SliceToArrayPointer(x, t)
default: default:
@@ -866,7 +865,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
func (p *context) getLocalVariable(b llssa.Builder, fn *ssa.Function, v *types.Var) llssa.DIVar { func (p *context) getLocalVariable(b llssa.Builder, fn *ssa.Function, v *types.Var) llssa.DIVar {
pos := p.fset.Position(v.Pos()) pos := p.fset.Position(v.Pos())
t := b.Prog.Type(v.Type(), llssa.InGo) t := p.type_(v.Type(), llssa.InGo)
for i, param := range fn.Params { for i, param := range fn.Params {
if param.Object().(*types.Var) == v { if param.Object().(*types.Var) == v {
argNo := i + 1 argNo := i + 1
@@ -920,7 +919,7 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
if p.inCFunc { if p.inCFunc {
bg = llssa.InC bg = llssa.InC
} }
return b.Const(v.Value, p.prog.Type(t, bg)) return b.Const(v.Value, p.type_(t, bg))
case *ssa.FreeVar: case *ssa.FreeVar:
fn := v.Parent() fn := v.Parent()
for idx, freeVar := range fn.FreeVars { for idx, freeVar := range fn.FreeVars {
@@ -1012,6 +1011,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
} }
ctx.initPyModule() ctx.initPyModule()
ctx.initFiles(pkgPath, files) ctx.initFiles(pkgPath, files)
ctx.prog.SetPatch(ctx.patchType)
ret.SetPatch(ctx.patchType) ret.SetPatch(ctx.patchType)
ret.SetResolveLinkname(ctx.resolveLinkname) ret.SetResolveLinkname(ctx.resolveLinkname)
@@ -1112,6 +1112,10 @@ func globalType(gbl *ssa.Global) types.Type {
return t return t
} }
func (p *context) type_(typ types.Type, bg llssa.Background) llssa.Type {
return p.prog.Type(p.patchType(typ), bg)
}
func (p *context) patchType(typ types.Type) types.Type { func (p *context) patchType(typ types.Type) types.Type {
if t, ok := typ.(*types.Named); ok { if t, ok := typ.(*types.Named); ok {
o := t.Obj() o := t.Obj()

View File

@@ -105,6 +105,8 @@ type aProgram struct {
sizes types.Sizes // provided by Go compiler sizes types.Sizes // provided by Go compiler
gocvt goTypes gocvt goTypes
patchType func(types.Type) types.Type
rt *types.Package rt *types.Package
rtget func() *types.Package rtget func() *types.Package
@@ -233,6 +235,17 @@ func NewProgram(target *Target) Program {
} }
} }
func (p Program) SetPatch(patchType func(types.Type) types.Type) {
p.patchType = patchType
}
func (p Program) patch(typ types.Type) types.Type {
if p.patchType != nil {
return p.patchType(typ)
}
return typ
}
// SetRuntime sets the runtime. // SetRuntime sets the runtime.
// Its type can be *types.Package or func() *types.Package. // Its type can be *types.Package or func() *types.Package.
func (p Program) SetRuntime(runtime any) { func (p Program) SetRuntime(runtime any) {

View File

@@ -429,7 +429,7 @@ func (p Program) toLLVMFields(raw *types.Struct) (fields []llvm.Type) {
if n > 0 { if n > 0 {
fields = make([]llvm.Type, n) fields = make([]llvm.Type, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
fields[i] = p.rawType(raw.Field(i).Type()).ll fields[i] = p.rawType(p.patch(raw.Field(i).Type())).ll
} }
} }
return return
@@ -443,7 +443,7 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
if n > 0 { if n > 0 {
ret = make([]llvm.Type, n) ret = make([]llvm.Type, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
ret[i] = p.rawType(t.At(i).Type()).ll ret[i] = p.rawType(p.patch(t.At(i).Type())).ll
} }
} }
return return