ssa: binop equal(func,slice,array,struct) and buildConstStr
This commit is contained in:
@@ -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 {
|
||||
|
||||
81
ssa/expr.go
81
ssa/expr.go
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user