compile_func.go 10.8 KB
Newer Older
3
3dgen 已提交
1 2
// 版权 @2021 凹语言 作者。保留所有权利。

chai2010's avatar
chai2010 已提交
3
package compiler_wat
3
3dgen 已提交
4 5 6 7 8 9 10 11

import (
	"strconv"

	"github.com/wa-lang/wa/internal/constant"
	"github.com/wa-lang/wa/internal/token"
	"github.com/wa-lang/wa/internal/types"

chai2010's avatar
chai2010 已提交
12
	"github.com/wa-lang/wa/internal/backends/compiler_wat/wir"
3
3dgen 已提交
13
	"github.com/wa-lang/wa/internal/backends/compiler_wat/wir/wat"
3
3dgen 已提交
14 15 16 17 18
	"github.com/wa-lang/wa/internal/logger"
	"github.com/wa-lang/wa/internal/ssa"
)

type functionGenerator struct {
3
3dgen 已提交
19
	module *wat.Module
3
3dgen 已提交
20 21 22 23 24 25 26 27 28 29 30 31

	locals_map map[ssa.Value]wir.Value

	registers    []wir.Value
	cur_local_id int

	var_block_selector wir.Value
	var_current_block  wir.Value
	var_ret            wir.Value
}

func newFunctionGenerator(p *Compiler) *functionGenerator {
3
3dgen 已提交
32
	return &functionGenerator{module: &p.module, locals_map: make(map[ssa.Value]wir.Value)}
3
3dgen 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
}

func (g *functionGenerator) getValue(i ssa.Value) wir.Value {
	if i == nil {
		return nil
	}

	if v, ok := g.locals_map[i]; ok {
		return v
	}

	switch v := i.(type) {
	case *ssa.Const:
		switch t := v.Type().(type) {
		case *types.Basic:
			switch t.Kind() {
3
3dgen 已提交
49

3
3dgen 已提交
50 51 52 53 54
			case types.Bool:
				logger.Fatalf("Todo:%T", t)

			case types.Int:
				val, _ := constant.Int64Val(v.Value)
3
3dgen 已提交
55
				return wir.NewConst(wir.I32{}, strconv.Itoa(int(val)))
3
3dgen 已提交
56

chai2010's avatar
chai2010 已提交
57 58
			case types.Int32:
				val, _ := constant.Int64Val(v.Value)
3
3dgen 已提交
59 60 61 62 63
				if t.Name() == "rune" {
					return wir.NewConst(wir.RUNE{}, strconv.Itoa(int(val)))
				} else {
					return wir.NewConst(wir.I32{}, strconv.Itoa(int(val)))
				}
chai2010's avatar
chai2010 已提交
64

3
3dgen 已提交
65
			case types.Float32:
3
3dgen 已提交
66 67
				val, _ := constant.Float64Val(v.Value)
				return wir.NewConst(wir.F32{}, strconv.FormatFloat(val, 'f', -1, 32))
3
3dgen 已提交
68 69

			case types.Float64:
3
3dgen 已提交
70 71
				val, _ := constant.Float64Val(v.Value)
				return wir.NewConst(wir.F64{}, strconv.FormatFloat(val, 'f', -1, 64))
3
3dgen 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

			case types.String, types.UntypedString:
				logger.Fatalf("Todo:%T", t)

			default:
				logger.Fatalf("Todo:%T", t)
			}

		case *types.Slice:
			logger.Fatalf("Todo:%T", t)

		default:
			logger.Fatalf("Todo:%T", t)
		}

	case ssa.Instruction:
		nv := g.addRegister(wir.ToWType(i.Type()))
		g.locals_map[i] = nv
		return nv
	}

	logger.Fatal("Value not found:", i)
	return nil
}

