<ul><li>语义分析与中间代码生成 </li></ul>第八讲
<ul><li>语义分析和中间代码生成在编译程序中的 </li></ul><ul><li>逻辑位置 </li></ul>语义分析与中间代码生成 词法分析 语法分析 中间代码生成 中间代码优化 目标代码优化 目标代码生成 静态语义分析 语义处理
<ul><li>语义分析和中间代码生成的重要数据结构 </li></ul><ul><li>符号表 ( symbol tables )  </li></ul><ul><ul><li>名字信息建立后加入 / 更改符号表   </li></ul></...
<ul><li>语义分析 </li></ul><ul><li>中间代码生成 </li></ul>语义分析与中间代码生成
<ul><li>与语义分析相关的工作 </li></ul>语义分析 <ul><li>静态语义检查 </li></ul><ul><ul><li>编译期间所进行的语义检查  </li></ul></ul><ul><li>动态语义检查 </li></...
<ul><li>静态语义检查 </li></ul><ul><li>代码生成前程序合法性检查的最后阶段 </li></ul><ul><ul><li>静态 类型检查 ( type checks )  </li></ul></ul><ul><ul><...
<ul><li>类型检查程序 ( type checker )负责类型检查 </li></ul><ul><ul><li>验证语言结构是否匹配上下文所期望的类型 </li></ul></ul><ul><ul><li>为相关阶段搜集及建立必要的类型...
<ul><li>类型表达式 ( type expressions ) </li></ul><ul><ul><li>由 基本类型 , 类型名字 , 类型变量 ,及 类型构 </li></ul></ul><ul><ul><li>造子 ( type ...
<ul><li>某个类型表达式集合(将用于示范类型检查 </li></ul><ul><li>程序的设计)归纳定义如下: </li></ul><ul><ul><li>基本类型  bool ,   char ,  int ,  real ,  ty...
<ul><li>以下是定义某个简单语言的上下文无关文法 </li></ul><ul><li>(将用于本讲的设计示例) G [ P ]   : </li></ul><ul><li>一个简单语言 </li></ul>P    D ; S D  ...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>将类型表达式作为属性值赋给程序各个部分 </li></ul></ul><ul><ul><li>设计恰当的翻译模式 </li></ul></ul><ul><ul><li>...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>处理 声明 的翻译模式(保存标识符的类型) </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>P    D ; E D    D...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>表达式 的类型检查 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E     true E     false E    ...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>表达式 的类型检查(续) </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E    E 1   rop   E 2 E    ...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>语句 的类型检查 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>S     id  :=  E S     if  E  t...
<ul><li>语法制导的方法 </li></ul><ul><ul><li>增加数 自动类型转换 ( type casting ) 的支持 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E    E 1...
<ul><li>静态作用域 </li></ul><ul><ul><li>通过符号表实现 </li></ul></ul><ul><ul><li>(已在第七讲讨论) </li></ul></ul><ul><li>动态作用域  </li></ul><...
中间代码生成 <ul><li>源程序的不同表示形式 </li></ul><ul><li>作用 </li></ul><ul><ul><li>源语言和目标语言之间的桥梁,避开二者 </li></ul></ul><ul><ul><li>之间较大的语义...
中间代码生成 <ul><li>有不同层次不同目的之分 </li></ul><ul><li>中间代码举例 </li></ul><ul><ul><li>Postfix ( 后缀式 , 逆波兰式 ) </li></ul></ul><ul><ul><l...
中间代码生成 <ul><li>算术表达式  A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>Postfix (后缀式 , 逆...
中间代码生成 <ul><li>算术表达式  A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>TAC (  Three-add...
中间代码生成 <ul><li>算术表达式  A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>AST ( Abstract s...
中间代码生成 <ul><li>算术表达式  A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>DAG ( Directed A...
中间代码生成 <ul><li>静态单赋值形式 </li></ul><ul><li>中间代码举例 </li></ul>
中间代码生成 <ul><li>语法制导的方法 </li></ul><ul><ul><li>例: 生成抽象语法树 </li></ul></ul><ul><li>中间代码生成 </li></ul>S     id  :=  E S     if...
中间代码生成 <ul><li>顺序的语句序列   其 语句 一般具有如下 形式 </li></ul><ul><li>x := y op z </li></ul><ul><li>( op   为操作符, y   和   z   为操作数,   x...
中间代码生成 <ul><li>课程后续部分用到的  TAC  语句类型 </li></ul><ul><ul><li>赋值语句   x := y op z   ( op  代表二元算术 / 逻辑运算) </li></ul></ul><ul><ul...
中间代码生成 <ul><li>语义属性 </li></ul><ul><ul><li>id . name   :  id   的词法名字(符号表中的名字)  </li></ul></ul><ul><ul><li>E . place   :  用来...
中间代码生成 <ul><li>翻译模式 </li></ul>S     id  :=  E E    E 1  +  E 2   E    E 1      E 2 E    - E 1 E     (  E 1  )  E   ...
中间代码生成 <ul><li>回顾:类型属性的计算 </li></ul><ul><li>说明语句的语法制导翻译 </li></ul>P    D ; E D    D 1  ; D 2 D     id   : T T     char...
中间代码生成 <ul><li>语义属性 </li></ul><ul><ul><li>id . name   :  id   的词法名字(符号表中的名字)  </li></ul></ul><ul><ul><li>T . type   :  类型属...
中间代码生成 <ul><li>过程中说明语句的语法制导翻译 </li></ul><ul><li>翻译模式 </li></ul>P     {  D.offset :=  0  }  D ; E D     { D 1 .offset := ...
中间代码生成 <ul><li>数组说明 </li></ul><ul><li>参考前页的翻译模式,可了解(一维)数组说明的翻译 </li></ul><ul><li>思想 .  至于符号表中一般情况下是如何组织数组说明信 </li></ul><ul...
中间代码生成 <ul><li>数组引用 </li></ul><ul><li>数组说明和数组元素引用的语法制导翻译 </li></ul>S     id  :=  E S    E 1 [ E 2  ]  :=  E 3 E    E 1 ...
中间代码生成 <ul><li>数组的内情向量 ( dove vector ) </li></ul><ul><li>在处理数组时,通常会将数组的有关信息记录在一些单 </li></ul><ul><li>元中,称为“内情向量” .  对于静态数组,...
中间代码生成 <ul><li>数组元素的地址计算   </li></ul><ul><li>例: 对于静态数组  A [ l 1 : u 1 , l 2 : u 2 ,…, l n : u n ]   ,若数组布局采 </li></ul><ul>...
中间代码生成 <ul><li>直接对布尔表达式求值 </li></ul><ul><ul><li>例如   :  可以用数值“ 1 ”  表示  true;  用数值“ 0 ”  表示  false; </li></ul></ul><ul><ul...
中间代码生成 <ul><li>直接对布尔表达式求值 </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E    E 1  or  E 2   E    E 1  and  E 2 E     not  E ...
中间代码生成 <ul><li>通过控制流体现布尔表达式的语义 </li></ul><ul><li>例   :  布尔表达式   E  =  a<b  or  c<d  and  e<f   可能翻译为如 </li></ul><ul><li>下 ...
中间代码生成 <ul><li>翻译布尔表达式至短路代码 </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E    E 1  or  E 2   E    E 1  and  E 2 E     not  ...
中间代码生成 <ul><li>if-then  语句 </li></ul><ul><li>S     if  E  then  S 1   </li></ul><ul><ul><li>{  E.true  :=   newlable; </l...
中间代码生成 <ul><li>if-then-else  语句 </li></ul><ul><li>S     if  E  then  S 1  else  S 2   </li></ul><ul><ul><li>{  E.true  :=...
中间代码生成 <ul><li>循环语句的语法制导翻译 </li></ul><ul><li>while  语句 </li></ul><ul><li>S     while  E  do  S 1 </li></ul><ul><ul><li>{ ...
中间代码生成 <ul><li>复合语句的语法制导翻译 </li></ul><ul><li>顺序复合语句 </li></ul><ul><li>S     S 1  ;  S 2 </li></ul><ul><ul><li>{  S 1 .nex...
中间代码生成 <ul><li>翻译布尔表达式至短路代码(翻译模式) </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E    {  E 1 .true :=  E .true  ; E 1 .false :=...
中间代码生成 <ul><li>if-then  语句(翻译模式) </li></ul><ul><li>S     if  {  E.true  :=   newlable ; E.false  :=  S.next  }  E   </li>...
中间代码生成 <ul><li>if-then-else  语句(翻译模式) </li></ul><ul><li>条件语句的语法制导翻译 </li></ul>E.code S 1 .code E.true: E.false: goto S .ne...
中间代码生成 <ul><li>循环语句的语法制导翻译 </li></ul><ul><li>while  语句(翻译模式) </li></ul>E.code S 1 .code S.begin: E.false: goto S .begin to...
中间代码生成 <ul><li>复合语句的语法制导翻译 </li></ul><ul><li>顺序复合语句(翻译模式) </li></ul><ul><li>S     {  S 1 .next  :=  newlable  }  S 1  ; <...
中间代码生成 <ul><li>拉链与代码回填 ( backpatching ) </li></ul><ul><li>另一种控制流中间代码生成技术 </li></ul><ul><li>比较:前面的方法采用  L - 属性文法 / 翻译模式 </l...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>语义属性 </li></ul><ul><li>E.truelist   :  “ 真链”,链表中的元素表示 一系列跳转语 </li></ul><ul><li>句的...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>语义函数 / 过程 </li></ul><ul><li>makelist(i)   :  创建只有一个结点  i   的表,对应存放目标 </li></ul><u...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理 布尔表达式的翻译模式 </li></ul>E    E 1  or  M   E 2   E    E 1  and  M   E 2 E     n...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理 布尔表达式的翻译模式 </li></ul>E     (  E 1  )  E     id 1  rop  id 2 E     true E  ...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>布尔表达式  E  =  a<b  or  c<d  and  e<f  的翻译 示意 </li></ul>( 0 ) if  a<b  goto  _   or...
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理条件 语句的翻译模式 </li></ul>S     if  E  then  M   S 1   {  backpatch(E .truelist ,M....
中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理循环、复合及其它 语句的翻译模式 </li></ul>S     while  M 1  E  do  M 2   S 1   {  backpatch(S...
中间代码生成 <ul><li>拉链回填技术 示例 </li></ul><ul><li>GOTO  语句的语法制导翻译 </li></ul><ul><li>…… </li></ul><ul><li>(10)   goto   L </li></u...
中间代码生成 <ul><li>拉链回填技术 示例 </li></ul><ul><li>GOTO  语句的语法制导翻译 </li></ul><ul><li>…… </li></ul><ul><li>(10)   goto   L </li></u...
中间代码生成 <ul><li>利用 标号的符号表项维护拉链 </li></ul><ul><ul><li>若采用类似  PL0  的符号表结构,可以设计标号表项包 </li></ul></ul><ul><ul><li>括如下域: </li></u...
中间代码生成 <ul><li>标号 说明和  GOTO  语句的翻译模式 </li></ul><ul><li>GOTO  语句的语法制导翻译 </li></ul>S     id  :  S {  p :=  lookup ( id . na...
中间代码生成 <ul><li>简单 过程调用的翻译 </li></ul><ul><ul><li>示例: 过程调用  CALL S ( A+B,A  B ) </li></ul></ul><ul><ul><li>将被翻译为: </li></ul...
中间代码生成 <ul><li>简单过程调用的 翻译模式 </li></ul><ul><li>过程调用的语法制导翻译 </li></ul>S    call   id   (  L  ) {  S .code :=  L .code ;  fo...
课后作业 1  熟练掌握本讲出现的每个属性文法 / 翻译模式的 设计目的 ,  设计思想和设计技术 <ul><li>参考本讲稿第 39-44 页的 L 属性文法及所用到的语义函数 ,  </li></ul><ul><li>(1)   若在基础文...
课后作业 3   参考本讲稿第 45-49 页的翻译模式及所用到的语义函数 ,  重复  2  中 (1), (2) 的工作。 <ul><li>参考本讲稿第 50-56 页的 S 属性文法 / 翻译模式及所用到 </li></ul><ul><l...
Thank You That’s all for today.
Upcoming SlideShare
Loading in...5
×

Slide08 807007748

120

Published on

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
120
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Slide08 807007748

  1. 1. <ul><li>语义分析与中间代码生成 </li></ul>第八讲
  2. 2. <ul><li>语义分析和中间代码生成在编译程序中的 </li></ul><ul><li>逻辑位置 </li></ul>语义分析与中间代码生成 词法分析 语法分析 中间代码生成 中间代码优化 目标代码优化 目标代码生成 静态语义分析 语义处理
  3. 3. <ul><li>语义分析和中间代码生成的重要数据结构 </li></ul><ul><li>符号表 ( symbol tables ) </li></ul><ul><ul><li>名字信息建立后加入 / 更改符号表 </li></ul></ul><ul><ul><li>名字信息如:种类,类型,偏移地址,占用空间等 </li></ul></ul><ul><ul><li>需要获取名字信息时,查找符号表 </li></ul></ul><ul><ul><li>符号表的组织可以体现名字作用域规则 </li></ul></ul><ul><li>(符号表的组织已在第七讲专门讨论) </li></ul>语义分析与中间代码生成
  4. 4. <ul><li>语义分析 </li></ul><ul><li>中间代码生成 </li></ul>语义分析与中间代码生成
  5. 5. <ul><li>与语义分析相关的工作 </li></ul>语义分析 <ul><li>静态语义检查 </li></ul><ul><ul><li>编译期间所进行的语义检查 </li></ul></ul><ul><li>动态语义检查 </li></ul><ul><ul><li>所生成的代码在运行期间进行的语义检查 </li></ul></ul><ul><li>收集语义信息 </li></ul><ul><ul><li>为语义检查收集程序的语义信息 </li></ul></ul><ul><ul><li>为代码生成等后续阶段收集程序的语义信息 </li></ul></ul><ul><ul><li>有些内容合并到“中间代码生成”部分讨论 </li></ul></ul><ul><ul><li>(如过程、数组声明的语义处理) </li></ul></ul>
  6. 6. <ul><li>静态语义检查 </li></ul><ul><li>代码生成前程序合法性检查的最后阶段 </li></ul><ul><ul><li>静态 类型检查 ( type checks ) </li></ul></ul><ul><ul><li>检查每个操作是否遵守语言类型系统的定义 </li></ul></ul><ul><ul><li>名字的作用域 ( scope ) 分析 </li></ul></ul><ul><ul><li>建立名字的定义和使用之间联系 </li></ul></ul><ul><ul><li>控制流检查 ( flow-of-control checks ) </li></ul></ul><ul><ul><li>控制流语句必须使控制转移到合法的地方(如 break </li></ul></ul><ul><ul><li>语句必须有合法的语句包围它) </li></ul></ul><ul><ul><li>唯一性检查 ( uniqueness checks ) 很多场合要求对 </li></ul></ul><ul><ul><li>象只能被定义一次(如枚举类型的元素不能重复出现) </li></ul></ul><ul><ul><li>名字相关检查 ( name-related checks ) </li></ul></ul><ul><ul><li>(如,一些名字可能被要求配对出现) </li></ul></ul><ul><ul><li>…… </li></ul></ul>语义分析
  7. 7. <ul><li>类型检查程序 ( type checker )负责类型检查 </li></ul><ul><ul><li>验证语言结构是否匹配上下文所期望的类型 </li></ul></ul><ul><ul><li>为相关阶段搜集及建立必要的类型信息 </li></ul></ul><ul><ul><li>实现 某个 类型系统 ( type system ) </li></ul></ul><ul><li>静态类型检查 </li></ul><ul><ul><li>编译期间进行的类型检查 </li></ul></ul><ul><li>动态类型检查 </li></ul><ul><ul><li>目标程序运行期间进行的类型检查 </li></ul></ul><ul><li>类型检查 </li></ul>语义分析
  8. 8. <ul><li>类型表达式 ( type expressions ) </li></ul><ul><ul><li>由 基本类型 , 类型名字 , 类型变量 ,及 类型构 </li></ul></ul><ul><ul><li>造子 ( type constructor )归纳定义的表达式 </li></ul></ul><ul><li>类型系统 ( type systems ) </li></ul><ul><ul><li>将类型表达式赋给程序各个部分的 规则集合 </li></ul></ul><ul><li>类型表达式和类型系统 </li></ul>语义分析
  9. 9. <ul><li>某个类型表达式集合(将用于示范类型检查 </li></ul><ul><li>程序的设计)归纳定义如下: </li></ul><ul><ul><li>基本类型 bool , char , int , real , type_error 和 ok </li></ul></ul><ul><ul><li>是类型表达式(其中, type_error 专用于类型检查 </li></ul></ul><ul><ul><li>时的出错提示; ok 可用于语句的类型检查) </li></ul></ul><ul><ul><li>若 T 是类型表达式,则 array(I,T) 是类型表达式, </li></ul></ul><ul><ul><li>表示元素类型是 T ,下标集合是 I 的数组类型(这 </li></ul></ul><ul><ul><li>里, I 是一个整数区间,如 1..10 ) </li></ul></ul><ul><ul><li>若 T 是类型表达式,则 pointer(T) 是类型表达式, </li></ul></ul><ul><ul><li>表示指向类型为 T 的对象的指针类型 </li></ul></ul><ul><li>类型表达式 举例 </li></ul>语义分析
  10. 10. <ul><li>以下是定义某个简单语言的上下文无关文法 </li></ul><ul><li>(将用于本讲的设计示例) G [ P ] : </li></ul><ul><li>一个简单语言 </li></ul>P  D ; S D  D ; D  id : T T  boolean  char  integer  real  array [ num ] of T   T E  true  false  literal  num  num . num  id  E op E  E rop E  E [ E ]  E  S  id := E  if E then S  while E do S  S ; S 语义分析
  11. 11. <ul><li>语法制导的方法 </li></ul><ul><ul><li>将类型表达式作为属性值赋给程序各个部分 </li></ul></ul><ul><ul><li>设计恰当的翻译模式 </li></ul></ul><ul><ul><li>可实现相应语言的一个类型系统 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>语义分析
  12. 12. <ul><li>语法制导的方法 </li></ul><ul><ul><li>处理 声明 的翻译模式(保存标识符的类型) </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>P  D ; E D  D 1 ; D 2 D  id : T T  boolean T  char T  integer T  real T  array [ num ] of T 1 T   T 1 { addtype ( id . entry , T.type )} { T.type := bool } { T.type := char } { T.type := int } { T.type := real } { T.type := array (1.. num .val, T 1 .type ) } { T.type := pointer ( T 1 .type ) } 语义分析
  13. 13. <ul><li>语法制导的方法 </li></ul><ul><ul><li>表达式 的类型检查 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E  true E  false E  literal E  num E  num . num E  id E  E 1 op E 2 { E.type := bool } { E.type := bool } { E.type := char } { E.type := int } { E.type := real } { E.type := lookup_type ( id . entry ) } { E.type := if E 1 .type = real and E 2 .type = real then real else if E 1 .type = int and E 2 .type = int then int else type_error } 语义分析
  14. 14. <ul><li>语法制导的方法 </li></ul><ul><ul><li>表达式 的类型检查(续) </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E  E 1 rop E 2 E  E 1 [ E 2 ] E  E 1  { E.type := if E 1 .type = real and E 2 .type = real then bool else if E 1 .type = int and E 2 .type = int then bool else type_error } { E.type := if E 2 .type = int and E 1 .type = array(s,t) then t else type_error } { E.type := if E 1 .type = pointer ( t ) then t else type_error } 语义分析
  15. 15. <ul><li>语法制导的方法 </li></ul><ul><ul><li>语句 的类型检查 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>S  id := E S  if E then S 1 S  while E do S 1 S  S 1 ; S 2 { S.type := if lookup_type ( id . entry ) = E.type then ok else type_error } { S.type := if E.type = bool then S 1 .type else type_error } { S.type := if E.type = bool then S 1 .type else type_error } { S.type := if S 1 .type = ok and S 2 .type = ok then ok else type_error } 语义分析
  16. 16. <ul><li>语法制导的方法 </li></ul><ul><ul><li>增加数 自动类型转换 ( type casting ) 的支持 </li></ul></ul><ul><li>类型检查程序的设计 </li></ul>E  E 1 op E 2 E  E 1 rop E 2 { E.type := if E 1 .type = real and E 2 .type = real then real else if E 1 .type = int and E 2 .type = int then int else if E 1 .type = real and E 2 .type = int then real else if E 1 .type = int and E 2 .type = real then real else type_error } { …… } 语义分析
  17. 17. <ul><li>静态作用域 </li></ul><ul><ul><li>通过符号表实现 </li></ul></ul><ul><ul><li>(已在第七讲讨论) </li></ul></ul><ul><li>动态作用域 </li></ul><ul><ul><li>通过运行时活动记录实现 </li></ul></ul><ul><ul><li>(参见下一讲) </li></ul></ul><ul><li>作用域分析 </li></ul>语义分析
  18. 18. 中间代码生成 <ul><li>源程序的不同表示形式 </li></ul><ul><li>作用 </li></ul><ul><ul><li>源语言和目标语言之间的桥梁,避开二者 </li></ul></ul><ul><ul><li>之间较大的语义跨度,使编译程序的逻辑 </li></ul></ul><ul><ul><li>结构更加简单明确 </li></ul></ul><ul><ul><li>利于编译程序的重定向 </li></ul></ul><ul><ul><li>利于进行与目标机无关的优化 </li></ul></ul><ul><li>中间代码 </li></ul>
  19. 19. 中间代码生成 <ul><li>有不同层次不同目的之分 </li></ul><ul><li>中间代码举例 </li></ul><ul><ul><li>Postfix ( 后缀式 , 逆波兰式 ) </li></ul></ul><ul><ul><li>AST ( Abstract syntax tree , 抽象语法树 ) </li></ul></ul><ul><ul><li>TAC ( Three-address code , 三地址码,四元式 ) </li></ul></ul><ul><ul><li>P-code ( 特别用于 Pasal 语言实现 ) </li></ul></ul><ul><ul><li>Bytecode ( Java 编译器的输出 , Java 虚拟机的输入 ) </li></ul></ul><ul><ul><li>SSA ( Static single assignment form , 静态单赋值形式 ) </li></ul></ul><ul><li>中间代码的形式 </li></ul>
  20. 20. 中间代码生成 <ul><li>算术表达式 A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>Postfix (后缀式 , 逆波兰式 ) </li></ul></ul><ul><ul><li>A B C D - * + E C D – N ^ / + </li></ul></ul><ul><li>中间代码举例 </li></ul>
  21. 21. 中间代码生成 <ul><li>算术表达式 A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>TAC ( Three-address code , 三地址码,四元式) </li></ul></ul><ul><li>(1) ( - C D T1 ) T1 := C - D </li></ul><ul><li>(2) ( * B T1 T2) T2 := B * T1 </li></ul><ul><li>(3) ( + A T2 T3) T3 := A + T2 </li></ul><ul><li>(4) ( - C D T4) 或 T4 := C - D </li></ul><ul><li>(5) ( ^ T4 N T5) T5 := T4 ^ N </li></ul><ul><li>(6) ( / E T5 T6) T6 := E / T5 </li></ul><ul><li>(7) (+ T3 T6 T7) T7 := T3 + T6 </li></ul><ul><li>中间代码举例 </li></ul>
  22. 22. 中间代码生成 <ul><li>算术表达式 A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>AST ( Abstract syntax tree , 抽象语法树 ) </li></ul></ul><ul><li>中间代码举例 </li></ul>^ + + / A * E - B D C - D C N
  23. 23. 中间代码生成 <ul><li>算术表达式 A + B * ( C - D ) + E / ( C - D ) ^N </li></ul><ul><li>(中缀形式) </li></ul><ul><ul><li>DAG ( Directed Acyclic Graph , 有向无圈图,改进型 AST ) </li></ul></ul><ul><li>中间代码举例 </li></ul>^ + + / A * E B - D C N
  24. 24. 中间代码生成 <ul><li>静态单赋值形式 </li></ul><ul><li>中间代码举例 </li></ul>
  25. 25. 中间代码生成 <ul><li>语法制导的方法 </li></ul><ul><ul><li>例: 生成抽象语法树 </li></ul></ul><ul><li>中间代码生成 </li></ul>S  id := E S  if E then S 1 S  while E do S 1 S  S 1 ; S 2 E  id E  E 1 + E 2 E  E 1  E 2 E  ( E 1 ) …… { S.ptr := mknode(‘assign’, mkleaf( id .entry), E.ptr) } { S.ptr := mknode(‘if_then’, E.ptr, S 1 .ptr) } { S.ptr := mknode(‘while_do’, E.ptr, S 1 .ptr) } { S.ptr := mknode(‘ ; ’ , S 1 .ptr , S 2 .ptr) } { E.ptr := mkleaf( id .entry) } { E.ptr := mknode(‘ + ’ , E 1 .ptr , E 2 .ptr) } { E.ptr := mknode(‘  ’ , E 1 .ptr , E 2 .ptr) } { E.ptr := E 1 .ptr } …… mknode : 构造内部结点 Mkleaf : 构造叶子结点
  26. 26. 中间代码生成 <ul><li>顺序的语句序列 其 语句 一般具有如下 形式 </li></ul><ul><li>x := y op z </li></ul><ul><li>( op 为操作符, y 和 z 为操作数, x 为结果 ) </li></ul><ul><li>三地址码 TAC </li></ul>
  27. 27. 中间代码生成 <ul><li>课程后续部分用到的 TAC 语句类型 </li></ul><ul><ul><li>赋值语句 x := y op z ( op 代表二元算术 / 逻辑运算) </li></ul></ul><ul><ul><li>赋值语句 x := op y ( op 代表一元运算) </li></ul></ul><ul><ul><li>复写语句 x := y ( y 的值赋值给 x ) </li></ul></ul><ul><ul><li>无条件跳转语句 goto L (无条件跳转至标号 L ) </li></ul></ul><ul><ul><li>条件跳转语句 if x rop y goto L ( rop 代表关系运算) </li></ul></ul><ul><ul><li>过程调用语句序列 param x 1 … param x n call p,n </li></ul></ul><ul><ul><li>过程返回语句 return y ( y 可选,存放返回值) </li></ul></ul><ul><ul><li>下标赋值语句 x := y [ i ] 和 x [ i ] := y (前者表示将地 </li></ul></ul><ul><ul><li>址 y 起第 i 个存储单元的值赋给 x , 后者类似) </li></ul></ul><ul><ul><li>地址和指针赋值语句 x := &y , x := *y 和 *x := y </li></ul></ul><ul><li>参考 A.V.Aho 等的教材(龙书) </li></ul>
  28. 28. 中间代码生成 <ul><li>语义属性 </li></ul><ul><ul><li>id . name : id 的词法名字(符号表中的名字) </li></ul></ul><ul><ul><li>E . place : 用来存放 E 的值的存储位置 </li></ul></ul><ul><ul><li>E . code : E 求值的 TAC 语句序列 </li></ul></ul><ul><li>语义函数 / 过程 </li></ul><ul><ul><li>lookup ( id . name ) : 从符号表中查找名字为 id . name </li></ul></ul><ul><ul><li>的项,返回存放相应值的指针(存储位置),若无该 </li></ul></ul><ul><ul><li>项,则返回 nil </li></ul></ul><ul><ul><li>gen : 生成一条 TAC 语句 </li></ul></ul><ul><ul><li>newtempt : 返回一个未使用过的存储位置 </li></ul></ul><ul><li>赋值语句及算数表达式的语法制导翻译 </li></ul>
  29. 29. 中间代码生成 <ul><li>翻译模式 </li></ul>S  id := E E  E 1 + E 2 E  E 1  E 2 E  - E 1 E  ( E 1 ) E  id { p := lookup ( id . name ); if ( p  nil) then S.code := E.code || gen (p ‘:=‘ E.place) else error } { E.place := newtemp; E.code := E 1 .code || E 2 .code || gen ( E.place ‘:=‘ E 1 .place ‘+’ E 2 .place) } { E.place := newtemp; E.code := E 1 .code || E 2 .code || gen ( E.place ‘:=‘ E 1 .place ‘  ’ E 2 .place) } { E.place := newtemp; E.code := E 1 .code || gen ( E.place ‘:=‘ ‘uminus‘ E 1 .palce) } { E.place := E 1 .place ; E.code := E 1 .code } { p := lookup ( id . name ); if ( p  nil) then E.place := p else error ; E.code := ‘’ } <ul><li>赋值语句及算数表达式的语法制导翻译 </li></ul>
  30. 30. 中间代码生成 <ul><li>回顾:类型属性的计算 </li></ul><ul><li>说明语句的语法制导翻译 </li></ul>P  D ; E D  D 1 ; D 2 D  id : T T  char T  integer T  real T  array [ num ] of T 1 T   T 1 E  … { enter ( id . name , T.type )} { T.type := char } { T.type := integer } { T.type := real } { T.type := array (1.. num .val, T 1 .type ) } { T.type := pointer ( T 1 .type ) } enter ( id . name , T.type ) : 将符号表中 id . name 所对应表项的 type 域置为 T.type
  31. 31. 中间代码生成 <ul><li>语义属性 </li></ul><ul><ul><li>id . name : id 的词法名字(符号表中的名字) </li></ul></ul><ul><ul><li>T . type : 类型属性 </li></ul></ul><ul><ul><li>T . width , D . width : 数据宽度(字节数) </li></ul></ul><ul><ul><li>D . offset : 相对于过程数据区基址的下一个可用的相 </li></ul></ul><ul><ul><li>对偏移地址(参考下一讲 : 运行时存储组织) </li></ul></ul><ul><li>语义函数 / 过程 </li></ul><ul><ul><li>enter ( id . name , T.type, D.offset ) : 将符号表中 </li></ul></ul><ul><ul><li>id . name 所对应表项的 type 域置为 T.type, </li></ul></ul><ul><ul><li>offset 域置为 D.offset </li></ul></ul><ul><li>过程(函数)中说明语句的语法制导翻译 </li></ul>
  32. 32. 中间代码生成 <ul><li>过程中说明语句的语法制导翻译 </li></ul><ul><li>翻译模式 </li></ul>P  { D.offset := 0 } D ; E D  { D 1 .offset := D.offset } D 1 ; { D 2 .offset := D.offset + D 1 .width } D 2 { D.width := D 1 .width + D 2 .width } D  id : T { enter ( id . name , T.type, D.offset ) ; D.width := T.width } T  char { T.type := char ; T.width := 1 } T  integer { T.type := integer ; T.width := 4 } T  real { T.type := real ; T.width := 8 } T  array [ num ] of T 1 { T.type := array( num .val, T 1 .type ) ; T.width := num .val  T 1 .width } T   T 1 { T.type := pointer ( T 1 .type ) ; T.width := 4 } E  …
  33. 33. 中间代码生成 <ul><li>数组说明 </li></ul><ul><li>参考前页的翻译模式,可了解(一维)数组说明的翻译 </li></ul><ul><li>思想 . 至于符号表中一般情况下是如何组织数组说明信 </li></ul><ul><li>息的,随后将会讨论 . </li></ul><ul><li>数组说明和数组元素引用的语法制导翻译 </li></ul>… D  id : T { enter ( id . name , T.type, D.offset ) ; D.width := T.width } … T  array [ num ] of T 1 { T.type := array( num .val, T 1 .width ) ; T.width := num .val  T 1 .width } …
  34. 34. 中间代码生成 <ul><li>数组引用 </li></ul><ul><li>数组说明和数组元素引用的语法制导翻译 </li></ul>S  id := E S  E 1 [ E 2 ] := E 3 E  E 1 [ E 2 ] E  id … { p := lookup ( id . name ); if ( p  nil) then S.code := E.code || gen (p ‘:=‘ E.place) else error } { S.code := E 2 .code || E 3 .code || gen (E 1 .place ‘[’ E 2 .place ‘]’ ‘:=‘ E 3 .place) } { E.place := newtemp; E.code := E 2 .code || gen ( E.place ‘:=‘ E 1 .place ‘ [ ’ E 2 .place ‘]’ ) } { p := lookup ( id . name ); if ( p  nil) then E.place := p else error ; E.code := ‘’}
  35. 35. 中间代码生成 <ul><li>数组的内情向量 ( dove vector ) </li></ul><ul><li>在处理数组时,通常会将数组的有关信息记录在一些单 </li></ul><ul><li>元中,称为“内情向量” . 对于静态数组,内情向量可放在 </li></ul><ul><li>符号表中;对于可变数组,运行时建立相应的内情向量 </li></ul><ul><li>例: 对于静态数组说明 A [ l 1 : u 1 , l 2 : u 2 ,…, l n : u n ] ,可以在符 </li></ul><ul><li>号表中建立如下形式的内情向量 : </li></ul><ul><li>数组说明和数组元素引用的语法制导翻译 </li></ul>l 1 u 1 l 2 u 2 l n u n type a n C … … l i : 第 i 维的下界 u i : 第 i 维的上界 type : 数组元素的类型 a : 数组首元素的地址 n : 数组维数 C : 随后解释
  36. 36. 中间代码生成 <ul><li>数组元素的地址计算 </li></ul><ul><li>例: 对于静态数组 A [ l 1 : u 1 , l 2 : u 2 ,…, l n : u n ] ,若数组布局采 </li></ul><ul><li>用行优先的连续布局,数组首元素的地址为 a ,则数组 </li></ul><ul><li>元素 A [ i 1 , i 2 ,…, i n ] 的地址 D 可以如下计算 : </li></ul><ul><ul><ul><ul><li>D = a + ( i 1 - l 1 )( u 2 - l 2 )( u 3 - l 3 ) …( u n - l n ) </li></ul></ul></ul></ul><ul><ul><ul><ul><li>+ ( i 2 - l 2 )( u 3 - l 3 )( u 4 - l 4 ) …( u n - l n ) </li></ul></ul></ul></ul><ul><ul><ul><ul><li>+…+ ( i n-1 - l n-1 )( u n - l n ) + ( i n - l n ) </li></ul></ul></ul></ul><ul><li>数组说明和数组元素引用的语法制导翻译 </li></ul><ul><li>重新整理后得 : D = a – C + V ,其中 </li></ul><ul><ul><li>C = ( … ( l 1 ( u 2 - l 2 ) +l 2 ) ( u 3 - l 3 ) + l 3 ) ( u 4 - l 4 ) + … + l n-1 ) ( u n - l n ) + l n </li></ul></ul><ul><ul><li>V = ( … (( i 1 ( u 2 - l 2 ) +i 2 ) ( u 3 - l 3 ) + i 3 ) ( u 4 - l 4 ) + …… + i n-1 ) ( u n - l n ) + i n </li></ul></ul>(这里的 C 即为前页内情向量中的 C )
  37. 37. 中间代码生成 <ul><li>直接对布尔表达式求值 </li></ul><ul><ul><li>例如 : 可以用数值“ 1 ” 表示 true; 用数值“ 0 ” 表示 false; </li></ul></ul><ul><ul><li>采用与算术表达式类似的方法对布尔表达式进行求值 </li></ul></ul><ul><li>通过控制流体现布尔表达式的语义 </li></ul><ul><ul><li>方法 :通过转移到程序中的某个位置来表示布尔表达式的求值结果 </li></ul></ul><ul><ul><li>优点 :方便实现 控制流语句中 布尔表达式的翻译 </li></ul></ul><ul><ul><li>常可以得到 短路 ( short-circuit )代码,而避免不必要的 </li></ul></ul><ul><ul><li>求值,如:在已知 E 1 为真时,不必再对 E 1  E 2 中的 E 2 </li></ul></ul><ul><ul><li>进行求值;同样,在已知 E 1 为假时,不必再对 E 1  E 2 </li></ul></ul><ul><ul><li>中的 E 2 进行求值 </li></ul></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>
  38. 38. 中间代码生成 <ul><li>直接对布尔表达式求值 </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E  E 1 or E 2 E  E 1 and E 2 E  not E 1 E  ( E 1 ) E  id 1 rop id 2 E  true E  false { E.place := newtemp; E.code := E 1 .code || E 2 .code || gen ( E.place ‘:=‘ E 1 .place ‘ or ’ E 2 .place) } { E.place := newtemp; E.code := E 1 .code || E 2 .code || gen ( E.place ‘:=‘ E 1 .place ‘ and ’ E 2 .place) } { E.place := newtemp; E.code := E 1 .code || gen ( E.place ‘:=‘ ‘ not ’ E 1 .palce) } { E.place := E 1 .place ; E.code := E 1 .code } { E.place := newtemp; E.code := gen ( ‘ if ‘ id 1 .place rop.op id 2 .place ‘goto’ nextstat+3) || gen ( E.place ‘:=‘ ‘0’ ) || gen ( ‘goto’ nextstat+2) || gen ( E.place ‘:=‘ ‘1’ ) } { E.place := newtemp; E.code := gen( E.place ‘:=‘ ‘1’ ) } { E.place := newtemp; E.code := gen( E.place ‘:=‘ ‘0’ ) } nextstat 返回输出代码序列 中下一条 TAC 语句的下标
  39. 39. 中间代码生成 <ul><li>通过控制流体现布尔表达式的语义 </li></ul><ul><li>例 : 布尔表达式 E = a<b or c<d and e<f 可能翻译为如 </li></ul><ul><li>下 TAC 语句序列(采用短路代码, E.true 和 E.false </li></ul><ul><li>分别代表 E 为真和假时对应于程序中的位置,可用 </li></ul><ul><li>标号体现): </li></ul><ul><li>if a<b goto E.true </li></ul><ul><li>goto label1 </li></ul><ul><li>label1 : </li></ul><ul><li>if c<d goto label2 </li></ul><ul><li>goto E.false </li></ul><ul><li>label2 : </li></ul><ul><li>if e<f goto E.true </li></ul><ul><li>goto E.false </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>
  40. 40. 中间代码生成 <ul><li>翻译布尔表达式至短路代码 </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E  E 1 or E 2 E  E 1 and E 2 E  not E 1 E  ( E 1 ) E  id 1 rop id 2 E  true E  false { E 1 .true := E .true ; E 1 .false := newlabel; E 2 .true := E .true ; E 2 .false := E .false ; E.code := E 1 .code || gen (E 1 .false ‘ : ‘ ) || E 2 .code } { E 1 .false := E .false ; E 1 .true := newlabel; E 2 .true := E .true ; E 2 .false := E .false ; E.code := E 1 .code || gen (E 1 .true ‘ : ‘ ) || E 2 .code } { E 1 .true := E .false ; E 1 .false := E .true ; E.code := E 1 .code } { E 1 .true := E .true ; E 1 .false := E .false ; E.code := E 1 .code } { E.code := gen ( ‘ if ‘ id 1 .place rop.op id 2 .place ‘goto’ E .true ) || gen ( ‘goto’ E .false ) } { E.code := gen ( ‘goto’ E .true ) } { E.code := gen ( ‘goto’ E .false ) }
  41. 41. 中间代码生成 <ul><li>if-then 语句 </li></ul><ul><li>S  if E then S 1 </li></ul><ul><ul><li>{ E.true := newlable; </li></ul></ul><ul><ul><li>E.false := S.next; </li></ul></ul><ul><ul><li>S 1 .next := S.next; </li></ul></ul><ul><li>S .code := E.code || </li></ul><ul><li>gen(E.true ‘:’) || </li></ul><ul><li>S 1 .code </li></ul><ul><li>} </li></ul><ul><li>条件语句的语法制导翻译 </li></ul>E.code S 1 .code E.true: E.false: …… to E.true to E.false newlable 返回一个新的语句标号 S.next 属性表示 S 之后要执行的首条 TAC 语句的标号
  42. 42. 中间代码生成 <ul><li>if-then-else 语句 </li></ul><ul><li>S  if E then S 1 else S 2 </li></ul><ul><ul><li>{ E.true := newlable; </li></ul></ul><ul><ul><li>E.false := newlable; </li></ul></ul><ul><ul><li>S 1 .next := S.next; </li></ul></ul><ul><ul><li>S 2 .next := S.next; </li></ul></ul><ul><li>S .code := E.code || </li></ul><ul><li>gen(E.true ‘:’) || </li></ul><ul><li>S 1 .code || </li></ul><ul><li>gen(‘goto’ S.next) || </li></ul><ul><li>gen(E.false ‘:’) || </li></ul><ul><li>S 2 .code </li></ul><ul><li>} </li></ul><ul><li>条件语句的语法制导翻译 </li></ul>E.code S 1 .code E.true: E.false: goto S .next to E.true to E.fase …… S 2 .code S.next:
  43. 43. 中间代码生成 <ul><li>循环语句的语法制导翻译 </li></ul><ul><li>while 语句 </li></ul><ul><li>S  while E do S 1 </li></ul><ul><ul><li>{ S.begin := newlable; </li></ul></ul><ul><ul><li>E.true := newlable; </li></ul></ul><ul><ul><li>E .false := S.next; </li></ul></ul><ul><ul><li>S 1 .next := S.begin; </li></ul></ul><ul><li>S .code := gen(S.begin ‘:’) </li></ul><ul><li>|| E.code </li></ul><ul><li>|| gen(E.true ‘:’) </li></ul><ul><li>|| S 1 .code </li></ul><ul><li>|| gen(‘goto’ S.begin) </li></ul><ul><li>} </li></ul>E.code S 1 .code S.begin: E.false: goto S .begin to E.true to E.false …… E.true:
  44. 44. 中间代码生成 <ul><li>复合语句的语法制导翻译 </li></ul><ul><li>顺序复合语句 </li></ul><ul><li>S  S 1 ; S 2 </li></ul><ul><ul><li>{ S 1 .next := newlable; </li></ul></ul><ul><ul><li>S 2 .next := S.next ; </li></ul></ul><ul><li>S .code := S 1 .code </li></ul><ul><li>|| gen( S 1 .next ‘:’) </li></ul><ul><li>|| S 2 .code </li></ul><ul><li>} </li></ul>S 1 .code S 2 .code S.next: …… S 1 .next:
  45. 45. 中间代码生成 <ul><li>翻译布尔表达式至短路代码(翻译模式) </li></ul><ul><li>布尔表达式的语法制导翻译 </li></ul>E  { E 1 .true := E .true ; E 1 .false := newlabel } E 1 or { E 2 .true := E .true ; E 2 .false := E .false } E 2 { E.code := E 1 .code || gen (E 1 .false ‘ : ‘ ) || E 2 .code } E  { E 1 .false := E .false ; E 1 .true := newlabel } E 1 and { E 2 .true := E .true ; E 2 .false := E .false } E 2 { E.code := E 1 .code || gen (E 1 .true ‘ : ‘ ) || E 2 .code } E  not { E 1 .true := E .false ; E 1 .false := E .true } E 1 { E.code := E 1 .code } E  ( { E 1 .true := E .true ; E 1 .false := E .false } E 1 ) { E.code := E 1 .code } E  id 1 rop id 2   { E.code := gen ( ‘ if ‘ id 1 .place rop.op id 2 .place ‘goto’ E .true ) || gen ( ‘goto’ E .false ) } E  true { E.code := gen ( ‘goto’ E .true ) } E  false { E.code := gen ( ‘goto’ E .false ) }
  46. 46. 中间代码生成 <ul><li>if-then 语句(翻译模式) </li></ul><ul><li>S  if { E.true := newlable ; E.false := S.next } E   </li></ul><ul><li>     then { S 1 .next := S.next }   S 1 </li></ul><ul><li>     { S .code := E.code || gen(E.true ‘:’) || S 1 .code } </li></ul><ul><li>条件语句的语法制导翻译 </li></ul>E.code S 1 .code E.true: E.false: …… to E.true to E.false newlable 返回一个新的语句标号 S.next 属性表示 S 之后要执行的首条 TAC 语句的标号
  47. 47. 中间代码生成 <ul><li>if-then-else 语句(翻译模式) </li></ul><ul><li>条件语句的语法制导翻译 </li></ul>E.code S 1 .code E.true: E.false: goto S .next to E.true to E.fase …… S 2 .code S.next: S  if { E.true := newlable;      E.false := newlable }    E   then      { S 1 .next := S.next }    S 1   else      { S 2 .next := S.next }    S 2         { S .code := E.code ||       gen(E.true ‘:’) ||       S 1 .code ||       gen(‘goto’ S.next) ||       gen(E.false ‘:’) ||       S 2 .code       }
  48. 48. 中间代码生成 <ul><li>循环语句的语法制导翻译 </li></ul><ul><li>while 语句(翻译模式) </li></ul>E.code S 1 .code S.begin: E.false: goto S .begin to E.true to E.false …… E.true: S  while       { E.true := newlable;      E .false := S.next }    E do     { S 1 .next := newlable }    S 1        { S.begin :=   S 1 .next;     S .code := gen(S.begin ‘:’)       || E.code       || gen(E.true ‘:’)       || S 1 .code       || gen(‘goto’ S.begin)     }
  49. 49. 中间代码生成 <ul><li>复合语句的语法制导翻译 </li></ul><ul><li>顺序复合语句(翻译模式) </li></ul><ul><li>S  { S 1 .next := newlable } S 1 ; </li></ul><ul><li>{ S 2 .next := S.next } S 2 </li></ul><ul><li>{ S .code := S 1 .code </li></ul><ul><li>   || gen( S 1 .next ‘:’) </li></ul><ul><li>   || S 2 .code </li></ul><ul><li>} </li></ul>S 1 .code S 2 .code S.next: …… S 1 .next:
  50. 50. 中间代码生成 <ul><li>拉链与代码回填 ( backpatching ) </li></ul><ul><li>另一种控制流中间代码生成技术 </li></ul><ul><li>比较:前面的方法采用 L - 属性文法 / 翻译模式 </li></ul><ul><li>下面的方法采用 S - 属性文法 / 翻译模式 </li></ul>
  51. 51. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>语义属性 </li></ul><ul><li>E.truelist : “ 真链”,链表中的元素表示 一系列跳转语 </li></ul><ul><li>句的地址,这些跳转语句的目标标号是体现布 </li></ul><ul><li>尔表达式 E 为“真”的标号 </li></ul><ul><li>E. falselist : “ 假链”,链表中的元素表示 一系列跳转语 </li></ul><ul><li>句的地址,这些跳转语句的目标标号是体现布 </li></ul><ul><li>尔表达式 E 为假的标号 </li></ul><ul><li>S. nextlist : “ next 链”,链表中的元素表示 一系列跳转 </li></ul><ul><li>语句的地址,这些跳转语句的目标标号是在执 </li></ul><ul><li>行序列中紧跟在 S 之后的下条 TAC 语句的标号 </li></ul>
  52. 52. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>语义函数 / 过程 </li></ul><ul><li>makelist(i) : 创建只有一个结点 i 的表,对应存放目标 </li></ul><ul><li>TAC 语句数组的一个下标 </li></ul><ul><li>merge(p 1 ,p 2 ) : 连接两个链表 p 1 和 p 2 ,返回结果链表 </li></ul><ul><li>backpatch(p,i) : 将链表 p 中每个元素所指向的跳转语句 </li></ul><ul><li>的标号置为 i </li></ul><ul><li>nextstm : 下一条 TAC 语句的地址 </li></ul><ul><li>emit (…) : 输出一条 TAC 语句,并使 nextstm 加 1 </li></ul>
  53. 53. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理 布尔表达式的翻译模式 </li></ul>E  E 1 or M E 2 E  E 1 and M E 2 E  not E 1 { backpatch(E 1 .falselist ,M.gotostm) ; E .truelist := merge(E 1 .truelist , E 2 .truelist ) ; E .falselist := E 2 .falselist } { backpatch(E 1 .truelist ,M.gotostm) ; E .falselist := merge(E 1 .falselist , E 2 .falselist ) ; E .truelist := E 2 .truelist } { E .truelist := E 1 .falselist ; E .falselist := E 1 .truelist } 注 : 这里可以规定产生式的优先级依次递增来解决冲突问题 (下同)
  54. 54. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理 布尔表达式的翻译模式 </li></ul>E  ( E 1 ) E  id 1 rop id 2 E  true E  false M   { E .truelist := E 1 .truelist ; E .falselist := E 1 .falselist } { E .truelist := makelist ( nextstm ); E .falselist := makelist ( nextstm+1 ); emit ( ‘ if ‘ id 1 .place rop.op id 2 .place ‘goto _’ ) ; emit ( ‘goto _’ ) } { E .truelist := makelist ( nextstm ); emit ( ‘goto _’ ) } { E .falselist := makelist ( nextstm ); emit ( ‘goto _’ ) } { M .gotostm := nextstm }
  55. 55. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>布尔表达式 E = a<b or c<d and e<f 的翻译 示意 </li></ul>( 0 ) if a<b goto _ or and ( 1 ) goto _ ( 3 ) goto _ ( 2 ) if c<d goto _ ( 4 ) if e<f goto _ ( 5 ) goto _ (4) (2) E .truelist={0,4} E .falselist={3,5}  M .gotostm=2  M .gotostm=4 E .truelist={4} E .falselist={3,5} E .truelist={0} E .falselist={1} < a b E .truelist={2} E .falselist={3} < c d E .truelist={4} E .falselist={5} < e f
  56. 56. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理条件 语句的翻译模式 </li></ul>S  if E then M S 1 { backpatch(E .truelist ,M.gotostm) ; S .nextlist := merge(E .falselist , S 1 .nextlist ) } S  if E then M 1 S 1 N else M 2 S 2 { backpatch(E .truelist , M 1 .gotostm) ; backpatch(E .falselist , M 2 .gotostm) ; S .nextlist := merge(S 1 .nextlist, merge(N .nextlist , S 2 .nextlist ) ) } M   { M .gotostm := nextstm } N   { N .nextlist := makelist( nextstm ); emit(‘goto _’) }
  57. 57. 中间代码生成 <ul><li>拉链与代码回填 </li></ul><ul><li>处理循环、复合及其它 语句的翻译模式 </li></ul>S  while M 1 E do M 2 S 1 { backpatch(S 1 .nextlist, M 1 .gotostm) ; backpatch(E .truelist, M 2 .gotostm) ; S .nextlist := E .falselist ; emit(‘goto’, M 1 .gotostm) } S  begin L end { S .nextlist := L .nextlist } S  A { S .nextlist := nil } L  L 1 ; M S { backpatch(L 1 .nextlist, M.gotostm) ; L .nextlist := S .nextlist } L  S { L .nextlist := S .nextlist }
  58. 58. 中间代码生成 <ul><li>拉链回填技术 示例 </li></ul><ul><li>GOTO 语句的语法制导翻译 </li></ul><ul><li>…… </li></ul><ul><li>(10) goto L </li></ul><ul><li>…… </li></ul><ul><li>(20) goto L </li></ul><ul><li>…… </li></ul><ul><li>(30) goto L </li></ul><ul><li>…… </li></ul><ul><li>(40) L : </li></ul><ul><li>…… </li></ul><ul><li>goto L </li></ul><ul><li>…… </li></ul>…… (100) goto 0 …… (200) goto 100 …… (300) goto 200 …… (400) L :
  59. 59. 中间代码生成 <ul><li>拉链回填技术 示例 </li></ul><ul><li>GOTO 语句的语法制导翻译 </li></ul><ul><li>…… </li></ul><ul><li>(10) goto L </li></ul><ul><li>…… </li></ul><ul><li>(20) goto L </li></ul><ul><li>…… </li></ul><ul><li>(30) goto L </li></ul><ul><li>…… </li></ul><ul><li>(40) L : </li></ul><ul><li>…… </li></ul><ul><li>goto L </li></ul><ul><li>…… </li></ul>…… (100) goto 400 …… (200) goto 400 …… (300) goto 400 …… (400) L : …… (500) goto 400 ……
  60. 60. 中间代码生成 <ul><li>利用 标号的符号表项维护拉链 </li></ul><ul><ul><li>若采用类似 PL0 的符号表结构,可以设计标号表项包 </li></ul></ul><ul><ul><li>括如下域: </li></ul></ul><ul><ul><li>name , kind , level 等,与其它类别的符号一样 </li></ul></ul><ul><ul><li>defined : 表示该标号的说明是否已处理过 </li></ul></ul><ul><ul><li>add : 该标号的说明处理之前用于拉链,处理过后表 </li></ul></ul><ul><ul><li>示该标号的说明翻译后所指向的 TAC 语句位置 </li></ul></ul><ul><li>语义函数 / 过程 </li></ul><ul><ul><li>setlbdefined ( id . name,x ), getlbdefined ( id . name ) </li></ul></ul><ul><ul><li>setlbadd ( id . name,x ), getlbadd ( id . name ) </li></ul></ul><ul><ul><li>分别表示设置和获取标号的 defined 、 add 值 </li></ul></ul><ul><ul><li>backpatch ( nextstm ): </li></ul></ul><ul><ul><li>沿拉链反向将所有 goto 语句的目标返填为 nextstm </li></ul></ul><ul><li>GOTO 语句的语法制导翻译 </li></ul>
  61. 61. 中间代码生成 <ul><li>标号 说明和 GOTO 语句的翻译模式 </li></ul><ul><li>GOTO 语句的语法制导翻译 </li></ul>S  id : S { p := lookup ( id . name ); if ( p=nil) then enter( id . name ) ; setlbdefined( id . name ,1) ; setlbadd( id . name , nextstm ); backpatch( nextstm ) } S  goto id { p := lookup ( id . name ); if ( p=nil) then { enter( id . name ) ; setlbdefined( id . name ,0) ; setlbadd( id . name ,0); emit(‘goto’, 0)}; else emit(‘goto’, getlbadd( id . name ) ) if getlbdefined (id.name)=0 then setlbadd( id . name , nextstm-1 ) }
  62. 62. 中间代码生成 <ul><li>简单 过程调用的翻译 </li></ul><ul><ul><li>示例: 过程调用 CALL S ( A+B,A  B ) </li></ul></ul><ul><ul><li>将被翻译为: </li></ul></ul><ul><ul><li>计算A+B 置于T中的代码 // T := A+B </li></ul></ul><ul><ul><li>计算A  B 置于Z中的代码 // Z := A  B </li></ul></ul><ul><ul><li>param  T // 第一个实参地址 </li></ul></ul><ul><ul><li>param  Z // 第二个实参地址 </li></ul></ul><ul><ul><li>call S , 2 // 转子指令 </li></ul></ul><ul><li>过程调用的语法制导翻译 </li></ul>
  63. 63. 中间代码生成 <ul><li>简单过程调用的 翻译模式 </li></ul><ul><li>过程调用的语法制导翻译 </li></ul>S  call id ( L ) { S .code := L .code ; for L.arglist 中的每一项 p do S.code := S.code || gen ( ‘ param ’ p ) ; S.code := S.code || gen ( ‘call’ id .place , L . n ) } L  L 1 , E { L.n := L 1 .n + 1; L.arglist := append(L 1 .arglist ,makelist(E.place)); L.code := L 1 .code || E.code } L   { L.n := 0; L.arglist := null ; L.code := ‘ ’ } L.n : 参数个数 L.arglist : 实参地址的列表 makelist : 创建实参地址结点 append : 在实参表中添加结点
  64. 64. 课后作业 1 熟练掌握本讲出现的每个属性文法 / 翻译模式的 设计目的 , 设计思想和设计技术 <ul><li>参考本讲稿第 39-44 页的 L 属性文法及所用到的语义函数 , </li></ul><ul><li>(1) 若在基础文法中增加产生式 E  E  E ,试给出相应 </li></ul><ul><li>该产生式的语义规则集合。其中 , “  ” 代表 “ 与非 ” 逻辑算 </li></ul><ul><li>符,可用其它逻辑运算定义为 P  Q  not ( P and Q ) </li></ul><ul><li>(2) 若在基础文法中增加产生式 S  repeat S until E , </li></ul><ul><li>试给出相应该产生式的语义规则集合。 </li></ul><ul><li>注: repeat < 循环体 > until < 布尔表达式 > 的语义为 : </li></ul><ul><li>至少执行 < 循环体 > 一次,直到 < 布尔表达式 > 成真 </li></ul><ul><li>时结束循环。 </li></ul>
  65. 65. 课后作业 3 参考本讲稿第 45-49 页的翻译模式及所用到的语义函数 , 重复 2 中 (1), (2) 的工作。 <ul><li>参考本讲稿第 50-56 页的 S 属性文法 / 翻译模式及所用到 </li></ul><ul><li>的语义函数 , 重复 2 中 (1), (2) 的工作。 </li></ul>
  66. 66. Thank You That’s all for today.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×