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