支持内置 copy 函数

This commit is contained in:
3dgen 2023-06-09 15:51:17 +08:00
parent 8d0808160b
commit 7e5593b33d
5 changed files with 189 additions and 11 deletions

22
_examples/copy.wa Normal file
View File

@ -0,0 +1,22 @@
# 版权 @2021 凹语言 作者。保留所有权利。
var s = []int{1, 2, 3, 4, 5, 6}
func main() {
d := make([]int, 3)
copy(d, s)
for i, v := range d {
println("d[", i, "]=", v)
}
a := s[0:4]
b := s[1:5]
copy(a, b)
for i, v := range s {
println("s[", i, "]=", v)
}
copy(b, a)
for i, v := range s {
println("s[", i, "]=", v)
}
}

View File

@ -671,6 +671,13 @@ func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) (insts []wat.Inst,
insts = g.module.EmitGenCap(g.getValue(call.Args[0]).value)
ret_type = g.module.I32
case "copy":
if len(call.Args) != 2 {
logger.Fatal("len(copy.Args) != 2")
}
insts = g.module.EmitGenCopy(g.getValue(call.Args[0]).value, g.getValue(call.Args[1]).value)
ret_type = g.module.I32
default:
logger.Fatal("Todo:", call.Value)
}

View File

@ -59,7 +59,7 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType {
newType = tLib.module.I32
}
case types.Uint32, types.Uintptr:
case types.Uint32, types.Uintptr, types.Uint:
newType = tLib.module.U32
case types.Int64:

View File