3
3dgen 已提交
97
func (g *functionGenerator) genFunction(f *ssa.Function) *wat.Function {
3
3dgen 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	var wir_fn wir.Function
	wir_fn.Name = f.Name()

	rets := f.Signature.Results()
	wir_fn.Result = wir.ToWType(rets)
	if rets.Len() > 1 {
		logger.Fatal("Todo")
	}

	for _, i := range f.Params {
		pa := wir.NewVar(i.Name(), wir.ValueKindLocal, wir.ToWType(i.Type()))
		wir_fn.Params = append(wir_fn.Params, pa)
		g.locals_map[i] = pa
	}

3
3dgen 已提交
113
	g.var_block_selector = wir.NewVar("$block_selector", wir.ValueKindLocal, wir.I32{})
3
3dgen 已提交
114
	g.registers = append(g.registers, g.var_block_selector)
3
3dgen 已提交
115
	wir_fn.Insts = append(wir_fn.Insts, g.var_block_selector.EmitInit()...)
3
3dgen 已提交
116

3
3dgen 已提交
117
	g.var_current_block = wir.NewVar("$current_block", wir.ValueKindLocal, wir.I32{})
3
3dgen 已提交
118
	g.registers = append(g.registers, g.var_current_block)
3
3dgen 已提交
119
	wir_fn.Insts = append(wir_fn.Insts, g.var_current_block.EmitInit()...)
3
3dgen 已提交
120

3
3dgen 已提交
121
	if !wir_fn.Result.Equal(wir.Void{}) {
3
3dgen 已提交
122
		g.var_ret = wir.NewVar("$ret", wir.ValueKindLocal, wir_fn.Result)
3
3dgen 已提交
123
		g.registers = append(g.registers, g.var_ret)
3
3dgen 已提交
124
		wir_fn.Insts = append(wir_fn.Insts, g.var_ret.EmitInit()...)
3
3dgen 已提交
125 126
	}

3
3dgen 已提交
127
	var block_temp wat.Inst
3
3dgen 已提交
128 129
	//BlockSel:
	{
3
3dgen 已提交
130 131
		inst := wat.NewInstBlock("$BlockSel")
		inst.Insts = append(inst.Insts, g.var_block_selector.EmitGet()...)
3
3dgen 已提交
132 133 134 135 136
		t := make([]int, len(f.Blocks)+1)
		for i := range f.Blocks {
			t[i] = i
		}
		t[len(f.Blocks)] = 0
3
3dgen 已提交
137
		inst.Insts = append(inst.Insts, wat.NewInstBrTable(t))
3
3dgen 已提交
138 139 140 141
		block_temp = inst
	}

	for i, b := range f.Blocks {
3
3dgen 已提交
142
		block := wat.NewInstBlock("$Block_" + strconv.Itoa(i))
3
3dgen 已提交
143 144 145 146 147 148 149
		block.Insts = append(block.Insts, block_temp)
		block.Insts = append(block.Insts, g.genBlock(b)...)
		block_temp = block
	}

	//BlockDisp
	{
3
3dgen 已提交
150
		inst := wat.NewInstLoop("$BlockDisp")
3
3dgen 已提交
151 152 153 154 155 156
		inst.Insts = append(inst.Insts, block_temp)
		block_temp = inst
	}

	//BlockFnBody
	{
3
3dgen 已提交
157
		inst := wat.NewInstBlock("$BlockFnBody")
3
3dgen 已提交
158 159 160 161 162
		inst.Insts = append(inst.Insts, block_temp)
		block_temp = inst
	}

	wir_fn.Insts = append(wir_fn.Insts, block_temp)
3
3dgen 已提交
163

3
3dgen 已提交
164 165
	if !wir_fn.Result.Equal(wir.Void{}) {
		wir_fn.Insts = append(wir_fn.Insts, g.var_ret.EmitGet()...)
3
3dgen 已提交
166 167
	}

3
3dgen 已提交
168 169
	wir_fn.Locals = g.registers

3
3dgen 已提交
170
	return wir_fn.ToWatFunc()
3
3dgen 已提交
171 172
}

