提交 0fa2cfa3 编写于 作者: 3 3dgen

支持非标类型相等操作

上级 e5ed1490
// 版权 @2021 凹语言 作者。保留所有权利。
type T1 struct {
a: i32
b: string
}
func T1.print(){
println("a: ", this.a)
}
type I interface {
print()
}
type T2 struct {
a: []i32
}
func main() {
var v1, v2: T1
v1.a = 13
v2.a = 42
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v2.a = 13
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v1.b = "abc"
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v2.b = "abc"
if v1 == v2 {
println("eq")
} else {
println("ne")
}
var i1, i2: interface{}
i1 = i32(13)
i2 = i32(42)
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = i32(13)
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = "abc"
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i1 = "abc"
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i1 = v1
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = v1
if i1 == i2 {
println("eq")
} else {
println("ne")
}
var i3: I
i3 = &v1
if i1 == i3 {
println("eq")
} else {
println("ne")
}
i1 = &v1
if i1 == i3 {
println("eq")
} else {
println("ne")
}
var v3, v4: T2
//if v3 == v4 {
// println("eq")
//} else {
// println("ne")
//}
i1 = v3
i2 = v4
if i1 == i2 { //panic
println("eq")
} else {
println("ne")
}
}
......@@ -434,49 +434,44 @@ func (g *functionGenerator) genBinOp(inst *ssa.BinOp) ([]wat.Inst, wir.ValueType
x := g.getValue(inst.X)
y := g.getValue(inst.Y)
switch inst.X.Type().Underlying().(type) {
case *types.Basic:
switch inst.Op {
case token.ADD:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAdd)
switch inst.Op {
case token.ADD:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAdd)
case token.SUB:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeSub)
case token.SUB:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeSub)
case token.MUL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeMul)
case token.MUL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeMul)
case token.QUO:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeQuo)
case token.QUO:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeQuo)
case token.REM:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeRem)
case token.REM:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeRem)
case token.EQL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeEql)
case token.EQL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeEql)
case token.NEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeNe)
case token.NEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeNe)
case token.LSS:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLt)
case token.LSS:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLt)
case token.GTR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGt)
case token.GTR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGt)
case token.LEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLe)
case token.LEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLe)
case token.GEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGe)
}
case token.GEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGe)
default:
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, x.value, inst.Op)
return nil, nil
}
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
return nil, nil
}
func (g *functionGenerator) genCall(inst *ssa.Call) (insts []wat.Inst, ret_type wir.ValueType) {
......
......@@ -43,13 +43,28 @@ func (m *Module) EmitUnOp(x Value, op wat.OpCode) (insts []wat.Inst, ret_type Va
}
func (m *Module) EmitBinOp(x, y Value, op wat.OpCode) (insts []wat.Inst, ret_type ValueType) {
rtype := m.binOpMatchType(x.Type(), y.Type())
for {
if ut, ok := x.(*aDup); ok {
x = ut.underlying
} else {
break
}
}
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
for {
if ut, ok := y.(*aDup); ok {
y = ut.underlying
} else {
break
}
}
rtype := m.binOpMatchType(x.Type(), y.Type())
switch op {
case wat.OpCodeAdd:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Append()))
} else {
......@@ -58,52 +73,61 @@ func (m *Module) EmitBinOp(x, y Value, op wat.OpCode) (insts []wat.Inst, ret_typ
ret_type = rtype
case wat.OpCodeSub:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstSub(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeMul:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstMul(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeQuo:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstDiv(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeRem:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstRem(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeEql:
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Equal()))
} else {
insts = append(insts, wat.NewInstEq(toWatType(rtype)))
}
ins, _ := x.emitEq(y)
insts = append(insts, ins...)
ret_type = m.I32
case wat.OpCodeNe:
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Equal()))
insts = append(insts, wat.NewInstConst(wat.I32{}, "1"))
insts = append(insts, wat.NewInstXor(wat.I32{}))
} else {
insts = append(insts, wat.NewInstNe(toWatType(rtype)))
}
ins, _ := x.emitEq(y)
insts = append(insts, ins...)
insts = append(insts, wat.NewInstEqz(wat.I32{}))
ret_type = m.I32
case wat.OpCodeLt:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstLt(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeGt:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstGt(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeLe:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstLe(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeGe:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstGe(toWatType(rtype)))
ret_type = m.I32
......@@ -445,11 +469,50 @@ func (m *Module) EmitGenMakeInterface(x Value, itype ValueType) (insts []wat.Ins
switch x := x.(type) {
case *aRef:
return itype.(*Interface).emitGenFromSPtr(x)
return itype.(*Interface).emitGenFromRef(x)
default:
sptr_t := m.GenValueType_Ref(x.Type())
return itype.(*Interface).emitGenFromValue(x, sptr_t)
compID := x_type.OnComp()
if compID == 0 {
var f Function
f.InternalName = "$" + GenSymbolName(x_type.Name()) + ".$$compAddr"
p0 := NewLocal("p0", m.GenValueType_Ptr(x_type))
p1 := NewLocal("p1", m.GenValueType_Ptr(x_type))
f.Params = append(f.Params, p0)
f.Params = append(f.Params, p1)
f.Results = append(f.Results, m.I32)
v0 := NewLocal("v0", x_type)
v1 := NewLocal("v1", x_type)
f.Locals = append(f.Locals, v0)
f.Locals = append(f.Locals, v1)
f.Insts = append(f.Insts, v0.EmitInit()...)
f.Insts = append(f.Insts, v1.EmitInit()...)
f.Insts = append(f.Insts, x_type.EmitLoadFromAddr(p0, 0)...)
f.Insts = append(f.Insts, v0.EmitPop()...)
f.Insts = append(f.Insts, x_type.EmitLoadFromAddr(p1, 0)...)
f.Insts = append(f.Insts, v1.EmitPop()...)
if ins, ok := v0.emitEq(v1); ok {
f.Insts = append(f.Insts, ins...)
f.Insts = append(f.Insts, v0.EmitRelease()...)
f.Insts = append(f.Insts, v1.EmitRelease()...)
m.AddFunc(&f)
compID = m.AddTableElem(f.InternalName)
} else {
compID = -1
}
x_type.setOnComp(compID)
}
ref_t := m.GenValueType_Ref(x_type)
return itype.(*Interface).emitGenFromValue(x, ref_t, compID)
}
}
......
......@@ -244,6 +244,17 @@ func (m *Module) ToWatModule() *wat.Module {
onfree_type.Params = m.I32.Raw()
wat_module.FuncTypes = append(wat_module.FuncTypes, onfree_type)
}
{
var comp_type wat.FuncType
comp_type.Name = "$wa.runtime.comp"
ptr_t := m.GenValueType_Ptr(m.VOID)
comp_type.Params = append(comp_type.Params, ptr_t.Raw()...)
comp_type.Params = append(comp_type.Params, ptr_t.Raw()...)
comp_type.Results = append(comp_type.Results, m.I32.Raw()...)
wat_module.FuncTypes = append(wat_module.FuncTypes, comp_type)
}
for _, t := range m.fnSigs {
var fn_type wat.FuncType
fn_type.Name = m.fnSigsName[t.String()].name
......
......@@ -206,3 +206,16 @@ func (v *aBasic) Bin() (b []byte) {
return
}
func (v *aBasic) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
insts = append(insts, v.EmitPush()...)
insts = append(insts, r.EmitPush()...)
insts = append(insts, wat.NewInstEq(toWatType(v.Type())))
ok = true
return
}
......@@ -188,3 +188,8 @@ func (v *aBlock) Bin() (b []byte) {
return
}
func (v *aBlock) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aBlock shouldn't be compared.")
return nil, false
}
......@@ -149,3 +149,8 @@ func EmitCallClosure(c Value, params []Value) (insts []wat.Inst) {
insts = append(insts, wat.NewInstCallIndirect(closure.typ._fnTypeName))
return
}
func (v *aClosure) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aClosure can't be compared.")
return nil, false
}
......@@ -4,6 +4,7 @@ package wir
import (
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -79,3 +80,10 @@ func (v *aDup) emitStore(offset int) []wat.Inst {
func (v *aDup) Bin() []byte {
return v.underlying.Bin()
}
func (v *aDup) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
return v.underlying.emitEq(r.(*aDup).underlying)
}
......@@ -6,6 +6,7 @@ import (
"strconv"
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -29,6 +30,7 @@ func (m *Module) GenValueType_Interface(name string) *Interface {
interface_t.underlying = m.genInternalStruct(interface_t.Name() + ".underlying")
interface_t.underlying.AppendField(m.NewStructField("data", m.GenValueType_Ref(m.VOID)))
interface_t.underlying.AppendField(m.NewStructField("itab", m.UPTR))
interface_t.underlying.AppendField(m.NewStructField("eq", m.I32))
interface_t.underlying.Finish()
m.addValueType(&interface_t)
......@@ -52,7 +54,7 @@ func (t *Interface) EmitLoadFromAddr(addr Value, offset int) []wat.Inst {
return t.underlying.EmitLoadFromAddr(addr, offset)
}
func (t *Interface) emitGenFromSPtr(x *aRef) (insts []wat.Inst) {
func (t *Interface) emitGenFromRef(x *aRef) (insts []wat.Inst) {
insts = append(insts, x.EmitPush()...) //data
insts = append(insts, wat.NewInstConst(wat.I32{}, strconv.Itoa(x.Type().Hash())))
......@@ -60,10 +62,12 @@ func (t *Interface) emitGenFromSPtr(x *aRef) (insts []wat.Inst) {
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, wat.NewInstConst(wat.I32{}, "0")) //eq
return
}
func (t *Interface) emitGenFromValue(x Value, xRefType *Ref) (insts []wat.Inst) {
func (t *Interface) emitGenFromValue(x Value, xRefType *Ref, compID int) (insts []wat.Inst) {
insts = append(insts, xRefType.emitHeapAlloc()...)
insts = append(insts, x.emitStore(0)...) //data
......@@ -72,6 +76,8 @@ func (t *Interface) emitGenFromValue(x Value, xRefType *Ref) (insts []wat.Inst)
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, wat.NewInstConst(wat.I32{}, strconv.Itoa(compID))) //eq
return
}
......@@ -84,6 +90,8 @@ func (t *Interface) emitGenFromInterface(x *aInterface) (insts []wat.Inst) {
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, x.Extract("eq").EmitPush()...) //eq
return
}
......@@ -160,6 +168,7 @@ func (v *aInterface) emitQueryInterface(destType ValueType, commaOk bool) (insts
insts = append(insts, wat.NewInstCall("$wa.runtime.DupI32"))
ifBlock := wat.NewInstIf(nil, nil, nil)
insts = append(insts, ifBlock)
if commaOk {
ifBlock.Ret = append(ifBlock.Ret, wat.I32{})
ifBlock.True = append(ifBlock.True, wat.NewInstConst(wat.I32{}, "1"))
......@@ -168,6 +177,55 @@ func (v *aInterface) emitQueryInterface(destType ValueType, commaOk bool) (insts
ifBlock.False = append(ifBlock.False, wat.NewInstUnreachable())
}
insts = append(insts, ifBlock)
insts = append(insts, v.Extract("eq").EmitPush()...)
return
}
func (v *aInterface) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
d := r.(*aInterface)
ins, _ := v.Extract("eq").emitEq(d.Extract("eq"))
insts = append(insts, ins...)
compEq := wat.NewInstIf(nil, nil, nil)
compEq.Ret = append(compEq.Ret, wat.I32{})
{
compEq.True = append(compEq.True, v.Extract("eq").EmitPush()...)
compEq.True = append(compEq.True, wat.NewInstConst(wat.I32{}, "-1"))
compEq.True = append(compEq.True, wat.NewInstNe(wat.I32{}))
compable := wat.NewInstIf(nil, nil, nil)
compable.Ret = append(compable.Ret, wat.I32{})
{
compable.True = append(compable.True, v.Extract("eq").EmitPush()...)
compable.True = append(compable.True, wat.NewInstEqz(wat.I32{}))
isRef := wat.NewInstIf(nil, nil, nil)
isRef.Ret = append(isRef.Ret, wat.I32{})
ins, _ = v.Extract("data").emitEq(d.Extract("data"))
isRef.True = ins
isRef.False = append(isRef.False, v.Extract("data").(*aRef).Extract("data").EmitPush()...)
isRef.False = append(isRef.False, d.Extract("data").(*aRef).Extract("data").EmitPush()...)
isRef.False = append(isRef.False, v.Extract("eq").EmitPush()...)
isRef.False = append(isRef.False, wat.NewInstCallIndirect("$wa.runtime.comp"))
compable.True = append(compable.True, isRef)
}
compable.False = append(compable.False, wat.NewInstConst(wat.I32{}, "0"))
compable.False = append(compable.False, wat.NewInstUnreachable())
compEq.True = append(compEq.True, compable)
}
compEq.False = append(compEq.False, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, compEq)
ok = true
return
}
......@@ -125,3 +125,11 @@ func (v *aRef) emitSetValue(d Value) []wat.Inst {
}
return d.emitStoreToAddr(v.aStruct.Extract("data"), 0)
}
func (v *aRef) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
return v.Extract("data").emitEq(r.(*aRef).Extract("data"))
}
......@@ -420,3 +420,8 @@ func (v *aSlice) emitSub(low, high Value) (insts []wat.Inst) {
return
}
func (v *aSlice) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aSlice can't be compared.")
return nil, false
}
......@@ -6,6 +6,7 @@ import (
"strconv"
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -360,3 +361,16 @@ func (v *aString) emitAt_CommaOk(index Value) (insts []wat.Inst) {
return
}
func (v *aString) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
insts = append(insts, v.EmitPush()...)
insts = append(insts, r.EmitPush()...)
insts = append(insts, wat.NewInstCall(v.typ.genFunc_Equal()))
ok = true
return
}
......@@ -328,3 +328,29 @@ func (v *aStruct) Bin() (b []byte) {
return
}
func (v *aStruct) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
d := r.(*aStruct)
for i := range v.typ.fields {
t1 := v.genSubValue(v.typ.fields[i])
t2 := d.genSubValue(d.typ.fields[i])
if ins, o := t1.emitEq(t2); !o {
return nil, false
} else {
insts = append(insts, ins...)
}
if i > 0 {
insts = append(insts, wat.NewInstAnd(wat.I32{}))
}
}
ok = true
return
}
......@@ -75,6 +75,7 @@ tCommon:
type tCommon struct {
addr int
hash int
comp int
methods []Method
}
......@@ -84,6 +85,8 @@ func (t *tCommon) AddMethod(m Method) { t.methods = append(t.methods, m) }
func (t *tCommon) NumMethods() int { return len(t.methods) }
func (t *tCommon) Method(i int) Method { return t.methods[i] }
func (t *tCommon) typeInfoAddr() int { return t.addr }
func (t *tCommon) OnComp() int { return t.comp }
func (t *tCommon) setOnComp(c int) { t.comp = c }
//func (t *tCommon) AddMethodEntry(m FnType) { logger.Fatal("Can't add method for common type.") }
//
......@@ -131,10 +134,10 @@ func (t *tRune) onFree() int { return 0 }
func (t *tRune) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} }
func (t *tRune) Equal(u ValueType) bool { _, ok := u.(*tRune); return ok }
func (t *tRune) EmitLoadFromAddr(addr Value, offset int) []wat.Inst {
if !addr.Type().(*Ptr).Base.Equal(t) {
logger.Fatal("Type not match")
return nil
}
//if !addr.Type().(*Ptr).Base.Equal(t) {
// logger.Fatal("Type not match")
// return nil
//}
insts := addr.EmitPush()
insts = append(insts, wat.NewInstLoad(toWatType(t), offset, 1))
return insts
......
......@@ -2,6 +2,28 @@
package wat
/**************************************
instAnd:
**************************************/
type instAnd struct {
anInstruction
typ ValueType
}
func NewInstAnd(t ValueType) *instAnd { return &instAnd{typ: t} }
func (i *instAnd) Format(indent string) string { return indent + i.typ.Name() + ".and" }
/**************************************
instOr:
**************************************/
type instOr struct {
anInstruction
typ ValueType
}
func NewInstOr(t ValueType) *instOr { return &instOr{typ: t} }
func (i *instOr) Format(indent string) string { return indent + i.typ.Name() + ".or" }
/**************************************
instXor:
**************************************/
......
......@@ -45,6 +45,8 @@ type Value interface {
emitStoreToAddr(addr Value, offset int) []wat.Inst
emitStore(offset int) []wat.Inst
Bin() []byte
emitEq(r Value) ([]wat.Inst, bool)
}
/**************************************
......@@ -68,6 +70,9 @@ type ValueType interface {
Method(i int) Method
typeInfoAddr() int
OnComp() int
setOnComp(c int)
}
/**************************************
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册