一种具有轻量级比较指令生成的编译方法
技术领域
本发明涉及编译器领域一种比较指令生成方法,涉及到编译器的前端语法树的生成,中端语法树到中间代码的翻译,和后端的代码生成部分,即涉及到生成语法树阶段,生成中间代码阶段和生成汇编码阶段。
背景技术
编译器是开发人员编写程序的工具,它将开发人员编写的高级语言程序转换成低级的汇编语言。在转换过程中,一个重要的组成部分就是对比较指令的生成。
在用户程序中,比如用C语言编写的程序,经常会使用if-then-else或者a>b?a:b等语句,这些就是比较指令。在编译器中,将比较指令转换为比较指令的判断语句,后面跟着比较判断指令的true分支语句和false分支语句,然后翻译成对应的汇编语句。生成汇编指令之后,判断语句在芯片上执行时,由硬件判断比较结果,并根据结果确定程序执行true分支语句还是false分支语句。
编译器从结构上分为前端、中端和后端,阶段划分构成如图1。前端主要是命令行参数处理阶段,词法分析阶段和语法分析阶段,前端生成语法树作为输出,提供给中端作为输入。中端包括生成中间代码阶段和对中间代码进行优化阶段,中端生成优化的中间代码作为输出,提供给后端作为输入。后端包括,生成汇编码阶段,它将中间代码翻译成汇编指令。这样编译器就完成了将程序员写的高级语言转换为汇编语言的功能。
本专利主要在编译器的前端、中端和后端针对比较指令的生成方法作优化。在编译器中比较指令分为大于、小于、大于等于、小于等于、等于和不等于这六大类。
在目标机的汇编语言中,比较指令对应的汇编指令只能进行两边都是有符号或者都是无符号的比较。但是在程序员写的高级语言程序中,不只都是有符号数与有符号数比较,或者无符号数与无符号数比较,还有可能有符号数与无符号数比较。这样当高级语言程序中,有符号数与无符号数比较时,在他们的高位为1时,无论是翻译成无符号比较汇编指令,还是翻译成有符号比较汇编指令都有可能出错。例如,有符号的0x82与无符号的0x80相比,应该左边有符号的0x82小于右边无符号的0x80,无论翻译成有符号的比较指令,还是翻译成无符号的比较指令,都出错。这样就需要判断比较指令的两边变量或者常量的高位是否为1.,记录这些信息,在比较时依据这些信息和符号信息来判断比较指令的结果。
有些编译器中,会将变量或者常量进行隐式转换,作扩展,比如8位的扩展成16位来比较,这样就不存在上面的问题了,但这样会增加一些隐式转换的指令。
如果用指令来显式的判断变量或者常量高位是否为1,比如增加指令cmp.w R0,#0来判断高位是否为1,这样能保证比较指令的正确性,但会大大的增加指令的条数,因为每次比较都要进行这样的判断。
发明内容
本发明目的在于在编译器中既保证比较指令生成的正确性,又使生成的汇编代码条数尽可能的少。本发明的目的通过以下步骤实现:将程序命令行参数进行处理;将进行命令行参数处理后的程序进行语言预处理;将进行语言预处理后的程序进行词法分析;将进行词法分析后的程序进行语法分析;将进行语法分析后的程序生成语法树;生成中间代码步骤;将中间代码进行优化并生成汇编码。其中在生成语法树步骤赋值语句中记录变量高位是否为1的状态,并在生成语法树和生成中间代码步骤中通过数据流进行传播,在生成汇编码步骤生成比较指令时,判断变量的高位是否为1,并据此进行优化的比较指令生成。在生成语法树阶段在赋值语句中记录高位是否为1,步骤如下:
(1)如果赋值语句中右边是常数,则根据左边的变量类型,判断右边常数的高位是否为1,分别记录这两种状态。如果左边的变量为char型,且不是指针,则右边的常数与0×80相或之后不为0,则高位是1,并记录状态,否则高位不是1,也记录此时的状态。如果左边的变量为int型或者short型,且不是指针,则右边的常数与0×8000相或之后不为0,则高位是1,并记录状态,否则高位不是1,也记录此时的状态。如果左边的变量为long型或者指针类型,则右边的常数与0×80000000相或之后不为0,则高位是1,并记录状态,否则高位不是1,也记录此时的状态。左边的变量不为标量时,比如数组或者结构型变量,通过遍历语法树,获取此变量的最外围的变量,a.asub.b[4]的最外围变量为a
(2)(2)如果赋值语句右边不是常数,赋值语句左边的状态等于赋值语句右边的高位的状态。在生成语法树和生成中间代码阶段通过数据流进行传播,步骤如下
(1)在生成语法树阶段,除了赋值操作,设置其他操作的返回值的类型的高位的状态。比如加法操作,结果值的高位状态不确定是否为1,则记录此时状态为不确定。如果是逻辑非操作,结果值为char型,高位确定不为1,并记录此时的状态。
(2)在生成中间代码阶段,在语法树翻译到中间代码的过程中,对于结构体操作或者数 组操作的翻译时,传播高位的状态。这是因为标量的高位状态通过该标量对应的符号和语法树来传播,非标量的结构体或者数组就需要在转换时,将高位的状态传播给非标量的最外围的变量。
(3)进行传播的原因是步骤1只是记录了赋值语句中左边变量的高位的状态,其他语句中引用此变量时,就需要此变量的状态记录并加以传播,才能识别变量的高位的状态。
在生成汇编码阶段,生成比较指令的流程如图3。
如果当前中间代码的左树或者右树高位为1时,通过后向的数据流分析,确定其高位是否为1。因为本方法中记录的高位状态是离当前比较指令最近的变量的状态,比如a与3比较大小,a的状态是离当前比较指令最近的对a的赋值的状态,但是这条赋值语句,不一定一定走到,所以需要通过后向的数据流判断来确定其高位是否是1。如果高位确定为1,则生成优化的比较指令,因为高位为1,很多情况下可以直接判定比较指令的结果,比如有符号类型的a高位为1,与一个无符号数比较时,一定是小于。又比如无符号类型的a高位是1,与一个有符号数比较时,一定是大于。如果高位不确定是1,则按照常规的比较指令规则,生成比较指令。
附图说明
图1编译器阶段划分构成图
图2比较指令生成流程图
图3生成汇编码阶段比较指令生成流程图
具体实施方式
实现本发明需要先建立数据结构,表示变量高位是否为1的状态,该状态值为1时,表示高位确定为1,状态值为2时,表示高位确定不为1,状态值为0时,表示高位不确定是否为1。
实现本发明,还需要建立变量与icode(本编译器中的中间代码的数据结构)的映射关系,原来一个变量在程序中的所有出现都对应于一个icode,要改为变量的每次出现对应一个新的icode,即多对一,变为一对一。
建立了适当的数据结构之后,就可以参照本发明附图中的流程,在编译器中实现轻量级的比较指令生成方法。包括以下步骤:
将程序命令行参数进行处理步;将进行命令行参数处理后的程序进行预处理;将进行语言预处理后的程序进行词法分析、语法分析;将进行词法分析、语法分析后的程序生成语法树;生成中间代码步骤;将中间代码进行优化并生成汇编码;其中在生成语法树步骤赋值语句中记录变量高位是否为1的状态,包括以下步骤:
(1)如果赋值语句中右边是常数,则根据左边的变量类型,判断右边常数的高位是否为1,分别记录这两种状态。
(2)如果赋值语句右边不是常数,赋值语句左边的状态等于赋值语句右边的高位的状态。在生成语法树和生成中间代码步骤中通过数据流进行传播,包括以下步骤:
(1)在生成语法树步骤中,除了赋值操作,设置其他操作的返回值的类型的高位的状态。
(2)在生成中间代码步骤中,语法树翻译到中间代码的过程中,传播高位的状态。在生成比较指令时,判断变量的高位是否为1,并据此进行优化的比较指令生成。如果当前中间代码的左树或者右树高位为1,通过后向的数据流分析,确定其高位是否为1,如果高位为1,则生成优化的比较指令;否则,按照常规的比较指令规则,生成比较指令。
本发明适用于嵌入式处理器上的编译器,简单高效,易于实现。一般的编译器中比较指令生成方法中或者采用显式插入比较汇编指令,或者对变量进行扩展的方式实现,这两种方法的缺点是生成的汇编代码的条数较多。由于本编译器面向嵌入式处理器,cos(智能卡操作系统)程序比较指令比较多,对代码条数要求较高,因此本发明具有简单高效的特点。