3
3dgen 已提交
173
func (g *functionGenerator) genBlock(block *ssa.BasicBlock) []wat.Inst {
3
3dgen 已提交
174 175 176 177 178
	if len(block.Instrs) == 0 {
		logger.Fatalf("Block:%s is empty", block)
	}

	cur_block_assigned := false
3
3dgen 已提交
179
	var b []wat.Inst
3
3dgen 已提交
180 181 182
	for _, inst := range block.Instrs {
		if _, ok := inst.(*ssa.Phi); !ok {
			if !cur_block_assigned {
3
3dgen 已提交
183
				b = append(b, wir.EmitAssginValue(g.var_current_block, wir.NewConst(wir.I32{}, strconv.Itoa(block.Index)))...)
3
3dgen 已提交
184 185 186 187 188 189 190 191 192 193
				cur_block_assigned = true
			}
		}

		b = append(b, g.genInstruction(inst)...)
	}
	return b

}

3
3dgen 已提交
194
func (g *functionGenerator) genInstruction(inst ssa.Instruction) []wat.Inst {
3
3dgen 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
	switch inst := inst.(type) {

	case *ssa.Alloc:
		logger.Fatalf("Todo:%T", inst)

	case *ssa.If:
		return g.genIf(inst)

	case *ssa.Store:
		logger.Fatalf("Todo:%T", inst)

	case *ssa.Jump:
		return g.genJump(inst)

	case *ssa.Return:
		return g.genReturn(inst)

	case *ssa.Extract:
		logger.Fatalf("Todo:%T", inst)

	case *ssa.Field:
		logger.Fatalf("Todo:%T", inst)

	case ssa.Value:
		s, t := g.genValue(inst)
3
3dgen 已提交
220
		if !t.Equal(wir.Void{}) {
3
3dgen 已提交
221
			v := g.getValue(inst)
3
3dgen 已提交
222
			s = append(s, v.EmitSet()...)
3
3dgen 已提交
223 224 225 226 227 228 229 230 231 232
			g.locals_map[inst] = v
		}
		return s

	default:
		logger.Fatal("Todo:", inst.String())
	}
	return nil
}

3
3dgen 已提交
233 234 235 236
func (g *functionGenerator) genValue(v ssa.Value) ([]wat.Inst, wir.ValueType) {
	//if _, ok := g.locals_map[v]; ok {
	//	logger.Printf("Instruction already exist:%s\n", v)
	//}
3
3dgen 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

	switch v := v.(type) {
	case *ssa.UnOp:
		logger.Fatalf("Todo: %v, type: %T", v, v)

	case *ssa.BinOp:
		return g.genBinOp(v)

	case *ssa.Call:
		return g.genCall(v)

	case *ssa.Phi:
		return g.genPhi(v)

	case *ssa.FieldAddr:
		logger.Fatalf("Todo: %v, type: %T", v, v)

	case *ssa.IndexAddr:
		logger.Fatalf("Todo: %v, type: %T", v, v)

	case *ssa.Slice:
		logger.Fatalf("Todo: %v, type: %T", v, v)
	}

	logger.Fatalf("Todo: %v, type: %T", v, v)
	return nil, nil
}

3
3dgen 已提交
265
func (g *functionGenerator) genBinOp(inst *ssa.BinOp) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
266 267 268 269 270 271 272
	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:
3
3dgen 已提交
273
			return wir.EmitBinOp(x, y, wat.OpCodeAdd)
3
3dgen 已提交
274 275

		case token.SUB:
3
3dgen 已提交
276
			return wir.EmitBinOp(x, y, wat.OpCodeSub)
3
3dgen 已提交
277 278

		case token.MUL:
3
3dgen 已提交
279
			return wir.EmitBinOp(x, y, wat.OpCodeMul)
3
3dgen 已提交
280 281

		case token.QUO:
3
3dgen 已提交
282
			return wir.EmitBinOp(x, y, wat.OpCodeQuo)
3
3dgen 已提交
283 284

		case token.REM:
3
3dgen 已提交
285
			return wir.EmitBinOp(x, y, wat.OpCodeRem)
3
3dgen 已提交
286 287

		case token.EQL:
3
3dgen 已提交
288
			return wir.EmitBinOp(x, y, wat.OpCodeEql)
3
3dgen 已提交
289 290

		case token.NEQ:
3
3dgen 已提交
291
			return wir.EmitBinOp(x, y, wat.OpCodeNe)
