
Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/I5G96F Test: Test262 suit, ark unittest, rk3568 XTS, ark previewer demo Signed-off-by: huangyu <huangyu76@huawei.com> Change-Id: I3f63d129a07deaa27a390f556dcaa5651c098185
3.7 KiB
Irtoc tool
Irtoc(Ir-To-Code) tool is aimed to compile a manually created IR (intermediate representation) to the target code.
Building flow:
Irtoc language
WARNING: this part is still under development. Thus, some things may be changed in the final implementation.
Irtoc 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.
Each opcode in the IR instructions has corresponding token in the irtoc lang. For example, IR instruction Add
:
- opcode: Add
base: BinaryOperation
signature: [d-number, number, number]
flags: [commutative, acc_write, acc_read, ifcvt]
description: Add two inputs.
has keyword with the same name Add
and with same signature:
var = Add(input1, input2)
All property setters that IrConstructor provides (i64
, bool
, Pc
, CC
, etc) are
available in Irtoc lang. They can be set in the similar way as in the IrConstructor:
var = Add(input1, input2).i64.CC(:CC_GE).pc(123)
Pseudo instructions
Pseudo instructions are not a real IR instructions in terms of compiler, those instructions are needed only as helpers for Irtoc. For example, for creating a control flow: Label, Else, While.
Pseudo instructions are described like regular instructions in the instructions.yaml
file, but in the separate section pseudo_instructions
.
Data flow
In last example variable var
holds the newly created instruction Add
and it can be input for the further instructions.
Thus, dataflow is constructing like in other general-purpose language: assign variable - use variable:
var = Add(input1, input2).i64.CC(:CC_GE).pc(123)
Return(var).i64
Also it is possible to omit variables and create instruction in-place:
Return(Add(input1, input2).i64.CC(:CC_GE).pc(123)).i64
Control flow
Irtoc uses instruction If
and pseudo instruction Else
to express conditional execution.
For example, add 1 to the biggest value:
function TestIncMaxValue(params: {a: i64, b: i64}) {
If(a, b).CC(:CC_GE) {
v1 = Add(a, 1).i64
} Else {
v2 = Add(b, 1).i64
}
phi = Phi(v1, v2)
Return(phi).i64
}
After automatic phi insertion will be implemented:
function TestIncMaxValue(params: {a: i64, b: i64}) {
If(a, b).CC(:CC_GE) {
v = Add(a, 1).i64
} Else {
v = Add(b, 1).i64
}
Return(v).i64
}
While
statement has the following semantic:
function SumSequence(params: {start: u64, end: u64}) {
res = 0
While (start, end).cc(ne) {
res = Add(res, start)
start = Add(start, 1)
}
Return.u32(res)
}
Using labels:
function SumSequence(params: {start: u64, end: u64}) {
res = 0
Label(head)
If (start, end).cc(ne) {
Goto(exit)
}
res = Add(res, start)
start = Add(start, 1)
Goto(head)
Label(exit)
Return.u32(res)
}
Dedicated registers
Sometimes there will be need to specify target register for the input parameter or other entities within a script.
For such needs, each function takes registers map as an input:
regmap_tls = {ARM64: {tr: 28},
ARM32: {tr: 12},
X86_64: {tr: 15}}
function CallEntrypoint(params: {offset: u64, tls: ptr(tr)}, regmap=regmap_tls) {
entry = Load(tr, offset)
Call(entry)
}
It will be transformed to the folloiwng code for Arm64 target:
COMPILE(CallEntrypoint) {
GRAPH(GetGraph()) {
PARAMETER(0, 1).u64();
PARAMETER(1, 1).ptr().DstReg(28); // for x86 will be `.DstReg(15)`
...
}
}
So, 28 register will be reserved for the life interval started by the second parameter.