value_slice.go 12.6 KB
Newer Older
3
3dgen 已提交
1 2 3 4 5
// 版权 @2022 凹语言 作者。保留所有权利。

package wir

import (
6 7
	"strconv"

3
3dgen 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
	"github.com/wa-lang/wa/internal/backends/compiler_wat/wir/wat"
)

/**************************************
Slice:
**************************************/
type Slice struct {
	Base ValueType
	Struct
}

func NewSlice(base ValueType) Slice {
	var v Slice
	v.Base = base
	var m []Field
	m = append(m, NewField("block", NewBlock(base)))
	m = append(m, NewField("data", NewPointer(base)))
3
3dgen 已提交
25 26
	m = append(m, NewField("len", U32{}))
	m = append(m, NewField("cap", U32{}))
3
3dgen 已提交
27 28 29 30
	v.Struct = NewStruct(base.Name()+".$$slice", m)
	return v
}
func (t Slice) Name() string         { return t.Base.Name() + ".$$slice" }
3
3dgen 已提交
31 32
func (t Slice) size() int            { return t.Struct.size() }
func (t Slice) align() int           { return t.Struct.align() }
33
func (t Slice) onFree() int          { return t.Struct.onFree() }
3
3dgen 已提交
34 35 36 37 38 39 40 41
func (t Slice) Raw() []wat.ValueType { return t.Struct.Raw() }
func (t Slice) Equal(u ValueType) bool {
	if ut, ok := u.(Slice); ok {
		return t.Base.Equal(ut.Base)
	}
	return false
}

3
3dgen 已提交
42 43
func (t Slice) EmitLoadFromAddr(addr Value, offset int) []wat.Inst {
	return t.Struct.EmitLoadFromAddr(addr, offset)
3
3dgen 已提交
44 45
}

46 47 48
/*这个函数极其不优雅*/
func (t Slice) emitGenFromRefOfSlice(x *aRef, low, high Value) (insts []wat.Inst) {
	//block
3
3dgen 已提交
49
	insts = append(insts, x.Extract("data").EmitPush()...)
3
3dgen 已提交
50
	insts = append(insts, wat.NewInstLoad(wat.U32{}, 0, 1))
51 52 53 54
	insts = append(insts, wat.NewInstCall("$wa.RT.Block.Retain"))

	//data
	if low == nil {
3
3dgen 已提交
55
		low = NewConst("0", U32{})
56
	}
3
3dgen 已提交
57
	insts = append(insts, x.Extract("data").EmitPush()...)
3
3dgen 已提交
58 59
	insts = append(insts, wat.NewInstLoad(wat.U32{}, 4, 1))
	insts = append(insts, NewConst(strconv.Itoa(x.Type().(Ref).Base.(Array).Base.size()), U32{}).EmitPush()...)
60
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
61 62
	insts = append(insts, wat.NewInstMul(wat.U32{}))
	insts = append(insts, wat.NewInstAdd(wat.U32{}))
63 64 65

	//len:
	if high == nil {
3
3dgen 已提交
66
		insts = append(insts, x.Extract("data").EmitPush()...)
3
3dgen 已提交
67
		insts = append(insts, wat.NewInstLoad(wat.U32{}, 12, 1))
68 69 70 71
	} else {
		insts = append(insts, high.EmitPush()...)
	}
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
72
	insts = append(insts, wat.NewInstSub(wat.U32{}))
73 74

	//cap:
3
3dgen 已提交
75
	insts = append(insts, x.Extract("data").EmitPush()...)
3
3dgen 已提交
76
	insts = append(insts, wat.NewInstLoad(wat.U32{}, 12, 1))
77
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
78
	insts = append(insts, wat.NewInstSub(wat.U32{}))
79 80 81 82 83 84

	return
}

func (t Slice) emitGenFromRefOfArray(x *aRef, low, high Value) (insts []wat.Inst) {
	//block
3
3dgen 已提交
85
	insts = append(insts, x.Extract("block").EmitPush()...)
86 87 88

	//data
	if low == nil {
3
3dgen 已提交
89
		low = NewConst("0", U32{})
90
	}
3
3dgen 已提交
91
	insts = append(insts, x.Extract("data").EmitPush()...)
3
3dgen 已提交
92
	insts = append(insts, NewConst(strconv.Itoa(x.Type().(Ref).Base.(Array).Base.size()), U32{}).EmitPush()...)
93
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
94 95
	insts = append(insts, wat.NewInstMul(wat.U32{}))
	insts = append(insts, wat.NewInstAdd(wat.U32{}))
96

3
3dgen 已提交
97
	array_len := NewConst(strconv.Itoa(x.Type().(Ref).Base.(Array).Capacity), U32{})
98 99 100 101 102 103 104

	//len:
	if high == nil {
		high = array_len
	}
	insts = append(insts, high.EmitPush()...)
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
105
	insts = append(insts, wat.NewInstSub(wat.U32{}))
106 107 108 109

	//cap:
	insts = append(insts, array_len.EmitPush()...)
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
110
	insts = append(insts, wat.NewInstSub(wat.U32{}))
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

	return
}

