ssa: binop equal(func,slice,array,struct) and buildConstStr

This commit is contained in:
visualfc
2024-06-13 09:40:41 +08:00
parent f3b6d25aaa
commit 0c321c8c98
27 changed files with 4226 additions and 3199 deletions

View File

@@ -317,6 +317,15 @@ func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
b.SetBlockEx(blks[1], AtEnd, false)
b.blk.last = blks[1].last
}
prog := p.Prog
kind, _, _ := abi.DataKindOf(t, 0, prog.is32Bits)
if kind == abi.Integer || kind == abi.BitCast {
// abi.Type.Kind_ |= abi.KindDirectIface
const kindDirectIface = 1 << 5
pkind := b.FieldAddr(vexpr, 6)
b.Store(pkind, b.BinOp(token.OR, b.Load(pkind), Expr{prog.IntVal(kindDirectIface, prog.Byte()).impl, prog.Byte()}))
}
if t, ok := t.(*types.Named); ok {
// skip interface
if _, ok := t.Underlying().(*types.Interface); ok {

View File

@@ -209,13 +209,34 @@ func (b Builder) CStr(v string) Expr {
}
// Str returns a Go string constant expression.
func (b Builder) Str(v string) (ret Expr) {
func (b Builder) Str(v string) Expr {
prog := b.Prog
data := llvm.CreateGlobalStringPtr(b.impl, v)
data := b.createGlobalStr(v)
size := llvm.ConstInt(prog.tyInt(), uint64(len(v)), false)
return Expr{aggregateValue(b.impl, prog.rtString(), data, size), prog.String()}
}
func (b Builder) createGlobalStr(v string) (ret llvm.Value) {
if ret, ok := b.Pkg.strs[v]; ok {
return ret
}
prog := b.Prog
if v != "" {
typ := llvm.ArrayType(prog.tyInt8(), len(v))
global := llvm.AddGlobal(b.Pkg.mod, typ, "")
global.SetInitializer(b.Prog.ctx.ConstString(v, false))
global.SetLinkage(llvm.PrivateLinkage)
global.SetGlobalConstant(true)
global.SetUnnamedAddr(true)
global.SetAlignment(1)
ret = llvm.ConstInBoundsGEP(typ, global, []llvm.Value{prog.Val(0).impl})
} else {
ret = llvm.ConstNull(prog.CStr().ll)
}
b.Pkg.strs[v] = ret
return
}
// unsafeString(data *byte, size int) string
func (b Builder) unsafeString(data, size llvm.Value) Expr {
prog := b.Prog
@@ -384,7 +405,8 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
}
case isPredOp(op): // op: == != < <= < >=
tret := b.Prog.Bool()
prog := b.Prog
tret := prog.Bool()
kind := x.kind
switch kind {
case vkSigned:
@@ -420,8 +442,59 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
ret.impl = llvm.CreateNot(b.impl, ret.impl)
return ret
}
case vkClosure:
x = b.Field(x, 0)
y = b.Field(y, 0)
fallthrough
case vkFuncPtr, vkFuncDecl:
switch op {
case token.EQL:
return Expr{llvm.CreateICmp(b.impl, llvm.IntEQ, x.impl, y.impl), tret}
case token.NEQ:
return Expr{llvm.CreateICmp(b.impl, llvm.IntNE, x.impl, y.impl), tret}
}
case vkArray:
typ := x.raw.Type.(*types.Array)
elem := b.Prog.Elem(x.Type)
ret := prog.BoolVal(true)
for i, n := 0, int(typ.Len()); i < n; i++ {
fx := b.impl.CreateExtractValue(x.impl, i, "")
fy := b.impl.CreateExtractValue(y.impl, i, "")
r := b.BinOp(token.EQL, Expr{fx, elem}, Expr{fy, elem})
ret = Expr{b.impl.CreateAnd(ret.impl, r.impl, ""), tret}
}
switch op {
case token.EQL:
return ret
case token.NEQ:
return Expr{b.impl.CreateNot(ret.impl, ""), tret}
}
case vkStruct:
typ := x.raw.Type.Underlying().(*types.Struct)
ret := prog.BoolVal(true)
for i, n := 0, typ.NumFields(); i < n; i++ {
ft := prog.Type(typ.Field(i).Type(), InGo)
fx := b.impl.CreateExtractValue(x.impl, i, "")
fy := b.impl.CreateExtractValue(y.impl, i, "")
r := b.BinOp(token.EQL, Expr{fx, ft}, Expr{fy, ft})
ret = Expr{b.impl.CreateAnd(ret.impl, r.impl, ""), tret}
}
switch op {
case token.EQL:
return ret
case token.NEQ:
return Expr{b.impl.CreateNot(ret.impl, ""), tret}
}
case vkSlice:
dx := b.impl.CreateExtractValue(x.impl, 0, "")
dy := b.impl.CreateExtractValue(y.impl, 0, "")
switch op {
case token.EQL:
return Expr{b.impl.CreateICmp(llvm.IntEQ, dx, dy, ""), tret}
case token.NEQ:
return Expr{b.impl.CreateICmp(llvm.IntNE, dx, dy, ""), tret}
}
case vkIface, vkEface:
prog := b.Prog
toEface := func(x Expr, emtpy bool) Expr {
if emtpy {
return x

View File

@@ -294,12 +294,13 @@ func (p Program) NewPackage(name, pkgPath string) Package {
stubs := make(map[string]Function)
pyobjs := make(map[string]PyObjRef)
pymods := make(map[string]Global)
strs := make(map[string]llvm.Value)
p.NeedRuntime = false
// Don't need reset p.needPyInit here
// p.needPyInit = false
ret := &aPackage{
mod: mod, vars: gbls, fns: fns, stubs: stubs,
pyobjs: pyobjs, pymods: pymods, Prog: p}
pyobjs: pyobjs, pymods: pymods, strs: strs, Prog: p}
ret.abi.Init(pkgPath)
return ret
}
@@ -544,6 +545,7 @@ type aPackage struct {
stubs map[string]Function
pyobjs map[string]PyObjRef
pymods map[string]Global
strs map[string]llvm.Value
afterb unsafe.Pointer
iRoutine int