From 7e5593b33dd96234fcdcb97c2b97de73efecc69d Mon Sep 17 00:00:00 2001 From: 3dgen <476582@qq.com> Date: Fri, 9 Jun 2023 15:51:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=86=85=E7=BD=AE=20copy=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _examples/copy.wa | 22 +++ .../backends/compiler_wat/compile_func.go | 7 + .../backends/compiler_wat/compile_type.go | 2 +- .../compiler_wat/wir/instruction_emitter.go | 39 ++++-- .../backends/compiler_wat/wir/value_slice.go | 130 +++++++++++++++++- 5 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 _examples/copy.wa diff --git a/_examples/copy.wa b/_examples/copy.wa new file mode 100644 index 0000000..ae6a5a4 --- /dev/null +++ b/_examples/copy.wa @@ -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) + } +} \ No newline at end of file diff --git a/internal/backends/compiler_wat/compile_func.go b/internal/backends/compiler_wat/compile_func.go index a1d4548..df9794a 100644 --- a/internal/backends/compiler_wat/compile_func.go +++ b/internal/backends/compiler_wat/compile_func.go @@ -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) } diff --git a/internal/backends/compiler_wat/compile_type.go b/internal/backends/compiler_wat/compile_type.go index 7584ece..12bea2a 100644 --- a/internal/backends/compiler_wat/compile_type.go +++ b/internal/backends/compiler_wat/compile_type.go @@ -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: diff --git a/internal/backends/compiler_wat/wir/instruction_emitter.go b/internal/backends/compiler_wat/wir/instruction_emitter.go index 781ce6f..9ec91e5 100644 --- a/internal/backends/compiler_wat/wir/instruction_emitter.go +++ b/internal/backends/compiler_wat/wir/instruction_emitter.go @@ -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) diff --git a/internal/backends/compiler_wat/wir/value_slice.go b/internal/backends/compiler_wat/wir/value_slice.go index 9d922f9..0ed57e5 100644 --- a/internal/backends/compiler_wat/wir/value_slice.go +++ b/internal/backends/compiler_wat/wir/value_slice.go @@ -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) + // dpsp + 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: **************************************/