func (t Slice) genAppendFunc() string {
	fn_name := "$" + t.Name() + ".append"
	if currentModule.findFunc(fn_name) != nil {
		return fn_name
	}

	var f Function
	f.Name = fn_name
	x := newValueSlice("x", ValueKindLocal, t.Base)
	y := newValueSlice("y", ValueKindLocal, t.Base)
	f.Params = append(f.Params, x)
	f.Params = append(f.Params, y)
3
3dgen 已提交
127
	f.Results = append(f.Results, t)
128

3
3dgen 已提交
129
	x_len := NewLocal("x_len", x.Extract("len").Type())
130
	f.Locals = append(f.Locals, x_len)
3
3dgen 已提交
131
	f.Insts = append(f.Insts, x.Extract("len").EmitPush()...)
132 133
	f.Insts = append(f.Insts, x_len.EmitPop()...)

3
3dgen 已提交
134
	y_len := NewLocal("y_len", y.Extract("len").Type())
135
	f.Locals = append(f.Locals, y_len)
3
3dgen 已提交
136
	f.Insts = append(f.Insts, y.Extract("len").EmitPush()...)
137 138 139 140 141 142 143
	f.Insts = append(f.Insts, y_len.EmitPop()...)

	//gen new_len:
	new_len := NewLocal("new_len", x_len.Type())
	f.Locals = append(f.Locals, new_len)
	f.Insts = append(f.Insts, x_len.EmitPush()...)
	f.Insts = append(f.Insts, y_len.EmitPush()...)
3
3dgen 已提交
144
	f.Insts = append(f.Insts, wat.NewInstAdd(wat.U32{}))
145 146 147 148
	f.Insts = append(f.Insts, new_len.EmitPop()...)

	//if_new_len_le_cap
	f.Insts = append(f.Insts, new_len.EmitPush()...)
3
3dgen 已提交
149
	f.Insts = append(f.Insts, x.Extract("cap").EmitPush()...)
3
3dgen 已提交
150
	f.Insts = append(f.Insts, wat.NewInstLe(wat.U32{}))
151 152 153 154 155 156 157

	item := NewLocal("item", t.Base)
	f.Locals = append(f.Locals, item)
	src := NewLocal("src", NewPointer(t.Base))
	f.Locals = append(f.Locals, src)
	dest := NewLocal("dest", NewPointer(t.Base))
	f.Locals = append(f.Locals, dest)
3
3dgen 已提交
158
	item_size := NewConst(strconv.Itoa(t.Base.size()), U32{})
159 160 161 162 163

	inst_if := wat.NewInstIf(nil, nil, t.Raw())
	{ //if_true
		var if_true []wat.Inst

3
3dgen 已提交
164 165
		if_true = append(if_true, x.Extract("block").EmitPush()...)
		if_true = append(if_true, x.Extract("data").EmitPush()...)
166
		if_true = append(if_true, new_len.EmitPush()...)
3
3dgen 已提交
167
		if_true = append(if_true, x.Extract("cap").EmitPush()...)
168 169

		//get src
3
3dgen 已提交
170
		if_true = append(if_true, y.Extract("data").EmitPush()...)
171 172 173
		if_true = append(if_true, src.EmitPop()...)

		//get dest
3
3dgen 已提交
174
		if_true = append(if_true, x.Extract("data").EmitPush()...)
175 176
		if_true = append(if_true, item_size.EmitPush()...)
		if_true = append(if_true, x_len.EmitPush()...)
3
3dgen 已提交
177 178
		if_true = append(if_true, wat.NewInstMul(wat.U32{}))
		if_true = append(if_true, wat.NewInstAdd(wat.U32{}))
179 180 181 182 183 184
		if_true = append(if_true, dest.EmitPop()...)

		block := wat.NewInstBlock("block1")
		loop := wat.NewInstLoop("loop1")
		{
			loop.Insts = append(loop.Insts, y_len.EmitPush()...)
3
3dgen 已提交
185
			loop.Insts = append(loop.Insts, wat.NewInstEqz(wat.U32{}))
186 187 188
			loop.Insts = append(loop.Insts, wat.NewInstIf([]wat.Inst{wat.NewInstBr("block1")}, nil, nil))

			//*dest = *src
3
3dgen 已提交
189
			loop.Insts = append(loop.Insts, t.Base.EmitLoadFromAddr(src, 0)...)
190 191 192 193 194
			loop.Insts = append(loop.Insts, item.EmitPop()...)
			loop.Insts = append(loop.Insts, item.emitStoreToAddr(dest, 0)...)

			loop.Insts = append(loop.Insts, src.EmitPush()...)
			loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
195
			loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
196 197 198 199
			loop.Insts = append(loop.Insts, src.EmitPop()...)

			loop.Insts = append(loop.Insts, dest.EmitPush()...)
			loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
200
			loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
201 202 203
			loop.Insts = append(loop.Insts, dest.EmitPop()...)

			loop.Insts = append(loop.Insts, y_len.EmitPush()...)
3
3dgen 已提交
204 205
			loop.Insts = append(loop.Insts, NewConst("1", U32{}).EmitPush()...)
			loop.Insts = append(loop.Insts, wat.NewInstSub(wat.U32{}))
206 207 208 209 210 211 212 213 214 215 216 217 218
			loop.Insts = append(loop.Insts, y_len.EmitPop()...)

			loop.Insts = append(loop.Insts, wat.NewInstBr("loop1"))
		}
		block.Insts = append(block.Insts, loop)
		if_true = append(if_true, block)

		inst_if.True = if_true
	}

	{ //if_false
		var if_false []wat.Inst

3
3dgen 已提交
219
		new_cap := NewLocal("new_cap", U32{})
220 221 222
		f.Locals = append(f.Locals, new_cap)
		//gen new slice
		if_false = append(if_false, new_len.EmitPush()...)
3
3dgen 已提交
223 224
		if_false = append(if_false, NewConst("2", U32{}).EmitPush()...)
		if_false = append(if_false, wat.NewInstMul(wat.U32{}))
225 226 227 228
		if_false = append(if_false, new_cap.EmitPop()...)
		if_false = append(if_false, NewBlock(t.Base).emitHeapAlloc(new_cap)...) //block

		if_false = append(if_false, wat.NewInstCall("$wa.RT.DupWatStack"))
3
3dgen 已提交
229 230
		if_false = append(if_false, NewConst("16", U32{}).EmitPush()...)
		if_false = append(if_false, wat.NewInstAdd(wat.U32{})) //data
231 232 233 234 235 236 237
		if_false = append(if_false, wat.NewInstCall("$wa.RT.DupWatStack"))
		if_false = append(if_false, dest.EmitPop()...)     //dest
		if_false = append(if_false, new_len.EmitPush()...) //len
		if_false = append(if_false, new_cap.EmitPush()...) //cap

		//x->new
		{
3
3dgen 已提交
238
			if_false = append(if_false, x.Extract("data").EmitPush()...)
239 240 241 242 243 244
			if_false = append(if_false, src.EmitPop()...)

			block := wat.NewInstBlock("block2")
			loop := wat.NewInstLoop("loop2")
			{
				loop.Insts = append(loop.Insts, x_len.EmitPush()...)
3
3dgen 已提交
245
				loop.Insts = append(loop.Insts, wat.NewInstEqz(wat.U32{}))
246 247 248
				loop.Insts = append(loop.Insts, wat.NewInstIf([]wat.Inst{wat.NewInstBr("block2")}, nil, nil))

				//*dest = *src
3
3dgen 已提交
249
				loop.Insts = append(loop.Insts, t.Base.EmitLoadFromAddr(src, 0)...)
250 251 252 253 254
				loop.Insts = append(loop.Insts, item.EmitPop()...)
				loop.Insts = append(loop.Insts, item.emitStoreToAddr(dest, 0)...)

				loop.Insts = append(loop.Insts, src.EmitPush()...)
				loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
255
				loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
256 257 258 259
				loop.Insts = append(loop.Insts, src.EmitPop()...)

				loop.Insts = append(loop.Insts, dest.EmitPush()...)
				loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
260
				loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
261 262 263
				loop.Insts = append(loop.Insts, dest.EmitPop()...)

				loop.Insts = append(loop.Insts, x_len.EmitPush()...)
3
3dgen 已提交
264 265
				loop.Insts = append(loop.Insts, NewConst("1", U32{}).EmitPush()...)
				loop.Insts = append(loop.Insts, wat.NewInstSub(wat.U32{}))
266 267 268 269 270 271 272 273 274 275
				loop.Insts = append(loop.Insts, x_len.EmitPop()...)

				loop.Insts = append(loop.Insts, wat.NewInstBr("loop2"))
			}
			block.Insts = append(block.Insts, loop)
			if_false = append(if_false, block)
		}

		//y->new
		{
3
3dgen 已提交
276
			if_false = append(if_false, y.Extract("data").EmitPush()...)
277 278 279 280 281 282
			if_false = append(if_false, src.EmitPop()...)

			block := wat.NewInstBlock("block3")
			loop := wat.NewInstLoop("loop3")
			{
				loop.Insts = append(loop.Insts, y_len.EmitPush()...)
3
3dgen 已提交
283
				loop.Insts = append(loop.Insts, wat.NewInstEqz(wat.U32{}))
284 285 286
				loop.Insts = append(loop.Insts, wat.NewInstIf([]wat.Inst{wat.NewInstBr("block3")}, nil, nil))

				//*dest = *src
3
3dgen 已提交
287
				loop.Insts = append(loop.Insts, t.Base.EmitLoadFromAddr(src, 0)...)
288 289 290 291 292
				loop.Insts = append(loop.Insts, item.EmitPop()...)
				loop.Insts = append(loop.Insts, item.emitStoreToAddr(dest, 0)...)

				loop.Insts = append(loop.Insts, src.EmitPush()...)
				loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
293
				loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
294 295 296 297
				loop.Insts = append(loop.Insts, src.EmitPop()...)

				loop.Insts = append(loop.Insts, dest.EmitPush()...)
				loop.Insts = append(loop.Insts, item_size.EmitPush()...)
3
3dgen 已提交
298
				loop.Insts = append(loop.Insts, wat.NewInstAdd(wat.U32{}))
299 300 301
				loop.Insts = append(loop.Insts, dest.EmitPop()...)

				loop.Insts = append(loop.Insts, y_len.EmitPush()...)
3
3dgen 已提交
302 303
				loop.Insts = append(loop.Insts, NewConst("1", U32{}).EmitPush()...)
				loop.Insts = append(loop.Insts, wat.NewInstSub(wat.U32{}))
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
				loop.Insts = append(loop.Insts, y_len.EmitPop()...)

				loop.Insts = append(loop.Insts, wat.NewInstBr("loop3"))
			}
			block.Insts = append(block.Insts, loop)
			if_false = append(if_false, block)
		}

		inst_if.False = if_false
	}

	f.Insts = append(f.Insts, inst_if)
	f.Insts = append(f.Insts, x.EmitRelease()...)
	f.Insts = append(f.Insts, y.EmitRelease()...)

	currentModule.AddFunc(&f)
	return fn_name
}

