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;