3
3dgen 已提交
292 293

		case token.LSS:
3
3dgen 已提交
294
			return wir.EmitBinOp(x, y, wat.OpCodeLt)
3
3dgen 已提交
295 296

		case token.GTR:
3
3dgen 已提交
297
			return wir.EmitBinOp(x, y, wat.OpCodeGt)
3
3dgen 已提交
298 299

		case token.LEQ:
3
3dgen 已提交
300
			return wir.EmitBinOp(x, y, wat.OpCodeLe)
3
3dgen 已提交
301 302

		case token.GEQ:
3
3dgen 已提交
303
			return wir.EmitBinOp(x, y, wat.OpCodeGe)
3
3dgen 已提交
304 305 306 307 308 309 310 311 312 313
		}

	default:
		logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
	}

	logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
	return nil, nil
}

3
3dgen 已提交
314
func (g *functionGenerator) genCall(inst *ssa.Call) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
315 316 317 318 319 320 321
	if inst.Call.IsInvoke() {
		logger.Fatal("Todo: genCall(), Invoke")
	}

	switch inst.Call.Value.(type) {
	case *ssa.Function:
		ret_type := wir.ToWType(inst.Call.Signature().Results())
3
3dgen 已提交
322
		var insts []wat.Inst
3
3dgen 已提交
323
		for _, v := range inst.Call.Args {
3
3dgen 已提交
324
			insts = append(insts, g.getValue(v).EmitGet()...)
3
3dgen 已提交
325
		}
3
3dgen 已提交
326
		insts = append(insts, wat.NewInstCall(inst.Call.StaticCallee().Name()))
3
3dgen 已提交
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
		return insts, ret_type

	case *ssa.Builtin:
		return g.genBuiltin(inst.Common())

	case *ssa.MakeClosure:
		logger.Fatal("Todo: genCall(), MakeClosure")

	default:
		logger.Fatalf("Todo: type:%T", inst.Call.Value)
	}

	logger.Fatal("Todo")

	return nil, nil
}

3
3dgen 已提交
344
func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
345 346
	switch call.Value.Name() {
	case "print", "println":
3
3dgen 已提交
347
		var insts []wat.Inst
3
3dgen 已提交
348 349 350
		for _, arg := range call.Args {
			arg := g.getValue(arg)
			switch arg.Type().(type) {
3
3dgen 已提交
351
			case wir.I32:
3
3dgen 已提交
352
				insts = append(insts, arg.EmitGet()...)
3
3dgen 已提交
353
				insts = append(insts, wat.NewInstCall("$PrintI32"))
3
3dgen 已提交
354

3
3dgen 已提交
355 356
			case wir.RUNE:
				insts = append(insts, arg.EmitGet()...)
3
3dgen 已提交
357
				insts = append(insts, wat.NewInstCall("$PrintRune"))
3
3dgen 已提交
358

3
3dgen 已提交
359
			default:
3
3dgen 已提交
360
				logger.Fatalf("Todo: print(%T)", arg.Type())
3
3dgen 已提交
361 362 363 364
			}
		}

		if call.Value.Name() == "println" {
3
3dgen 已提交
365
			insts = append(insts, wir.NewConst(wir.I32{}, strconv.Itoa('\n')).EmitGet()...)
3
3dgen 已提交
366
			insts = append(insts, wat.NewInstCall("$PrintRune"))
3
3dgen 已提交
367 368
		}

3
3dgen 已提交
369
		return insts, wir.Void{}
3
3dgen 已提交
370 371 372 373 374
	}
	logger.Fatal("Todo:", call.Value)
	return nil, nil
}

