vxx2 / vlib / v3 / insel / insel.v
118 lines · 109 sloc · 2.21 KB · 6c4d26f1f98c5464b012a375667ab345e462f7e0
Raw
1module insel
2
3import v3.mir
4import v3.ssa
5
6// OperandKind lists operand kind values used by insel.
7pub enum OperandKind {
8 value
9 block
10}
11
12// Operand represents operand data used by insel.
13pub struct Operand {
14pub:
15 kind OperandKind
16 id int
17}
18
19// Instruction represents instruction data used by insel.
20pub struct Instruction {
21pub:
22 op ssa.OpCode
23 operands []Operand
24 typ ssa.TypeID
25}
26
27// BasicBlock represents basic block data used by insel.
28pub struct BasicBlock {
29pub:
30 id int
31 name string
32 instrs []Instruction
33}
34
35// Function represents function data used by insel.
36pub struct Function {
37pub:
38 id int
39 name string
40 abi mir.FunctionAbi
41 blocks []BasicBlock
42}
43
44// Module represents module data used by insel.
45pub struct Module {
46pub:
47 target mir.Target
48 funcs []Function
49}
50
51// select_ selects MIR instructions into a target-specific machine module shell.
52pub fn select_(mut m mir.Module) Module {
53 mut funcs := []Function{}
54 for f in m.funcs {
55 if f.is_c_extern {
56 continue
57 }
58 mut blocks := []BasicBlock{}
59 for block_id in f.blocks {
60 if block_id < 0 || block_id >= m.blocks.len {
61 continue
62 }
63 blk := m.blocks[block_id]
64 mut instrs := []Instruction{}
65 for val_id in blk.instrs {
66 if val_id <= 0 || val_id >= m.values.len {
67 continue
68 }
69 val := m.values[val_id]
70 if val.kind != .instruction {
71 continue
72 }
73 instr := m.instrs[val.index]
74 instrs << Instruction{
75 op: instr.op
76 operands: select_operands(instr)
77 typ: instr.typ
78 }
79 }
80 blocks << BasicBlock{
81 id: blk.id
82 name: blk.name
83 instrs: instrs
84 }
85 }
86 funcs << Function{
87 id: f.id
88 name: f.name
89 abi: f.abi
90 blocks: blocks
91 }
92 }
93 return Module{
94 target: m.target
95 funcs: funcs
96 }
97}
98
99// select_operands resolves select operands information for insel.
100fn select_operands(instr mir.Instruction) []Operand {
101 mut operands := []Operand{}
102 for i, operand in instr.operands {
103 kind := if instr.op == .br && i > 0 {
104 OperandKind.block
105 } else if instr.op == .phi && i % 2 == 1 {
106 OperandKind.block
107 } else if instr.op == .jmp {
108 OperandKind.block
109 } else {
110 OperandKind.value
111 }
112 operands << Operand{
113 kind: kind
114 id: operand
115 }
116 }
117 return operands
118}
119