5.1 编译原理
目录
引言
编译原理是将文本字符流,通过一系列的分析、转换,最后生成确定的指令文件的数据分析转换技术。
编译器是利用编译原理,将一种程序(源程序)翻译成另一种程序(目标程序)的计算机程序。业界也将编译器分为三个部分:前端、中端、后端。
编译器所做的工作流程如下图所示。
编译器是利用编译原理,将一种程序(源程序)翻译成另一种程序(目标程序)的计算机程序。业界也将编译器分为三个部分:前端、中端、后端。
编译器所做的工作流程如下图所示。
词法分析就是将代码字符流,按照一定的规则进行分析,获取符合词法规则的字符串,并进行信息标注,为语法分析提供单词(Token)流。
词法分析按照规定的规则,可以从字符流中获取数据。
规则定义为以下几类:
待续
待续
语法分析就是将词法分析提供单词(Token)流,按照语法规则构建抽象语法分析树,为语义分析提供数据骨架。
待续
待续
待续
待续
待续
待续
待续
语义分析就是分析语法树中所有的符号是否存在声明,从语义层次进一步规范程序所表达的含义。
指令集可分为两大类,真实硬件指令集和虚拟机指令集。
真实硬件指令集又分为两类:
虚拟机指令集可分为三种:
虚拟机的指令与设计的字节码保存文件存在较强相关性,所以要真正理解虚拟机指令,还需要理解字节码文件的存储格式。
基于栈的指令集参考Java的指令集。
Dalvik 字节码指令集的字节码指令集不支持无符号整数运算,因此参照 Dalvik 设计了以下指令集。
基于纯寄存器的指令集,指令系统存在下列的要求:
总体格式:
操作码 + [ 操作子码 ] + ( 操作数 )*
寄存器位宽索引支持的寄存器数量:
位宽 | 寄存器数量 | 索引范围 |
---|---|---|
4 bit | 16 | [ 0, 15 ] |
8 bit | 256 | [ 0, 255 ] |
16 bit | 65536 | [ 0, 65535 ] |
文本格式: nop
助记符 | 操作码 | 对齐 | 注解 |
---|---|---|---|
格式 | 8 bit | 8bit | 指令宽度:16 bit |
nop | 0 | 空操作,用于对齐 |
助记符 | 操作码 | 目的寄存器 | 立即数 | 注解 |
---|---|---|---|---|
8 bit | 4 bit | 4 bit | 4 bit 立即数,指令宽度:16 bit | |
const-w32-I4-i4 | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 | |
const-w64-I4-i4 | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 | |
const-w32-I4-u4 | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 | |
const-w64-I4-u4 | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 | |
8 bit | 8 bit | 16 bit | 16 bit 立即数,指令宽度:32 bit | |
const-w32-I8-i16 | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 | |
const-w64-I8-i16 | des | imm | imm 为有符号整数,有符号扩展至 64 bit。 | |
const-w32-I8-u16 | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 | |
const-w64-I8-u16 | des | imm | imm 为无符号整数,无符号扩展至 64 bit。 | |
const-w32-I8-L16 | des | imm | imm 为无符号整数。imm 存放在寄存器的低 16 bit,不改变高 16 bit。 | |
const-w32-I8-H16 | des | imm | imm 为无符号整数。imm 存放在寄存器的高 16 bit,不改变低 16 bit。 | |
8 bit | 8 bit | 32 bit | 32 bit 立即数,指令宽度:48 bit | |
const-w32-I8 | des | imm | 原样拷贝,支持32 bit 整数和浮点。 | |
const-w64-I8-i32 | des | imm | imm 为有符号整数,有符号扩展至 64 bit。 | |
const-w64-I8-u32 | des | imm | imm 为无符号整数,无符号扩展至 64 bit。 | |
8 bit | 8 bit | 64 bit | 64 bit 立即数,指令宽度:80 bit | |
const-w64-I8 | des | imm | 原样拷贝,支持64 bit整数和浮点。 |
助记符 | 操作码 | 操作子码 | 目的寄存器 | 立即数 | 注解 |
---|---|---|---|---|---|
8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit | |
const-w32-I8 | subop | des | imm | imm 为无符号整数 |
助记符 | 操作子码 | 注解 |
---|---|---|
B0 | imm存放在寄存器的第 1 个字节,不改变其他字节。 | |
B1 | imm存放在寄存器的第 2 个字节,不改变其他字节。 | |
B2 | imm存放在寄存器的第 3 个字节,不改变其他字节。 | |
B3 | imm存放在寄存器的第 4 个字节,不改变其他字节。 |
文本格式:op des,src
助记符 | 操作码 | 目的寄存器 | 源寄存器 | 注解 |
---|---|---|---|---|
8 bit | 4 bit | 4 bit | 指令宽度:16 bit | |
move-w32-I4 | des | src | 32 位寄存器值传递 | |
move-w64-I4 | des | src | 64 位寄存器值传递 | |
8 bit | 8 bit | 16 bit | 指令宽度:32 bit | |
move-w32-I8I16 | des | src | 32 位寄存器值传递 | |
move-w64-I8I16 | des | src | 64 位寄存器值传递 |
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 注解 |
---|---|---|---|---|---|
8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit | |
mov-I8 | sub | des | src | ||
8 bit | 8 bit | 16 bit | 16 bit | 指令宽度:48 bit | |
mov-I16 | sub | des | src |
助记符含义:
目标位宽-源数据获取转换位宽
目标类型-源类型
助记符 | 操作子码 | 注解 |
---|---|---|
w32-B0-i8 | 0 | 获取寄存器的第 1 个字节,进行符号扩展到 32 位 |
w32-B0-u8 | 1 | 获取寄存器的第 1 个字节,进行零扩展到 32 位 |
w32-B1-i8 | 2 | 获取寄存器的第 2 个字节,进行符号扩展到 32 位 |
w32-B1-u8 | 3 | 获取寄存器的第 2 个字节,进行零扩展到 32 位 |
w32-B2-i8 | 4 | 获取寄存器的第 3 个字节,进行符号扩展到 32 位 |
w32-B2-u8 | 5 | 获取寄存器的第 3 个字节,进行零扩展到 32 位 |
w32-B3-i8 | 6 | 获取寄存器的第 4 个字节,进行符号扩展到 32 位 |
w32-B3-u8 | 7 | 获取寄存器的第 4 个字节,进行零扩展到 32 位 |
w32-L16-i16 | 8 | 获取寄存器的低 16 位,进行符号扩展到 32 位 |
w32-L16-u16 | 9 | 获取寄存器的低 16 位,进行零扩展到 32 位 |
w32-H16-i16 | 10 | 获取寄存器的高 16 位,进行符号扩展到 32 位 |
w32-H16-u16 | 11 | 获取寄存器的高 16 位,进行零扩展到 32 位 |
w32 | 12 | 32 位原值拷贝传递 |
w64-B0-i8 | 13 | 获取寄存器的第 1 个字节,进行符号扩展到 64 位 |
w64-B0-u8 | 14 | 获取寄存器的第 1 个字节,进行零扩展到 64 位 |
w64-B1-i8 | 15 | 获取寄存器的第 2 个字节,进行符号扩展到 64 位 |
w64-B1-u8 | 16 | 获取寄存器的第 2 个字节,进行零扩展到 64 位 |
w64-B2-i8 | 17 | 获取寄存器的第 3 个字节,进行符号扩展到 64 位 |
w64-B2-u8 | 18 | 获取寄存器的第 3 个字节,进行零扩展到 64 位 |
w64-B3-i8 | 19 | 获取寄存器的第 4 个字节,进行符号扩展到 64 位 |
w64-B3-u8 | 20 | 获取寄存器的第 4 个字节,进行零扩展到 64 位 |
w64-L16-i16 | 21 | 获取寄存器的低 16 位,进行符号扩展到 32 位 |
w64-L16-u16 | 22 | 获取寄存器的低 16 位,进行零扩展到 32 位 |
w64-H16-i16 | 23 | 获取寄存器的高 16 位,进行符号扩展到 32 位 |
w64-H16-u16 | 24 | 获取寄存器的高 16 位,进行零扩展到 32 位 |
w64-i32 | 25 | 获取寄存器的 32 位,进行符号扩展到 64 位 |
w64-u32 | 26 | 获取寄存器的 32 位,进行零扩展到 64 位 |
w64 | 27 | 64 位原值拷贝传递 |
i32-f32 | 28 | 32 位有符号整数转 32 位浮点数 |
i32-f64 | 29 | 32 位有符号整数转 64 位浮点数 |
u32-f32 | 30 | 32 位无符号整数转 32 位浮点数 |
u32-f64 | 31 | 32 位无符号整数转 64 位浮点数 |
i64-f32 | 32 | 64 位有符号整数转 32 位浮点数 |
i64-f64 | 33 | 64 位有符号整数转 32 位浮点数 |
u64-f32 | 34 | 64 位无符号整数转 32 位浮点数 |
u64-f64 | 35 | 64 位无符号整数转 64 位浮点数 |
f32-i32 | 36 | 32 位浮点数转 32 位有符号 |
f32-i64 | 37 | 32 位浮点数转 64 位有符号 |
f32-u32 | 38 | 32 位浮点数转 32 位无符号 |
f32-u64 | 39 | 32 位浮点数转 64 位无符号 |
f32-f64 | 49 | 32 位浮点数转 64 位浮点数 |
f64-i32 | 41 | 64 位浮点数转 32 位有符号 |
f64-i64 | 42 | 64 位浮点数转 64 位有符号 |
f64-u32 | 43 | 64 位浮点数转 32 位无符号 |
f64-u64 | 44 | 64 位浮点数转 64 位无符号 |
f64-f32 | 45 | 64 位浮点数转 32 位浮点数 |
三地址文本格式: op.sub des,src,src2
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 源操作数 | 注解 |
---|---|---|---|---|---|---|
8 bit | 8 bit | 8 bit | 4 bit | 4 bit | 指令宽度:32 bit | |
math-I4 | sub | des | src | src2 | ||
8 bit | 8 bit | 16 bit | 8 bit | 8 bit | 指令宽度:48 bit | |
math-I16I8 | sub | des | src | src2 | ||
8 bit | 8 bit | 16 bit | 16 bit | 16 bit | 指令宽度:64 bit | |
math-I16 | sub | des | src | src2 |
助记符 | 操作子码 | 注解 |
---|---|---|
add-int32 | 0 | 32 位有符号 加 + |
sub-int32 | 1 | 32 位有符号 减 - |
mul-int32 | 2 | 32 位有符号 乘 * |
div-int32 | 3 | 32 位有符号 除 / |
mod-int32 | 4 | 32 位有符号 模 % |
add-uint32 | 5 | 32 位无符号 加 + |
sub-uint32 | 6 | 32 位无符号 减 - |
mul-uint32 | 7 | 32 位无符号 乘 * |
div-uint32 | 8 | 32 位无符号 除 / |
mod-uint32 | 9 | 32 位无符号 模 % |
add-int64 | 10 | 64 位有符号 加 + |
sub-int64 | 11 | 64 位有符号 减 - |
mul-int64 | 12 | 64 位有符号 乘 * |
div-int64 | 13 | 64 位有符号 除 / |
mod-int64 | 14 | 64 位有符号 |
add-uint64 | 15 | 64 位无符号 加 + |
sub-uint64 | 16 | 64 位无符号 减 - |
mul-uint64 | 17 | 64 位无符号 乘 * |
div-uint64 | 18 | 64 位无符号 除 / |
mod-uint64 | 19 | 64 位无符号 模 % |
add-flt32 | 20 | 32 位浮点 加 + |
sub-flt32 | 21 | 32 位浮点 减 - |
mul-flt32 | 22 | 32 位浮点 乘 * |
div-flt32 | 23 | 32 位浮点 除 / |
mod-flt32 | 24 | 32 位浮点 模 % |
add-flt64 | 25 | 64 位浮点 加 + |
sub-flt64 | 26 | 64 位浮点 减 - |
mul-flt64 | 27 | 64 位浮点 乘 * |
div-flt64 | 28 | 64 位浮点 除 / |
mod-flt64 | 29 | 64 位浮点 模 % |
sl-w32 | 30 | 32 位 左移 |
sr-w32 | 31 | 32 位 右移 |
sra-w32 | 32 | 32 位 算术右移 |
rol-w32 | 33 | 32 位 循环左移 |
ror-w32 | 34 | 32 位 循环右移 |
and-w32 | 35 | 32 位 位与 |
or-w32 | 36 | 32 位 位或 |
xor-w32 | 37 | 32 位 位异或 |
sl-w64 | 38 | 64 位 左移 |
sr-w64 | 39 | 64 位 右移 |
sra-w64 | 40 | 64 位 算术右移 |
rol-w32 | 41 | 64 位 循环左移 |
ror-w32 | 42 | 64 位 循环右移 |
and-w64 | 43 | 64 位 位与 |
or-w64 | 44 | 64 位 位或 |
xor-w64 | 45 | 64 位 位异或 |
andl-w32 | 46 | 32 位 逻辑与 |
orl-w32 | 47 | 32 位 逻辑或 |
cmp-int32 | 48 | src < src2 : des=-1 |
cmp-uint32 | 49 | src == src2 : des=0 |
cmp-int64 | 50 | src > src2 : des=1 |
cmp-uint64 | 51 | |
cmp-flt32 | 52 | |
cmp-flt64 | 53 | |
二地址文本格式: op.sub des,src
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 源操作数 | 注解 |
---|---|---|---|---|---|---|
8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit | ||
math-I8 | sub | des | src | |||
8 bit | 8 bit | 16 bit | 16 bit | 指令宽度:48 bit | ||
math-I16 | sub | des | src |
助记符 | 操作子码 | 注解 |
---|---|---|
not-w32 | 0 | 32 位 按位取反 |
not-w64 | 1 | 64 位 按位取反 |
inv-w32 | 2 | 32 位 逻辑取反 |
inv-w64 | 3 | 64 位 逻辑取反 |
neg-int32 | 4 | 32 位 符号取反 |
neg-int64 | 5 | 64 位 符号取反 |
neg-flt32 | 6 | 32 位 符号取反 |
neg-flt64 | 7 | 64 位 符号取反 |
abs-int32 | 8 | 32 位 取绝对值 |
abs-int64 | 9 | 64 位 取绝对值 |
abs-flt32 | 10 | 32 位 取绝对值 |
abs-flt64 | 11 | 64 位 取绝对值 |
sin-flt32 | 12 | 三角函数 |
cos-flt32 | 13 | 三角函数 |
tan-flt32 | 14 | 三角函数 |
asin-flt32 | 15 | 三角函数 |
acos-flt32 | 16 | 三角函数 |
atan-flt32 | 17 | 三角函数 |
sin-flt64 | 18 | 三角函数 |
cos-flt64 | 19 | 三角函数 |
tan-flt64 | 20 | 三角函数 |
asin-flt64 | 21 | 三角函数 |
acos-flt64 | 22 | 三角函数 |
atan-flt64 | 23 | 三角函数 |
文本格式: goto imm
助记符 | 操作码 | 对齐 | 立即数 | 注解 |
---|---|---|---|---|
8 bit | 8 bit | 指令宽度: 16 bit | ||
goto8 | imm | 8 bit有符号偏移 | ||
8 bit | 8 bit | 16 bit | 指令宽度: 32 bit | |
goto16 | imm | |||
8 bit | 8 bit | 32 bit | 指令宽度: 48 bit | |
goto32 | imm |
jbr src,src2,imm
jbr src,imm
助记符 | 操作码 | 操作子码 | 类型码 | 源操作数 | 源操作数 | 立即数 | 注解 |
---|---|---|---|---|---|---|---|
8 bit | 4 bit | 4 bit | |||||
8 bit | 8 bit | 16 bit | 指令宽度: 32 bit | ||||
8 bit | 8 bit | 32 bit | 指令宽度: 32 bit | ||||
16 bit | 16 bit | 16 bit | 指令宽度: 32 bit | ||||
16 bit | 16 bit | 32 bit | 指令宽度: 32 bit | ||||
src | src2 | imm |
助记符 | 操作子码 | 注解 |
---|---|---|
eq | 0 | if( src == src2 ) goto imm |
ne | 1 | if( src != src2 ) goto imm |
lt | 2 | if( src < src2 ) goto imm |
le | 3 | if( src <= src2 ) goto imm |
gt | 4 | if( src > src2 ) goto imm |
ge | 5 | if( src >= src2 ) goto imm |
eqz | 6 | if( src == 0 ) goto imm |
nez | 7 | if( src != 0 ) goto imm |
ltz | 8 | if( src < 0 ) goto imm |
lez | 9 | if( src <= 0 ) goto imm |
gtz | 10 | if( src > 0 ) goto imm |
gez | 11 | if( src >= 0 ) goto imm |
注意: 和 0 比较时,无源操作数 src2。
助记符 | 操作子码 | 注解 |
---|---|---|
int32 | 0 | 32 位有符号比较 |
uint32 | 1 | 32 位无符号比较 |
int64 | 2 | 64 位有符号比较 |
uint64 | 3 | 64 位无符号比较 |
flt32 | 4 | 32 位浮点数比较 |
flt64 | 5 | 64 位浮点数比较 |
文本格式: op src op imm
助记符 | 操作码 | 操作子码 | 立即数码 | 源操作数 | 注解 |
---|---|---|---|---|---|
8 bit | 8 bit | 指令宽度: 16 bit | |||
return-void | 无参数返回 | ||||
return-w32-I8 | 返回 32 bit 值 | ||||
return-w64-I8 | 返回 64 bit 值 | ||||
8 bit | 4 bit | 4 bit | 16/32/64 bit |
助记符 | 操作子码 | 注解 |
---|---|---|
I16 | 0 | 寄存器索引16位 |
int32 | 1 | 立即数转换到32位有符号整数 |
uint32 | 2 | 立即数转换到32位有符号整数 |
int64 | 3 | 立即数转换到32位有符号整数 |
uint64 | 4 | 立即数转换到32位有符号整数 |
flt32 | 5 | 立即数转换到32位有符号整数 |
flt64 | 6 | 立即数转换到32位有符号整数 |
助记符 | 操作子码 | 注解 |
---|---|---|
B16 | 0 | 16 位立即数 |
B32 | 1 | 32 位立即数 |
B64 | 2 | 64 位立即数 |
文本格式:op argcnt, arg,arg2,…,func
助记符 | 操作码 | 参数个数 | 参数寄存器 | 函数 | 注解 |
---|---|---|---|---|---|
8 bit | 8 bit | 16 bit | 32 bit | ||
invoke-virtual-nofix | argcnt | arg… | func | 调用虚函数 | |
invoke-direct-nofix | argcnt | arg… | func | 直接调用函数 | |
invoke-static-nofix | argcnt | arg… | func | 调用静态函数 | |
invoke-interface-nofix | argcnt | arg… | func | 调用接口函数 | |
invoke-native-nofix | argcnt | arg… | func | 调用C语言函数 |
文本格式:op argcnt,start, end,func
助记符 | 操作码 | 参数个数 | 起始寄存器 | 结束寄存器索引 | 函数 | 注解 |
---|---|---|---|---|---|---|
8 bit | 8 bit | 16 bit | 16 bit | 32 bit | ||
invoke-virtual-range | argcnt | arg… | func | 调用虚函数 | ||
invoke-direct-range | argcnt | arg… | func | 直接调用函数 | ||
invoke-static-range | argcnt | arg… | func | 调用静态函数 | ||
invoke-interface-range | argcnt | arg… | func | 调用接口函数 | ||
invoke-native-range | argcnt | arg… | func | 调用C语言函数 |
文本格式:op des
助记符 | 操作码 | 对齐 | 源寄存器 | 注解 |
---|---|---|---|---|
8 bit | 8 bit | 指令宽度: 16 bit | ||
get-result-w32-I8 | des | 获取32位返回值 | ||
get-result-w64-I8 | des | 获取64位返回值 | ||
get-result-obj-I8 | des | 获取对象返回值 | ||
8 bit | 8 bit | 16 bit | 指令宽度: 32 bit | |
get-result-w32-I16 | des | 获取32位返回值 | ||
get-result-w64-I16 | des | 获取64位返回值 | ||
get-result-obj-I16 | des | 获取对象返回值 |
文本格式:op des
助记符 | 操作码 | 对齐 | 源寄存器 | 注解 |
---|---|---|---|---|
8 bit | 8 bit | 指令宽度: 16 bit | ||
get-exception-I8 | des | 获取异常对象 | ||
throw-I8 | src | 抛出异常对象 | ||
8 bit | 8 bit | 16 bit | 指令宽度: 32 bit | |
get-exception-I16 | des | 获取异常对象 | ||
throw-I16 | src | 抛出异常对象 |
本章节描述的是作者按照 RISC 指令系统设计的虚拟机指令集。
其类似与硬件指令集,可作为编译器后端指令系统目标,用于提供类似硬件指令系统环境,避免编译原理初学者陷入对硬件指令系统不了解的深渊。 降低学习难度,提高学习效率。
这类指令的主要特点如下:
虚拟机的寄存器分为三种:
每条指令是 32bit 大小对齐的,其中最低 9bit 是操作码,其余23bit作为操作数或者操作码的补充。如下表所示:
操作码 | 操作数 |
---|---|
9 bit | 23 bit |
操作码 | 操作数 |
---|---|
9 bit | 23 bit |
多数指令使用此格式。
操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
该格式主要用于比较指令后的三元选择赋值操作。
操作码 | 目的操作数 | 源操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 5 bit | 3 bit |
当指令中需要使用立即数时,且在指令中没有足够的空间可以存储时,可以使用指令后跟32bit对齐的立即数操作数。
格式如下所示:
指令 | 立即数 1 | 立即数 2 | … | 立即数 n |
---|---|---|---|---|
32 bit | 32 bit | 32 bit | … | 32 bit |
空指令一般用于对齐,在本指令集中没有特殊含义,执行空操作。
格式如下:
助记符 | 操作码 | 操作数 |
---|---|---|
9 bit | 23 bit | |
Nop | 0 | 0 |
算术运算包含 +、-、*、/、%,支持的运算类型有 int32、uint32、int64、uint64、flt32、flt64。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
add-i32 | des | src | src2 | ||
sub-i32 | des | src | src2 | ||
mul-i32 | des | src | src2 | ||
div-i32 | des | src | src2 | ||
mod-i32 | des | src | src2 | ||
add-u32 | des | src | src2 | ||
sub-u32 | des | src | src2 | ||
mul-u32 | des | src | src2 | ||
div-u32 | des | src | src2 | ||
mod-u32 | des | src | src2 | ||
add-i64 | des | src | src2 | ||
sub-i64 | des | src | src2 | ||
mul-i64 | des | src | src2 | ||
div-i64 | des | src | src2 | ||
mod-i64 | des | src | src2 | ||
add-u64 | des | src | src2 | ||
sub-u64 | des | src | src2 | ||
mul-u64 | des | src | src2 | ||
div-u64 | des | src | src2 | ||
mod-u64 | des | src | src2 | ||
add-f32 | des | src | src2 | ||
sub-f32 | des | src | src2 | ||
mul-f32 | des | src | src2 | ||
div-f32 | des | src | src2 | ||
add-f64 | des | src | src2 | ||
sub-f64 | des | src | src2 | ||
mul-f64 | des | src | src2 | ||
div-f64 | des | src | src2 |
位运算包括位相关的与、或、非、异或、移位、取反等运算。
支持的运算类型有 uint32、uint64。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
sl-i32 | des | src | src2 | ||
sr-i32 | des | src | src2 | ||
sra-i32 | des | src | src2 | ||
and-i32 | des | src | src2 | ||
or-i32 | des | src | src2 | ||
xor-i32 | des | src | src2 | ||
andn-i32 | des | src | src2 | ||
orn-i32 | des | src | src2 | ||
xorn-i32 | des | src | src2 | ||
not-i32 | des | src | src2 | ||
sl-i64 | des | src | src2 | ||
sr-i64 | des | src | src2 | ||
sra-i64 | des | src | src2 | ||
and-i64 | des | src | src2 | ||
or-i64 | des | src | src2 | ||
xor-i64 | des | src | src2 | ||
andn-i64 | des | src | src2 | ||
orn-i64 | des | src | src2 | ||
xorn-i64 | des | src | src2 | ||
not-i64 | des | src | src2 |
逻辑比较运算包括:<、>、<=、>=、==、!=、 ==0、!=0. 支持的运算类型有 int32、uint32、int64、uint64、flt32\flt64。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
cmp-i32 | des | src | src2 | ||
cmp-u32 | des | src | src2 | ||
cmp-i64 | des | src | src2 | ||
cmp-u64 | des | src | src2 | ||
cmp-f32 | des | src | src2 | ||
cmp-f64 | des | src | src2 |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|---|---|
lt | < | |
le | <= | |
gt | > | |
ge | >= | |
eq | == | |
ne | != | |
ez | ==0,此时没有源操作数src2 | |
nz | !=0,此时没有源操作数src2 |
当不使用操作子码,而是使用下面方式运算:
条件赋值指令使用比较指令的结果,对另外 2 个源操作数进行选择,传递个目标操作数。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 5 bit | 3 bit | |
sel-i32 | des | src | src2 | cond | ||
sel-u32 | des | src | src2 | cond | ||
sel-i64 | des | src | src2 | cond | ||
sel-u64 | des | src | src2 | cond | ||
sel-f32 | des | src | src2 | cond | ||
sel-f64 | des | src | src2 | cond |
当比较系列指令使用操作子码方式时:
当比较系列指令不使用操作子码方式时,本系列指令要求使用操作子码进行判断:
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|---|---|
lt | < :des = cond == -1 ? src : src2 | |
le | <= :des = cond < 1 ? src : src2 | |
gt | > :des = cond == 1 ? src : src2 | |
ge | >= :des = cond > -1 ? src : src2 | |
eq | == :des = cond == 0 ? src : src2 | |
ne | != :des = cond != 0 ? src : src2 |
此系列包括寄存器间赋值或类型转换。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
mov | des | src |
操作子码用于获取源操作数并转换到响应的类型。
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|---|---|
i8-i32 | ||
u8-i32 | ||
i8-i64 | ||
u8-u64 | ||
i16-i32 | ||
u16-i32 | ||
i16-i64 | ||
u16-i64 | ||
i32_i32 | ||
i32-i64 | ||
i32-f32 | ||
i32-f64 | ||
u32-u32 | ||
u32-u64 | ||
u32-f32 | ||
u32-f64 | ||
i64-i64 | ||
i64-f32 | ||
i64-f64 | ||
u64-u64 | ||
u64-f32 | ||
u64-f64 | ||
f32-i32 | ||
f32-u32 | ||
f32-i64 | ||
f32-u64 | ||
f32-f32 | ||
f32-f64 | ||
f64-i32 | ||
f64-u32 | ||
f64-i64 | ||
f64-u64 | ||
f64-f32 | ||
f64-f64 | ||
f32-bit-u32 | 位转换 | |
u32-bit-f32 | 位转换 | |
f64-bit-u64 | 位转换 | |
u64-bit-f64 | 位转换 |
此系列指令功能是从内存中读取、存储特定类型数据。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 | 注释 |
---|---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | ||
load | des | base | offset | 从基址内存中获取数据 | ||
store | des | base | offset | |||
gload | des | base | offset | 从全局内存中获取数据 | ||
gstore | des | base | offset |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|---|---|
i8 | ||
u8 | ||
i16 | ||
u16 | ||
i32 | ||
u32 | ||
i64 | ||
u64 | ||
f32 | ||
f64 |
此系列指令用于将数据入栈,同时可以进行类型转换。 注意:入栈数据应当进行 32bit 对齐。以加快虚拟机执行速度数据
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
push | des | ||||
pop | des | ||||
操作子码定义如下: | |||||
助记符 | 操作码 | 含义 | |||
— | — | — | |||
i8 | |||||
u8 | |||||
i16 | |||||
u16 | |||||
i32 | |||||
u32 | |||||
i64 | |||||
u64 | |||||
f32 | |||||
f64 |
此系列指令用于栈内存分配释放。 注意:立即数是无符号整数。
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|---|---|---|---|
9 bit | 5 bit | 18 bit | ||
grown | des | imm | 分配栈内存,将分配后的栈指针值传递到 des 寄存器 | |
9 bit | 23 bit | 释放栈内存, | ||
shrunk | imm |
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|---|---|---|---|
9 bit | 23 bit | |||
jmp | imm | 直接跳转 | ||
9 bit | 5 bit | 18 bit | ||
jmpx | reg | 偏移量在 reg 寄存器中 | ||
9 bit | 5 bit | 18 bit | ||
jtab | reg | imm | reg 表示偏移量索引,imm表示偏移量数组中偏移数据条数,指令后面接 32 bit 对齐的偏移量数组 |
此系列指令用于条件分支跳转。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 | 偏移立即数 |
---|---|---|---|---|---|---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit | 32 bit | |
jbr-i32 | src | src2 | cond | offset | ||
jbr-u32 | src | src2 | cond | offset | ||
jbr-i64 | src | src2 | cond | offset | ||
jbr-u64 | src | src2 | cond | offset | ||
jbr-f32 | src | src2 | cond | offset | ||
jbr-f64 | src | src2 | cond | offset |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|---|---|
lt | < | |
le | <= | |
gt | > | |
ge | >= | |
eq | == | |
ne | != | |
ez | ==0,此时没有源操作数src2 | |
nz | !=0,此时没有源操作数src2 |
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|---|---|---|---|
9 bit | 23 bit | 32 bit | ||
call | imm | imm表示函数的偏移量或者是编号,看虚拟机的具体实现 | ||
9 bit | 5 bit | 18 bit | ||
callx | reg | reg 寄存器中保存函数的偏移量或者是编号,看虚拟机的具体实现 | ||
9 bit | 23 bit | |||
ret | 函数返回 |
待续
air语言是C语法系的编程语言,提供面向对象、函数式、模板等高级语言功能。
语法使用非严格的EBNF语法描述。
文件单元
FileUnit = PkgDef (ImportDef) Decl*
包定义
PkgDef = package ID (.ID)*
依赖导入(可选)
ImportDef = 'import' STRING as ID; |'{' (STRING as ID; )* '}'
声明定义
Decl = ScopeDecl | VarDecl | FuncDecl | EnumDecl | StructDecl | UnionDecl | InterfaceDecl | ClassDecl | EntrustDecl | ~
表达式
Exp = BaseExp | DotExp | UnaryExp | BinaryExp | TernaryExp | NewExp | PriorityExp
基础表达式
BaseExp = IDExp | ConstExp | CallExp | ArrarExp | ThisExp | SuperExp
IDExp = ID
ConstExp = c
CallExp = ID '(' ArgList')'
ArrarExp = ID '[' Exp ']'
ThisExp = 'this'
SuperExp = 'super'
成员访问表达式
DotExp = BaseExp ( '.' BaseExp)* //BaseExp不得是ConstExp
一元表达式
UnaryExp = UnaryOP BaseExp
UnaryOP = '-' | '+' | '--' | '++' | '~' | '!'
二元表达式
BinaryExp = Exp BinaryOP Exp
BinaryOP = '+' | '-' | '*' | '/' | '%' |
'&' | '|' | '&&' | '||' |
'<<' | '>>' | '>>>' |
'<' | '>' | '<=' | '>=' |
'==' | '!=' | '=' |
三元表达式
TernaryExp = Exp '?' Exp ':' Exp
括号表达式
PriorityExp = '(' Exp ')'
作用域声明
ScopeDecl = ( 'public' | 'protected' | 'private' ) ':'
变量声明
VarDecl = Scope Type 'id' [=initExp] ';'
Scope = ['public' | 'protected' | 'private'| 'extern' | 'static']
Type = ['const' ] 'id'( '.' 'id')*
代理变量
Scope Type 'id''(' [ arglist] ')' 'delegate' ';'
闭包变量
Scope Type 'id''(' [ arglist] ')' 'closure' ';'
函数申明
VarDecl = Scope Type 'id''(' [ arglist] ')'[@override] [@cfun] [const] [final] (';' | funbody )
arglist = argitem (',' argitem)*
argitem = type ['id']
funbody = BlkState
BlkState = '{' [Statement] '}'
Statement = ( BlkState | ExpState | IfState | ElseifState |
ElseState | SwitchState | ForState | DoState |
WhileState | GotoState | BreakState | ContinueState |
ReturnState )*
TypeDecl = EnumDecl | StructDecl | UnionDecl |EntrustDecl
FuncDecl = Type 'id''(' [ arglist] ')' '=' Serial
Serial = 'u32'
枚举声明
EnumDecl = 'enum' id [: BaseType]'{' EnumItem* '}'
BaseType = 基本整数类型
EnumItem = 'id'[=initExp] ','
每一个文件都必须定义一个作用域名,其他内容在此作用域定义。
生成的声明符号都在该作用域内,只能通过该作用域才能访问代码文件中声明的符号内容。
package pkg.pkg2;
Import file=“dir/file.ext”;
Import file2=“dir/file2.ext”;
或者
Import{
file=“dir/file.ext” ;
file2=“dir/file2.ext”;
}
enum name : int32{
item=0,
item2=23,
…
}
Struct name{
Int32 i32;
Union{
Int32 s32;
Flt32 f32;
}
}
Union name{
Int32 s32;
Flt32 f32;
Struct{…}
}
Interface IFather{
void eat(int32 arg);
}
Interface IFather2{
void say(int32 arg);
}
Interface IChild :[ IFather,IFather2 ]{
void walk(int32 arg);
}
Class Parent {
Private:
Int32 mI32;
Public Flt32 mF32;
Public:
Void print(){}
Protected void toString(){}
Virtual void vfun()=0;
}
Class child: Parent :[ IChild ]{
void eat(int32 arg) @override{}
void say(int32 arg) @override{}
void walk(int32 arg) @override{}
void vfun()@override{}
}
airlang 的关键字分为两种:普通关键字,宏关键字。 两者差别不大,但是宏关键字有特殊的标记作用,一般用于注解一些信息。
关键字 | 注解 |
---|---|
@file | 代码中获取文件的名称字符串 |
@line | 代码中获取代码所作行号数字 |
@func | 代码中获取函数声明字符串 |
@debug | 用于标记只在debug标志下启用的代码 |
@NotNulptr | 用于标记需要检查函数的指针参数非空 |
@override | 标记非静态成员函数是重写父类的函数 |
固定位宽类型关键字 | 注解 | 位宽(bit) |
---|---|---|
void | 空,一般用于表示无返回值 | 0 |
bool | 布尔类型 | 8 |
flt32 | 32位单精度浮点 | 32 |
flt64 | 64位双精度浮点 | 32 |
int8 | 8位有符号整数 | 8 |
int16 | 8位有符号整数 | 16 |
int32 | 8位有符号整数 | 32 |
int64 | 8位有符号整数 | 64 |
uint8 | 8位无符号整数 | 8 |
uint16 | 16位无符号整数 | 16 |
uint32 | 32位无符号整数 | 32 |
uint64 | 64位无符号整数 | 64 |
char | 字符 | 8 |
可变位宽类型的位宽由编译的目标CPU架构有关。
可变位宽类型关键字 | 注解 | CPU32 | CPU64 |
---|---|---|---|
sint | 有符号整数 | 32 | 64 |
uint | 无符号整数 | 32 | 64 |
uintptr | 指针 | 32 | 64 |
cstring | 字符串指针 | 32 | 64 |
修饰关键字 | 注解 |
---|---|
static | 静态 |
public | 完全公开的 |
protected | 对部分成员公开的 |
private | 私有的 成员 |
const | 常量化,只读 |
friend | 友元定义 |
分支关键字 | 注解 |
---|---|
if | 比较分支 |
elsif | 次比较分支 |
else | 比较默认分支 |
for | 循环 |
foreach | 循环 |
while | 循环 |
do | 循环 |
break | 跳出循环 |
continue | 继续下一轮循环 |
goto | 跳转到标签 |
return | 函数返回 |
类型定义关键字 | 注解 |
---|---|
enum | 枚举 |
struct | 结构体 |
union | 联合体 |
interface | 接口 |
class | 类 |
entrust | 委托指针 |
其他关键字 | 注解 |
---|---|
false | |
true | |
nullptr | |
this | |
super |
成员访问操作符的优先级最高。
成员访问操作符 | 优先级 | 注解 |
---|---|---|
. | 0 | 成员访问 |
.? | 0 | 带null检查的成员访问 |
一元操作符优先级一致,主要查看其声明的先后顺序。
一元操作符 | 优先级 | 注解 |
---|---|---|
~ | -10 | 按位取反 |
! | -10 | 逻辑取反 |
- | -10 | 符号取反 |
+ | -10 | 取绝对值 |
++ | -10 | 自增 |
-- | -10 | 自减 |
在语法解析表达式中,二元表达式最复杂的。
二元操作符 | 优先级 | 注解 |
---|---|---|
* | -20 | 乘运算操作符 |
/ | -20 | 除运算操作符 |
% | -20 | 模运算操作符 |
+ | -30 | 加运算操作符 |
- | -30 | 减运算操作符 |
<< | -40 | 左移操作符 |
>> | -40 | 逻辑右移操作符 |
>>> | -40 | 算术右移操作符 |
< | -50 | 小于操作符 |
<= | -50 | 小于等于操作符 |
> | -50 | 大于于操作符 |
>= | -50 | 大于等于操作符 |
== | -60 | 等于操作符 |
!= | -60 | 不等于操作符 |
& | -70 | 位与操作符 |
^ | -71 | 位异或操作符 |
| | -72 | 位或操作符 |
&& | -80 | 逻辑与操作符 |
|| | -81 | 逻辑或操作符 |
三元操作符主要用于比较赋值、简单的比较分支操作。
三元操作符 | 优先级 | 注解 |
---|---|---|
? : | -90 |
赋值类操作符的优先级一致,优先级最低。
赋值操作符 | 优先级 | 注解 |
---|---|---|
= | -100 | 赋值操作符 |
*= | -100 | 乘运算复合赋值操作符 |
/= | -100 | 除运算复合赋值操作符 |
%= | -100 | 模运算复合赋值操作符 |
+= | -100 | 加运算复合赋值操作符 |
-= | -100 | 减运算复合赋值操作符 |
&= | -100 | 位与运算复合赋值操作符 |
= | -100 | 位或运算复合赋值操作符 |
^= | -100 | 位异或运算复合赋值操作符 |
~= | -100 | 位取反运算复合赋值操作符 |
<<= | -100 | 左移运算复合赋值操作符 |
>>= | -100 | 逻辑右移运算复合赋值操作符 |
>>>= | -100 | 算术右移运算复合赋值操作符 |
括号表达式中的括号操作符,用于提升表达式的优先级,在算符优先解析算法,该系列是作为基本表达式进行解析的。
括号操作符 | 优先级 | 注解 |
---|---|---|
() | -10 | 括号操作符 |
[] | -10 | 数组下标 |
cast | -10 | 静态类型转换 |
dyn_cast | -10 | 动态类型转换 |
() | -10 | 函数调用 |
固定位宽类型 | 注解 | 位宽(bit) |
---|---|---|
void | 空,一般用于表示无返回值 | — |
bool | 布尔类型 | 8 |
flt32 | 32位单精度浮点 | 32 |
flt64 | 64位双精度浮点 | 32 |
int8 | 8位有符号整数 | 8 |
int16 | 8位有符号整数 | 16 |
int32 | 8位有符号整数 | 32 |
int64 | 8位有符号整数 | 64 |
uint8 | 8位无符号整数 | 8 |
uint16 | 16位无符号整数 | 16 |
uint32 | 32位无符号整数 | 32 |
uint64 | 64位无符号整数 | 64 |
char | 字符 | 8 |
可变位宽类型的位宽由编译的目标CPU架构有关。
可变位宽类型 | 注解 | CPU32 | CPU64 |
---|---|---|---|
sint | 有符号整数 | 32 | 64 |
uint | 无符号整数 | 32 | 64 |
uintptr | 指针 | 32 | 64 |
cstring | 字符串指针 | 32 | 64 |
枚举定义只能是定义整数类的值,其占用的字节数、有无符号性,通过基类标识指定。
如下所示:
enum Color:uint32{
Red,
Black,
}
结构体在airlang中是值类型,不会进入GC系统,除通过API分配独立的堆内存。
一般用于构成类中的共同属性。
struct Vec2{
int32 x;
int32 y;
}
struct Vec3 :Vec2{
int32 z;
}
union Int32{
int32 i32;
struct{
int8 [4] v4;
}
}
interface IEvent{
void eat();
}
class Parent{
int32 i32;
void doing(){}
}
class Child :Parent <IEvent>{
int64 i64;
void eat()@override{}
}
entrust Func = void (int32,int64)@clang;