compile_func.go 11.9 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 *wir.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
}

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

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

44 45 46 47
	if v, ok := g.module.Globals_map[i]; ok {
		return v
	}

3
3dgen 已提交
48 49
	switch v := i.(type) {
	case *ssa.Const:
3
3dgen 已提交
50 51 52 53
		if v.Value == nil {
			return nil
		}

3
3dgen 已提交
54 55 56
		switch t := v.Type().(type) {
		case *types.Basic:
			switch t.Kind() {
3
3dgen 已提交
57

3
3dgen 已提交
58
			case types.Bool:
59
				if constant.BoolVal(v.Value) {
3
3dgen 已提交
60
					return wir.NewConst("1", wir.I32{})
61
				} else {
3
3dgen 已提交
62
					return wir.NewConst("0", wir.I32{})
63
				}
3
3dgen 已提交
64 65 66

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

chai2010's avatar
chai2010 已提交
69 70
			case types.Int32:
				val, _ := constant.Int64Val(v.Value)
3
3dgen 已提交
71
				if t.Name() == "rune" {
3
3dgen 已提交
72
					return wir.NewConst(strconv.Itoa(int(val)), wir.RUNE{})
3
3dgen 已提交
73
				} else {
3
3dgen 已提交
74
					return wir.NewConst(strconv.Itoa(int(val)), wir.I32{})
3
3dgen 已提交
75
				}
chai2010's avatar
chai2010 已提交
76

3
3dgen 已提交
77
			case types.Float32:
3
3dgen 已提交
78
				val, _ := constant.Float64Val(v.Value)
3
3dgen 已提交
79
				return wir.NewConst(strconv.FormatFloat(val, 'f', -1, 32), wir.F32{})
3
3dgen 已提交
80 81

			case types.Float64:
3
3dgen 已提交
82
				val, _ := constant.Float64Val(v.Value)
3
3dgen 已提交
83
				return wir.NewConst(strconv.FormatFloat(val, 'f', -1, 64), wir.F64{})
3
3dgen 已提交
84 85 86 87 88 89 90 91

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

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

3
3dgen 已提交
92 93 94
		case *types.Pointer:
			logger.Fatalf("Todo:%T", t)

3
3dgen 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
		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 已提交
112
func (g *functionGenerator) genFunction(f *ssa.Function) *wir.Function {
3
3dgen 已提交
113
	var wir_fn wir.Function
114 115 116 117 118
	if len(f.LinkName()) > 0 {
		wir_fn.Name = f.LinkName()
	} else {
		wir_fn.Name = f.Name()
	}
3
3dgen 已提交
119 120 121 122 123 124 125 126

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

	for _, i := range f.Params {
3
3dgen 已提交
127
		pa := wir.NewLocal(i.Name(), wir.ToWType(i.Type()))
3
3dgen 已提交
128 129 130 131
		wir_fn.Params = append(wir_fn.Params, pa)
		g.locals_map[i] = pa
	}

3
3dgen 已提交
132
	g.var_block_selector = wir.NewLocal("$block_selector", wir.I32{})
3
3dgen 已提交
133
	g.registers = append(g.registers, g.var_block_selector)
3
3dgen 已提交
134
	g.var_current_block = wir.NewLocal("$current_block", wir.I32{})
3
3dgen 已提交
135
	g.registers = append(g.registers, g.var_current_block)
3
3dgen 已提交
136
	if !wir_fn.Result.Equal(wir.VOID{}) {
3
3dgen 已提交
137
		g.var_ret = wir.NewLocal("$ret", wir_fn.Result)
3
3dgen 已提交
138 139 140
		g.registers = append(g.registers, g.var_ret)
	}

3
3dgen 已提交
141
	var block_temp wat.Inst
3
3dgen 已提交
142 143
	//BlockSel:
	{
3
3dgen 已提交
144
		inst := wat.NewInstBlock("$BlockSel")
3
ref WIP  
3dgen 已提交
145
		inst.Insts = append(inst.Insts, g.var_block_selector.EmitPush()...)
3
3dgen 已提交
146 147 148 149 150
		t := make([]int, len(f.Blocks)+1)
		for i := range f.Blocks {
			t[i] = i
		}
		t[len(f.Blocks)] = 0
3
3dgen 已提交
151
		inst.Insts = append(inst.Insts, wat.NewInstBrTable(t))
3
3dgen 已提交
152 153 154 155
		block_temp = inst
	}

	for i, b := range f.Blocks {
3
3dgen 已提交
156
		block := wat.NewInstBlock("$Block_" + strconv.Itoa(i))
3
3dgen 已提交
157 158 159 160 161 162 163
		block.Insts = append(block.Insts, block_temp)
		block.Insts = append(block.Insts, g.genBlock(b)...)
		block_temp = block
	}

	//BlockDisp
	{
3
3dgen 已提交
164
		inst := wat.NewInstLoop("$BlockDisp")
3
3dgen 已提交
165 166 167 168 169 170
		inst.Insts = append(inst.Insts, block_temp)
		block_temp = inst
	}

	//BlockFnBody
	{
3
3dgen 已提交
171
		inst := wat.NewInstBlock("$BlockFnBody")
3
3dgen 已提交
172 173 174 175
		inst.Insts = append(inst.Insts, block_temp)
		block_temp = inst
	}

3
ref WIP  
3dgen 已提交
176 177 178 179
	for _, i := range g.registers {
		wir_fn.Insts = append(wir_fn.Insts, i.EmitInit()...)
	}

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

3
3dgen 已提交
182
	if !wir_fn.Result.Equal(wir.VOID{}) {
3
ref WIP  
3dgen 已提交
183 184 185 186 187
		wir_fn.Insts = append(wir_fn.Insts, g.var_ret.EmitPush()...)
	}

	for _, i := range g.registers {
		wir_fn.Insts = append(wir_fn.Insts, i.EmitRelease()...)
3
3dgen 已提交
188 189
	}

3
3dgen 已提交
190 191
	wir_fn.Locals = g.registers

3
3dgen 已提交
192
	return &wir_fn
3
3dgen 已提交
193 194
}

3
3dgen 已提交
195
func (g *functionGenerator) genBlock(block *ssa.BasicBlock) []wat.Inst {
3
3dgen 已提交
196 197 198 199 200
	if len(block.Instrs) == 0 {
		logger.Fatalf("Block:%s is empty", block)
	}

	cur_block_assigned := false
3
3dgen 已提交
201
	var b []wat.Inst
3
3dgen 已提交
202 203 204
	for _, inst := range block.Instrs {
		if _, ok := inst.(*ssa.Phi); !ok {
			if !cur_block_assigned {
3
3dgen 已提交
205
				b = append(b, wir.EmitAssginValue(g.var_current_block, wir.NewConst(strconv.Itoa(block.Index), wir.I32{}))...)
3
3dgen 已提交
206 207 208 209 210 211 212 213 214 215
				cur_block_assigned = true
			}
		}

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

}

3
3dgen 已提交
216
func (g *functionGenerator) genInstruction(inst ssa.Instruction) []wat.Inst {
3
3dgen 已提交
217 218 219 220 221 222
	switch inst := inst.(type) {

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

	case *ssa.Store:
3
ref WIP  
3dgen 已提交
223
		return g.genStore(inst)
3
3dgen 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

	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 已提交
239
		if !t.Equal(wir.VOID{}) {
3
3dgen 已提交
240
			v := g.getValue(inst)
3
ref WIP  
3dgen 已提交
241
			s = append(s, v.EmitPop()...)
3
3dgen 已提交
242 243 244 245 246 247 248 249 250 251
			g.locals_map[inst] = v
		}
		return s

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

3
3dgen 已提交
252 253 254 255
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 已提交
256 257 258

	switch v := v.(type) {
	case *ssa.UnOp:
3
Ref WIP  
3dgen 已提交
259
		return g.genUnOp(v)
3
3dgen 已提交
260 261 262 263 264 265 266 267 268 269

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

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

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

3
Ref WIP  
3dgen 已提交
270 271 272
	case *ssa.Alloc:
		return g.genAlloc(v)

3
3dgen 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286
	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
Ref WIP  
3dgen 已提交
287 288 289
func (g *functionGenerator) genUnOp(inst *ssa.UnOp) ([]wat.Inst, wir.ValueType) {
	switch inst.Op {
	case token.MUL: //*x
290
		return g.genLoad(inst.X)
3
Ref WIP  
3dgen 已提交
291 292 293 294 295 296
	}

	logger.Fatal("Todo")
	return nil, nil
}

3
3dgen 已提交
297
func (g *functionGenerator) genBinOp(inst *ssa.BinOp) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
298 299 300 301 302 303 304
	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 已提交
305
			return wir.EmitBinOp(x, y, wat.OpCodeAdd)
3
3dgen 已提交
306 307

		case token.SUB:
3
3dgen 已提交
308
			return wir.EmitBinOp(x, y, wat.OpCodeSub)
3
3dgen 已提交
309 310

		case token.MUL:
3
3dgen 已提交
311
			return wir.EmitBinOp(x, y, wat.OpCodeMul)
3
3dgen 已提交
312 313

		case token.QUO:
3
3dgen 已提交
314
			return wir.EmitBinOp(x, y, wat.OpCodeQuo)
3
3dgen 已提交
315 316

		case token.REM:
3
3dgen 已提交
317
			return wir.EmitBinOp(x, y, wat.OpCodeRem)
3
3dgen 已提交
318 319

		case token.EQL:
3
3dgen 已提交
320
			return wir.EmitBinOp(x, y, wat.OpCodeEql)
3
3dgen 已提交
321 322

		case token.NEQ:
3
3dgen 已提交
323
			return wir.EmitBinOp(x, y, wat.OpCodeNe)
3
3dgen 已提交
324 325

		case token.LSS:
3
3dgen 已提交
326
			return wir.EmitBinOp(x, y, wat.OpCodeLt)
3
3dgen 已提交
327 328

		case token.GTR:
3
3dgen 已提交
329
			return wir.EmitBinOp(x, y, wat.OpCodeGt)
3
3dgen 已提交
330 331

		case token.LEQ:
3
3dgen 已提交
332
			return wir.EmitBinOp(x, y, wat.OpCodeLe)
3
3dgen 已提交
333 334

		case token.GEQ:
3
3dgen 已提交
335
			return wir.EmitBinOp(x, y, wat.OpCodeGe)
3
3dgen 已提交
336 337 338 339 340 341 342 343 344 345
		}

	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 已提交
346
func (g *functionGenerator) genCall(inst *ssa.Call) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
347 348 349 350 351 352 353
	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 已提交
354
		var insts []wat.Inst
3
3dgen 已提交
355
		for _, v := range inst.Call.Args {
3
ref WIP  
3dgen 已提交
356
			insts = append(insts, g.getValue(v).EmitPush()...)
3
3dgen 已提交
357
		}
358 359 360 361 362 363
		callee := inst.Call.StaticCallee()
		if len(callee.LinkName()) > 0 {
			insts = append(insts, wat.NewInstCall(callee.LinkName()))
		} else {
			insts = append(insts, wat.NewInstCall(callee.Name()))
		}
3
3dgen 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
		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 已提交
381
func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
382 383
	switch call.Value.Name() {
	case "print", "println":
3
3dgen 已提交
384
		var insts []wat.Inst
3
3dgen 已提交
385 386 387
		for _, arg := range call.Args {
			arg := g.getValue(arg)
			switch arg.Type().(type) {
3
3dgen 已提交
388
			case wir.I32:
3
ref WIP  
3dgen 已提交
389
				insts = append(insts, arg.EmitPush()...)
390
				insts = append(insts, wat.NewInstCall("$waPrintI32"))
3
3dgen 已提交
391

3
3dgen 已提交
392
			case wir.RUNE:
3
ref WIP  
3dgen 已提交
393
				insts = append(insts, arg.EmitPush()...)
394
				insts = append(insts, wat.NewInstCall("$waPrintRune"))
3
3dgen 已提交
395

3
3dgen 已提交
396
			default:
3
3dgen 已提交
397
				logger.Fatalf("Todo: print(%T)", arg.Type())
3
3dgen 已提交
398 399 400 401
			}
		}

		if call.Value.Name() == "println" {
3
3dgen 已提交
402
			insts = append(insts, wir.NewConst(strconv.Itoa('\n'), wir.I32{}).EmitPush()...)
403
			insts = append(insts, wat.NewInstCall("$waPrintRune"))
3
3dgen 已提交
404 405
		}

3
3dgen 已提交
406
		return insts, wir.VOID{}
3
3dgen 已提交
407 408 409 410 411
	}
	logger.Fatal("Todo:", call.Value)
	return nil, nil
}

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

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

3
ref WIP  
3dgen 已提交
418
	trueInsts := values[0].EmitPush()
3
3dgen 已提交
419
	var falseInsts []wat.Inst
3
3dgen 已提交
420
	if len(preds) == 2 {
3
ref WIP  
3dgen 已提交
421
		falseInsts = values[1].EmitPush()
3
3dgen 已提交
422
	} else {
3
3dgen 已提交
423
		falseInsts = g.genPhiIter(preds[1:], values[1:])
3
3dgen 已提交
424
	}
3
3dgen 已提交
425
	insts = append(insts, wat.NewInstIf(trueInsts, falseInsts, values[0].Type().Raw()))
3
3dgen 已提交
426 427 428

	return insts
}
3
3dgen 已提交
429
func (g *functionGenerator) genPhi(inst *ssa.Phi) ([]wat.Inst, wir.ValueType) {
3
3dgen 已提交
430 431 432 433 434 435 436 437 438
	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 已提交
439 440
func (g *functionGenerator) genReturn(inst *ssa.Return) []wat.Inst {
	var insts []wat.Inst
3
3dgen 已提交
441 442 443 444 445 446 447 448 449 450 451 452

	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 已提交
453
	insts = append(insts, wat.NewInstBr("$BlockFnBody"))
3
3dgen 已提交
454 455 456
	return insts
}

457 458 459 460
func (g *functionGenerator) genLoad(addr ssa.Value) ([]wat.Inst, wir.ValueType) {
	return wir.EmitLoad(g.getValue(addr))
}

3
ref WIP  
3dgen 已提交
461 462 463 464
func (g *functionGenerator) genStore(inst *ssa.Store) []wat.Inst {
	return wir.EmitStore(g.getValue(inst.Addr), g.getValue(inst.Val))
}

3
3dgen 已提交
465
func (g *functionGenerator) genIf(inst *ssa.If) []wat.Inst {
3
3dgen 已提交
466
	cond := g.getValue(inst.Cond)
3
3dgen 已提交
467
	if !cond.Type().Equal(wir.I32{}) {
3
3dgen 已提交
468 469 470
		logger.Fatal("cond.type() != i32")
	}

3
ref WIP  
3dgen 已提交
471
	insts := cond.EmitPush()
3
3dgen 已提交
472 473
	instsTrue := g.genJumpID(inst.Block().Index, inst.Block().Succs[0].Index)
	instsFalse := g.genJumpID(inst.Block().Index, inst.Block().Succs[1].Index)
3
3dgen 已提交
474
	insts = append(insts, wat.NewInstIf(instsTrue, instsFalse, nil))
3
3dgen 已提交
475 476 477 478

	return insts
}

3
3dgen 已提交
479
func (g *functionGenerator) genJump(inst *ssa.Jump) []wat.Inst {
3
3dgen 已提交
480 481 482
	return g.genJumpID(inst.Block().Index, inst.Block().Succs[0].Index)
}

3
3dgen 已提交
483 484
func (g *functionGenerator) genJumpID(cur, dest int) []wat.Inst {
	var insts []wat.Inst
3
3dgen 已提交
485 486

	if cur >= dest {
3
3dgen 已提交
487
		insts = wir.EmitAssginValue(g.var_block_selector, wir.NewConst(strconv.Itoa(dest), wir.I32{}))
3
3dgen 已提交
488
		insts = append(insts, wat.NewInstBr("$BlockDisp"))
3
3dgen 已提交
489
	} else {
3
3dgen 已提交
490
		insts = append(insts, wat.NewInstBr("$Block_"+strconv.Itoa(dest-1)))
3
3dgen 已提交
491 492 493 494 495
	}

	return insts
}

3
Ref WIP  
3dgen 已提交
496 497
func (g *functionGenerator) genAlloc(inst *ssa.Alloc) ([]wat.Inst, wir.ValueType) {
	if inst.Heap {
3
3dgen 已提交
498
		return wir.EmitHeapAlloc(wir.ToWType(inst.Type().(*types.Pointer).Elem()), g.module)
3
Ref WIP  
3dgen 已提交
499
	} else {
3
3dgen 已提交
500
		return wir.EmitStackAlloc(wir.ToWType(inst.Type().(*types.Pointer).Elem()), g.module)
3
Ref WIP  
3dgen 已提交
501 502 503
	}
}

3
3dgen 已提交
504
func (g *functionGenerator) addRegister(typ wir.ValueType) wir.Value {
3
3dgen 已提交
505
	defer func() { g.cur_local_id++ }()
3
3dgen 已提交
506
	name := "$T_" + strconv.Itoa(g.cur_local_id)
3
3dgen 已提交
507
	v := wir.NewLocal(name, typ)
3
3dgen 已提交
508 509 510
	g.registers = append(g.registers, v)
	return v
}