3
3dgen 已提交
323 324 325 326
/**************************************
aSlice:
**************************************/
type aSlice struct {
3
3dgen 已提交
327 328
	aStruct
	typ Slice
3
3dgen 已提交
329 330 331 332
}

func newValueSlice(name string, kind ValueKind, base_type ValueType) *aSlice {
	var v aSlice
3
3dgen 已提交
333 334
	v.typ = NewSlice(base_type)
	v.aStruct = *newValueStruct(name, kind, v.typ.Struct)
3
3dgen 已提交
335 336 337
	return &v
}

3
3dgen 已提交
338 339
func (v *aSlice) Type() ValueType { return v.typ }

3
3dgen 已提交
340 341 342 343 344
func (v *aSlice) raw() []wat.Value        { return v.aStruct.raw() }
func (v *aSlice) EmitInit() []wat.Inst    { return v.aStruct.EmitInit() }
func (v *aSlice) EmitPush() []wat.Inst    { return v.aStruct.EmitPush() }
func (v *aSlice) EmitPop() []wat.Inst     { return v.aStruct.EmitPop() }
func (v *aSlice) EmitRelease() []wat.Inst { return v.aStruct.EmitRelease() }
3
3dgen 已提交
345 346

func (v *aSlice) emitStoreToAddr(addr Value, offset int) []wat.Inst {
3
3dgen 已提交
347
	return v.aStruct.emitStoreToAddr(addr, offset)
3
3dgen 已提交
348
}
349 350 351