@ -668,16 +668,21 @@ func (m *Module) EmitGenConvert(x Value, typ ValueType) (insts []wat.Inst) {
}
func (m *Module) EmitGenAppend(x, y Value) (insts []wat.Inst, ret_type ValueType) {
if !x.Type().Equal(y.Type()) {
logger.Fatal("Type not match")
return
}
stype := x.Type().(*Slice)
xtype := x.Type().(*Slice)
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstCall(stype.genAppendFunc()))
ret_type = stype
if !x.Type().Equal(y.Type()) {
if _, ok := y.Type().(*String); ok && xtype.Base.Equal(m.U8) {
insts = append(insts, y.(*aString).Extract("len").EmitPush()...)
} else {
logger.Fatal("Type not match")
return
}
}
insts = append(insts, wat.NewInstCall(xtype.genAppendFunc()))
ret_type = xtype
return
}
@ -715,6 +720,24 @@ func (m *Module) EmitGenCap(x Value) (insts []wat.Inst) {
return
}
func (m *Module) EmitGenCopy(x, y Value) (insts []wat.Inst) {
xtype := x.Type().(*Slice)
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
if !x.Type().Equal(y.Type()) {
if _, ok := y.Type().(*String); ok && xtype.Base.Equal(m.U8) {
insts = append(insts, y.(*aString).Extract("len").EmitPush()...)
} else {
logger.Fatal("Type not match")
return
}
}
insts = append(insts, wat.NewInstCall(xtype.genCopyFunc()))
return
}
func (m *Module) EmitGenMakeInterface(x Value, itype ValueType) (insts []wat.Inst) {
x_type := x.Type()
m.markConcreteTypeUsed(x_type)

View File

@ -170,6 +170,10 @@ func (t *Slice) genAppendFunc() string {
f.Params = append(f.Params, y)
f.Results = append(f.Results, t)
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
f.Insts = append(f.Insts, item.EmitInit()...)
x_len := NewLocal("x_len", x.Extract("len").Type())
f.Locals = append(f.Locals, x_len)
f.Insts = append(f.Insts, x.Extract("len").EmitPush()...)
@ -193,8 +197,6 @@ func (t *Slice) genAppendFunc() string {
f.Insts = append(f.Insts, x.Extract("cap").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstLe(wat.U32{}))
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
src := NewLocal("src", t._base_ptr)
f.Locals = append(f.Locals, src)
dest := NewLocal("dest", t._base_ptr)
@ -359,11 +361,135 @@ func (t *Slice) genAppendFunc() string {
f.Insts = append(f.Insts, inst_if)
f.Insts = append(f.Insts, x.EmitRelease()...)
f.Insts = append(f.Insts, y.EmitRelease()...)
f.Insts = append(f.Insts, item.EmitRelease()...)
currentModule.AddFunc(&f)
return fn_name
}
func (t *Slice) genCopyFunc() string {
var f Function
f.InternalName = "$" + GenSymbolName(t.Name()) + ".copy"
if currentModule.FindFunc(f.InternalName) != nil {
return f.InternalName
}
d := newValue_Slice("d", ValueKindLocal, t)
s := newValue_Slice("s", ValueKindLocal, t)
f.Params = append(f.Params, d)
f.Params = append(f.Params, s)
f.Results = append(f.Results, t._u32)
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
f.Insts = append(f.Insts, item.EmitInit()...)
count := NewLocal("count", d.Extract("len").Type())
f.Locals = append(f.Locals, count)
{
f.Insts = append(f.Insts, d.Extract("len").EmitPush()...)
f.Insts = append(f.Insts, s.Extract("len").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstGt(toWatType(count.Type())))
ifs := wat.NewInstIf(nil, nil, nil)
f.Insts = append(f.Insts, ifs)
ifs.True = append(ifs.True, s.Extract("len").EmitPush()...)
ifs.True = append(ifs.True, count.EmitPop()...)
ifs.False = append(ifs.False, d.Extract("len").EmitPush()...)
ifs.False = append(ifs.False, count.EmitPop()...)
}
f.Insts = append(f.Insts, count.EmitPush()...) //ret size
dp := NewLocal("dp", d.Extract("data").Type())
f.Locals = append(f.Locals, dp)
sp := NewLocal("sp", s.Extract("data").Type())
f.Locals = append(f.Locals, sp)
item_size := NewLocal("item_size", d.Extract("len").Type())
f.Locals = append(f.Locals, item_size)
{
f.Insts = append(f.Insts, d.Extract("data").EmitPush()...)
f.Insts = append(f.Insts, s.Extract("data").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstLt(toWatType(d.Extract("data").Type())))
ifs := wat.NewInstIf(nil, nil, nil)
f.Insts = append(f.Insts, ifs)
// dp<sp
ifs.True = append(ifs.True, d.Extract("data").EmitPush()...)
ifs.True = append(ifs.True, dp.EmitPop()...)
ifs.True = append(ifs.True, s.Extract("data").EmitPush()...)
ifs.True = append(ifs.True, sp.EmitPop()...)
ifs.True = append(ifs.True, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.True = append(ifs.True, item_size.EmitPop()...)
// dp>sp
ifs.False = append(ifs.False, count.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "1"))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.False = append(ifs.False, wat.NewInstMul(wat.I32{}))
ifs.False = append(ifs.False, item_size.EmitPop()...)
ifs.False = append(ifs.False, d.Extract("data").EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, dp.EmitPop()...)
ifs.False = append(ifs.False, s.Extract("data").EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, sp.EmitPop()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "0"))
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, item_size.EmitPop()...)
}
b0 := wat.NewInstBlock("b0")
f.Insts = append(f.Insts, b0)
l0 := wat.NewInstLoop("l0")
b0.Insts = append(b0.Insts, l0)
l0.Insts = append(l0.Insts, count.EmitPush()...)
l0.Insts = append(l0.Insts, wat.NewInstEqz(wat.I32{}))
{
ifs := wat.NewInstIf(nil, nil, nil)
l0.Insts = append(l0.Insts, ifs)
ifs.True = append(ifs.True, wat.NewInstBr("b0"))
ifs.False = append(ifs.False, t.Base.EmitLoadFromAddr(sp, 0)...)
ifs.False = append(ifs.False, item.EmitPop()...)
ifs.False = append(ifs.False, item.emitStoreToAddr(dp, 0)...)
ifs.False = append(ifs.False, sp.EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, sp.EmitPop()...)
ifs.False = append(ifs.False, dp.EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, dp.EmitPop()...)
ifs.False = append(ifs.False, count.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "1"))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, count.EmitPop()...)
ifs.False = append(ifs.False, wat.NewInstBr("l0"))
}
f.Insts = append(f.Insts, d.EmitRelease()...)
f.Insts = append(f.Insts, s.EmitRelease()...)
f.Insts = append(f.Insts, item.EmitRelease()...)
currentModule.AddFunc(&f)
return f.InternalName
}
/**************************************
aSlice:
**************************************/