forked from wa-lang/wa
支持内置 copy 函数
This commit is contained in:
parent
8d0808160b
commit
7e5593b33d
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
**************************************/
|
||||
|
|
|
|||
Loading…
Reference in New Issue