3
3dgen 已提交
375 376
func (g *functionGenerator) genPhiIter(preds []int, values []wir.Value) []wat.Inst {
	var insts []wat.Inst
3
3dgen 已提交
377

3
3dgen 已提交
378
	cond, _ := wir.EmitBinOp(g.var_current_block, wir.NewConst(wir.I32{}, strconv.Itoa(preds[0])), wat.OpCodeEql)
3
3dgen 已提交
379 380
	insts = append(insts, cond...)

3
3dgen 已提交
381 382
	trueInsts := values[0].EmitGet()
	var falseInsts []wat.Inst
3
3dgen 已提交
383
	if len(preds) == 2 {
3
3dgen 已提交
384
		falseInsts = values[1].EmitGet()
3
3dgen 已提交
385
	} else {
3
3dgen 已提交
386
		falseInsts = g.genPhiIter(preds[1:], values[1:])
3
3dgen 已提交
387
	}
3
3dgen 已提交
388
	insts = append(insts, wat.NewInstIf(trueInsts, falseInsts, values[0].Type().Raw()))
3
3dgen 已提交
389 390 391

	return insts
}
3
3dgen 已提交
392
func (g *functionGenerator) genPhi(inst *ssa.Phi) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
393 394 395 396 397 398 399 400 401
	var preds []int
	var values []wir.Value
	for i, v := range inst.Edges {
		preds = append(preds, inst.Block().Preds[i].Index)
		values = append(values, g.getValue(v))
	}
	return g.genPhiIter(preds, values), wir.ToWType(inst.Type())
}

3
3dgen 已提交
402 403
func (g *functionGenerator) genReturn(inst *ssa.Return) []wat.Inst {
	var insts []wat.Inst
3
3dgen 已提交
404 405 406 407 408 409 410 411 412 413 414 415

	switch len(inst.Results) {
	case 0:
		break

	case 1:
		insts = append(insts, wir.EmitAssginValue(g.var_ret, g.getValue(inst.Results[0]))...)

	default:
		logger.Fatal("Todo")
	}

3
3dgen 已提交
416
	insts = append(insts, wat.NewInstBr("$BlockFnBody"))
3
3dgen 已提交
417 418 419
	return insts
}

3
3dgen 已提交
420
func (g *functionGenerator) genIf(inst *ssa.If) []wat.Inst {
3
3dgen 已提交
421
	cond := g.getValue(inst.Cond)
3
3dgen 已提交
422
	if !cond.Type().Equal(wir.I32{}) {
3
3dgen 已提交
423 424 425
		logger.Fatal("cond.type() != i32")
	}

3
3dgen 已提交
426
	insts := cond.EmitGet()
3
3dgen 已提交
427 428
	instsTrue := g.genJumpID(inst.Block().Index, inst.Block().Succs[0].Index)
	instsFalse := g.genJumpID(inst.Block().Index, inst.Block().Succs[1].Index)
3
3dgen 已提交
429
	insts = append(insts, wat.NewInstIf(instsTrue, instsFalse, nil))
3
3dgen 已提交
430 431 432 433

	return insts
}

3
3dgen 已提交
434
func (g *functionGenerator) genJump(inst *ssa.Jump) []wat.Inst {
3
3dgen 已提交
435 436 437
	return g.genJumpID(inst.Block().Index, inst.Block().Succs[0].Index)
}

3
3dgen 已提交
438 439
func (g *functionGenerator) genJumpID(cur, dest int) []wat.Inst {
	var insts []wat.Inst
3
3dgen 已提交
440 441

	if cur >= dest {
3
3dgen 已提交
442
		insts = wir.EmitAssginValue(g.var_block_selector, wir.NewConst(wir.I32{}, strconv.Itoa(dest)))
3
3dgen 已提交
443
		insts = append(insts, wat.NewInstBr("$BlockDisp"))
3
3dgen 已提交
444
	} else {
3
3dgen 已提交
445
		insts = append(insts, wat.NewInstBr("$Block_"+strconv.Itoa(dest-1)))
3
3dgen 已提交
446 447 448 449 450
	}

	return insts
}

3
3dgen 已提交
451
func (g *functionGenerator) addRegister(typ wir.ValueType) wir.Value {
3
3dgen 已提交
452
	defer func() { g.cur_local_id++ }()
3
3dgen 已提交
453
	name := "$T_" + strconv.Itoa(g.cur_local_id)
3
3dgen 已提交
454 455 456 457
	v := wir.NewVar(name, wir.ValueKindLocal, typ)
	g.registers = append(g.registers, v)
	return v
}