Page 138 - 《软件学报》2025年第8期
P. 138

于涛 等: 基于下推自动机的同步数据流语言可信编译                                                       3561


                 名流, 而非将   A  的流改变为   ck.
                    表  4  为  3  个时钟算子的目标码模式. 其中     when  运算符的目标码为第       1  个表达式的值, 因为    when  运算符在表
                 达式中不改变目标码, 仅告知编译器流的时钟即可. current 运算符在时钟为                   false 时返回上一个有效的值, 因此依
                 赖于先前周期的信息, 所以目标码和时态算子一样, 使用辅助函数和上下文结构体的方式实现. merge 运算符将多
                 个互补的流融合为一个流, 因此每个周期都有一个有效值, 不依赖于先前周期.

                                                  表 4 时钟算子目标码模式

                     产生式左部                  产生式右部                               目标码模式
                                       <Expression> when <Expression>            <Expression>
                     Expression            current <Expression>      current_function(<Expression>, <Expression>, ctx)
                                        merge <Lv6Id> <Mergecaselist>     switch(<Lv6Id>) {< Mergecaselist>}

                    以  merge 运算符为例, <Mergecaselist> 在  merge 产生式的转换中不做处理, 交由<Mergecaselist> 产生式转换,
                 其产生式和目标码模式如表          5  所示, 本质上是填补了     C  语言  switch  语句中  case 的部分.

                                                表 5 merge 运算符目标码模式

                       产生式左部                    产生式右部                             目标码模式
                                            <MergeCase> <Mergecaselist>       <MergeCase> <Mergecaselist>
                      Mergecaselist               <MergeCase>                       <MergeCase>
                                                    empty                               -
                                              (Lv6Id → <Expression>)       case Lv6Id: temp = <Expression>; break;
                       MergeCase               (true → <Expression>)        case true: temp = <Expression>; break;
                                               (false → <Expression>)       case false: temp = <Expression>; break;

                 3.3   C  代码生成
                    代码生成的过程大致可分为           3  个步骤: (1) 通过下推自动机识别算法对程序进行识别的同时生成                 Lustre 程序
                 的目标码; (2) 生成  Lustre 程序所有节点和辅助函数、结构体的目标码; (3) 生成             C  目标代码主循环.
                    在目标码转换模式和下推自动机的基础上, 将目标码转换模式拆解为具体的转换动作, 即每个下推自动机识
                 别过程中的状态转移动作需要执行的转换动作. 随后将转换动作嵌入到下推自动机识别算法当中, 在识别的同时
                 就完成了   Lustre 源程序的转换.
                    表  6  以伪代码形式展示了      Lustre 程序与  C  程序的对应关系, Lustre 程序主要由     node 组成, 每一个   node 对应
                 于  C  程序中的一个函数. 由于     Lustre 的输入参数与输出参数可能不止一个值, 因此在              C  程序中使用输入和输出结
                 构体来描述各个参数的类型. <expr> 表达式由算术和逻辑表达式, 条件表达式, 时态表达式, 节点调用组成; 分别
                 对应于   C  语言中的算术和逻辑表达式, 条件表达式, 条件表达式, 函数调用.

                                               表 6 Lustre 程序及对应的     C  程序

                                      Lustre程序                       Lustre程序对应的C程序
                                                                   typedef struct{
                                                                       paraType para1;
                                                                       paraType para2;
                                   node function(para1,
                                                                   }function_in;
                                   para2:paraType)
                                                                   typedef struct{
                                   returns(retPara1,
                                                                       retType retPara1;
                                   retPara2:retType)
                                                                       retType retPara2;
                                   let
                                                                   }function_out;
                                       <expr1>
                                                                   void function(function_in *in, function_out
                                       <expr2>
                                                                   *out){
                                       <expr3>
                                                                       <expr1>
                                   tel
                                                                       <expr2>
                                                                       <expr3>
                                                                   }
   133   134   135   136   137   138   139   140   141   142   143