1b1994897Sopenharmony_ci# Irtoc tool
2b1994897Sopenharmony_ci
3b1994897Sopenharmony_ci**Irtoc**(Ir-To-Code) tool is aimed to compile a manually created IR (intermediate representation) to the target code.
4b1994897Sopenharmony_ci
5b1994897Sopenharmony_ciBuilding flow:
6b1994897Sopenharmony_ci
7b1994897Sopenharmony_ci![irtoc_build_flow](images/irtoc_build_flow.png)
8b1994897Sopenharmony_ci
9b1994897Sopenharmony_ci## Irtoc language
10b1994897Sopenharmony_ci
11b1994897Sopenharmony_ci> WARNING: this part is still under development. Thus, some things may be changed in the final implementation.
12b1994897Sopenharmony_ci
13b1994897Sopenharmony_ciIrtoc DSL is a wrapper above the `IrConstructor`. It reads compiler's `instructions.yaml` file to get information about instructions. As output it generates c++ code, that uses `IrConstructor` to build IR.
14b1994897Sopenharmony_ci
15b1994897Sopenharmony_ciEach opcode in the IR instructions has corresponding token in the irtoc lang. For example, IR instruction `Add`:
16b1994897Sopenharmony_ci```
17b1994897Sopenharmony_ci  - opcode: Add
18b1994897Sopenharmony_ci    base: BinaryOperation
19b1994897Sopenharmony_ci    signature: [d-number, number, number]
20b1994897Sopenharmony_ci    flags: [commutative, acc_write, acc_read, ifcvt]
21b1994897Sopenharmony_ci    description: Add two inputs.
22b1994897Sopenharmony_ci```
23b1994897Sopenharmony_cihas keyword with the same name `Add` and with same signature:
24b1994897Sopenharmony_ci```
25b1994897Sopenharmony_civar = Add(input1, input2)
26b1994897Sopenharmony_ci```
27b1994897Sopenharmony_ci
28b1994897Sopenharmony_ciAll property setters that IrConstructor provides (`i64`, `bool`, `Pc`, `CC`, etc) are
29b1994897Sopenharmony_ciavailable in Irtoc lang. They can be set in the similar way as in the IrConstructor:
30b1994897Sopenharmony_ci```
31b1994897Sopenharmony_civar = Add(input1, input2).i64.CC(:CC_GE).pc(123)
32b1994897Sopenharmony_ci```
33b1994897Sopenharmony_ci### Pseudo instructions
34b1994897Sopenharmony_ciPseudo instructions are not a real IR instructions in terms of compiler, those instructions are needed only as helpers
35b1994897Sopenharmony_cifor Irtoc. For example, for creating a control flow: Label, Else, While.
36b1994897Sopenharmony_ci
37b1994897Sopenharmony_ciPseudo instructions are described like regular instructions in the `instructions.yaml` file, but in the separate section `pseudo_instructions`.
38b1994897Sopenharmony_ci
39b1994897Sopenharmony_ci### Data flow
40b1994897Sopenharmony_ci
41b1994897Sopenharmony_ciIn last example variable `var` holds the newly created instruction `Add` and it can be input for the further instructions.
42b1994897Sopenharmony_ciThus, dataflow is constructing like in other general-purpose language: assign variable - use variable:
43b1994897Sopenharmony_ci```
44b1994897Sopenharmony_civar = Add(input1, input2).i64.CC(:CC_GE).pc(123)
45b1994897Sopenharmony_ciReturn(var).i64
46b1994897Sopenharmony_ci```
47b1994897Sopenharmony_ciAlso it is possible to omit variables and create instruction in-place:
48b1994897Sopenharmony_ci```
49b1994897Sopenharmony_ciReturn(Add(input1, input2).i64.CC(:CC_GE).pc(123)).i64
50b1994897Sopenharmony_ci```
51b1994897Sopenharmony_ci
52b1994897Sopenharmony_ci### Control flow
53b1994897Sopenharmony_ci
54b1994897Sopenharmony_ciIrtoc uses instruction `If` and pseudo instruction `Else` to express conditional execution.
55b1994897Sopenharmony_ci
56b1994897Sopenharmony_ciFor example, add 1 to the biggest value:
57b1994897Sopenharmony_ci```
58b1994897Sopenharmony_cifunction TestIncMaxValue(params: {a: i64, b: i64}) {
59b1994897Sopenharmony_ci    If(a, b).CC(:CC_GE) {
60b1994897Sopenharmony_ci        v1 = Add(a, 1).i64
61b1994897Sopenharmony_ci    } Else {
62b1994897Sopenharmony_ci        v2 = Add(b, 1).i64
63b1994897Sopenharmony_ci    }
64b1994897Sopenharmony_ci    phi = Phi(v1, v2)
65b1994897Sopenharmony_ci    Return(phi).i64
66b1994897Sopenharmony_ci}
67b1994897Sopenharmony_ci```
68b1994897Sopenharmony_ci
69b1994897Sopenharmony_ciAfter automatic phi insertion will be implemented:
70b1994897Sopenharmony_ci```
71b1994897Sopenharmony_cifunction TestIncMaxValue(params: {a: i64, b: i64}) {
72b1994897Sopenharmony_ci    If(a, b).CC(:CC_GE) {
73b1994897Sopenharmony_ci        v = Add(a, 1).i64
74b1994897Sopenharmony_ci    } Else {
75b1994897Sopenharmony_ci        v = Add(b, 1).i64
76b1994897Sopenharmony_ci    }
77b1994897Sopenharmony_ci    Return(v).i64
78b1994897Sopenharmony_ci}
79b1994897Sopenharmony_ci```
80b1994897Sopenharmony_ci
81b1994897Sopenharmony_ci`While` statement has the following semantic:
82b1994897Sopenharmony_ci```
83b1994897Sopenharmony_cifunction SumSequence(params: {start: u64, end: u64}) {
84b1994897Sopenharmony_ci    res = 0
85b1994897Sopenharmony_ci    While (start, end).cc(ne) {
86b1994897Sopenharmony_ci        res = Add(res, start)
87b1994897Sopenharmony_ci        start = Add(start, 1)
88b1994897Sopenharmony_ci    }
89b1994897Sopenharmony_ci
90b1994897Sopenharmony_ci    Return.u32(res)
91b1994897Sopenharmony_ci}
92b1994897Sopenharmony_ci```
93b1994897Sopenharmony_ci
94b1994897Sopenharmony_ciUsing labels:
95b1994897Sopenharmony_ci
96b1994897Sopenharmony_ci```
97b1994897Sopenharmony_cifunction SumSequence(params: {start: u64, end: u64}) {
98b1994897Sopenharmony_ci    res = 0
99b1994897Sopenharmony_ci
100b1994897Sopenharmony_ci    Label(head)
101b1994897Sopenharmony_ci    If (start, end).cc(ne) {
102b1994897Sopenharmony_ci        Goto(exit)
103b1994897Sopenharmony_ci    }
104b1994897Sopenharmony_ci
105b1994897Sopenharmony_ci    res = Add(res, start)
106b1994897Sopenharmony_ci    start = Add(start, 1)
107b1994897Sopenharmony_ci    Goto(head)
108b1994897Sopenharmony_ci
109b1994897Sopenharmony_ci    Label(exit)
110b1994897Sopenharmony_ci
111b1994897Sopenharmony_ci    Return.u32(res)
112b1994897Sopenharmony_ci}
113b1994897Sopenharmony_ci```
114b1994897Sopenharmony_ci
115b1994897Sopenharmony_ci## Dedicated registers
116b1994897Sopenharmony_ci
117b1994897Sopenharmony_ciSometimes there will be need to specify target register for the input parameter or other entities within a script.
118b1994897Sopenharmony_ci
119b1994897Sopenharmony_ciFor such needs, each function takes registers map as an input:
120b1994897Sopenharmony_ci```
121b1994897Sopenharmony_ciregmap_tls = {ARM64: {tr: 28},
122b1994897Sopenharmony_ci              ARM32: {tr: 12},
123b1994897Sopenharmony_ci              X86_64: {tr: 15}}
124b1994897Sopenharmony_cifunction CallEntrypoint(params: {offset: u64, tls: ptr(tr)}, regmap=regmap_tls) {
125b1994897Sopenharmony_ci    entry = Load(tr, offset)
126b1994897Sopenharmony_ci    Call(entry)
127b1994897Sopenharmony_ci}
128b1994897Sopenharmony_ci```
129b1994897Sopenharmony_ciIt will be transformed to the folloiwng code for Arm64 target:
130b1994897Sopenharmony_ci```
131b1994897Sopenharmony_ciCOMPILE(CallEntrypoint) {
132b1994897Sopenharmony_ci    GRAPH(GetGraph()) {
133b1994897Sopenharmony_ci        PARAMETER(0, 1).u64();
134b1994897Sopenharmony_ci        PARAMETER(1, 1).ptr().DstReg(28); // for x86 will be `.DstReg(15)`
135b1994897Sopenharmony_ci        ...
136b1994897Sopenharmony_ci    }
137b1994897Sopenharmony_ci}
138b1994897Sopenharmony_ci```
139b1994897Sopenharmony_ciSo, 28 register will be reserved for the life interval started by the second parameter.
140