func (v *aSlice) emitSub(low, high Value) (insts []wat.Inst) {
	//block
3
3dgen 已提交
352
	insts = append(insts, v.Extract("block").EmitPush()...)
353 354 355

	//data:
	if low == nil {
3
3dgen 已提交
356
		low = NewConst("0", U32{})
357
	}
3
3dgen 已提交
358
	insts = append(insts, v.Extract("data").EmitPush()...)
3
3dgen 已提交
359
	insts = append(insts, NewConst(strconv.Itoa(v.Type().(Slice).Base.size()), U32{}).EmitPush()...)
360
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
361 362
	insts = append(insts, wat.NewInstMul(wat.U32{}))
	insts = append(insts, wat.NewInstAdd(wat.U32{}))
363 364 365

	//len:
	if high == nil {
3
3dgen 已提交
366
		high = v.Extract("len")
367 368 369
	}
	insts = append(insts, high.EmitPush()...)
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
370
	insts = append(insts, wat.NewInstSub(wat.U32{}))
371 372

	//cap:
3
3dgen 已提交
373
	insts = append(insts, v.Extract("cap").EmitPush()...)
374
	insts = append(insts, low.EmitPush()...)
3
3dgen 已提交
375
	insts = append(insts, wat.NewInstSub(wat.U32{}))
376 377 378

	return
}