07-第7章-中间代码生成-编译原理PDF精讲课件-中国科技大学(共13讲)
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理和技术
中国科学技术大学 计算机科学与技术学院 陈意云
第七章 中间代码生成
记号 分析 流 器 本章内容
–介绍几种常用的中间表示:后缀表示、图形表示 和三地址代码 –用语法制导定义和翻译方案来说明源语言的各种 构造怎样被翻译成中间形式
静态 检查 器
中间 代码 中间 代码 生成 代码 生成 器 器
7.1 中 间 语 言
7.1.2 图形表示 • 语法树是一种图形化的中间表示 • 有向无环图也是一种中间表示
assign a + + a assign +
+ c uminus d uminus c c d d b b (b) DAG (a) 语法树 a = (b + cd) + cd的图形表示
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 – 一个变量在不同路径上都定值的解决办法 if (flag) x = 1; else x = 1; y = x a; 改成 if (flag) x1 = 1; else x2 = 1; x3 = (x1, x2); //由flag的值决定用x1还是x2
E E1 E2 E.nptr = mkNode( ‘’, E1.nptr, E2.nptr) E.nptr = mkUNode( ‘uminus’, E1.nptr) E E1 E (E1) F id E.nptr = E1.nptr E.nptr = mkLeaf (id, id.entry)
符号表实例
7.2 声 明 语 句
• 符号表的特点
–各过程有各自的符号表 –符号表之间有双向链 –构造符号表时需要符号表栈 –构造符号表需要活动记录栈 sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…;
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.2 声 明 语 句
7.2.3 记录的域名 T record D end 记录类型单独建符号表,作为类型表达式的 主要部分,域的相对地址从0开始 record T record L D end a :…; r : record {T.type = record (top(tblptr) ); i :…; T.width = top(offset); ... pop(tblptr); pop(offset) } end; L {t = mkTable(nil); k : …; push(t, tblprt); push(0, offset) }
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.1 中 间 语 言
• 三地址代码是语法树或DAG的一种线性表示 • 例 a = ( b + c d ) + c d 语法树的代码 DAG的代码 t1 = b t1 = b assign t2 = c d t2 = c d a + t3 = t1 + t2 t3 = t1 + t2 + t4 = c d t4 = t3 + t2 uminus c d t5 = t3 + t4 a = t4 b a = t5
7.1 中 间 语 言
构造赋值语句语法树的语法制导定义 修改构造结点的函数可生成有向无环图
产 生 式 S id =E E E1 +E2 语 义 规 则 S.nptr = mkNode(‘assign’, mkLeaf (id, id.entry), E.nptr) E.nptr = mkNode( ‘+’, E1.nptr, E2.nptr)
7.1 中 间 语 言
7.1.3 三地址代码 一般形式:x = y op z • 例 表达式x + y z翻译成的三地址语句序列是 t1 = y z t2 = x + t1
7.1 中 间 语 言
• 三地址代码是语法树或DAG的一种线性表示 • 例 a = ( b + c d ) + c d 语法树的代码 t1 = b assign t2 = c d a + t3 = t1 + t2 + t4 = c d c uminus d c d t5 = t3 + t4 b a = t5
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 三地址代码 静态单赋值形式 p = a +b p1 = a +b q=pc q1 = p 1 c p=qd p2 = q1 d p=ep p3 = e p2 q=p+q q 2 = p3 + q1
• 语义动作用到的函数
mkTable(previous) enter(table, name, type, offset) addWidth(table, width) 图6.14的程序 enterProc(table, name, newtable) 参数被略去
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.2 声 明 语 句
7.2.2 作用域信息的保存 • 所讨论语言的文法
P D; S D D ; D | id : T | proc id ; D ; S sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…; 图6.14的程序 参数被略去
7.1 中 间 语 言
7.1.1 后缀表示 E E opE | uopE | (E) | id | num 表达式E的后缀表示可以如下归纳定义: 表达式E 后缀式E id num E1 opE2 uopE (E) id num E1 E2 op E.2 声 明 语 句
计算被声明名字的类型和相对地址 P {offset = 0} D; S DD;D D id : T {enter ( id.lexeme, T.type, offset); offset = offset + T.width } T integer {T.type = integer; T.width = 4 } T real {T.type = real; T.width = 8 } T array [ num ] of T1 {T.type = array (num.val, T1.type); T.width = num.val T1.width} T T1 {T.type = pointer (T1.type); T.width = 4 }
7.2 声 明 语 句
本节介绍 • 为局部名字建立符号表条目 • 为它分配存储单元 • 符号表中包含名字的类型和分配给它的存储 单元的相对地址等信息
7.2 声 明 语 句
7.2.1 过程中的声明
7.2 声 明 语 句
计算被声明名字的类型和相对地址 P {offset = 0} D; S DD;D D id : T {enter ( id.lexeme, T.type, offset); offset = offset + T.width } T integer {T.type = integer; T.width = 4 } T real {T.type = real; T.width = 8 } T array [ num ] of T1 {T.type = array (num.val, T1.type); T.width = num.val T1.width} T T1 {T.type = pointer (T1.type); T.width = 4 }
7.2 声 明 语 句
sort readarray exchange quicksort partition readarray 表头 i 空 sort 表头 指向readarray 指向exchange quicksort 表头 k v partition partition a x readarray exchange quicksort exchange 表头
7.1 中 间 语 言
本书常用的三地址语句 • 赋值语句x = y op z, x = op y, x=y • 无条件转移goto L • 条件转移if x relop y goto L • 过程调用param x 和call p , n • 过程返回 return y • 索引赋值x = y[i]和 x[i] = y • 地址和指针赋值x = &y,x = y和x = y
• 后缀表示不需要括号 (8 5) + 2 的后缀表示是8 5 2 + • 后缀表示的最大优点是便于计算机处理表达 式
计算栈 8 85 3 32 5 输入串 8 5 2 + 5 2 + 2 + 2+ +
7.1 中 间 语 言
• 后缀表示不需要括号 (8 5) + 2 的后缀表示是8 5 2 + • 后缀表示的最大优点是便于计算机处理表达 式 • 后缀表示也可以拓广到表示赋值语句和控制 语句,但很难用栈来描述控制语句的计算
中国科学技术大学 计算机科学与技术学院 陈意云
第七章 中间代码生成
记号 分析 流 器 本章内容
–介绍几种常用的中间表示:后缀表示、图形表示 和三地址代码 –用语法制导定义和翻译方案来说明源语言的各种 构造怎样被翻译成中间形式
静态 检查 器
中间 代码 中间 代码 生成 代码 生成 器 器
7.1 中 间 语 言
7.1.2 图形表示 • 语法树是一种图形化的中间表示 • 有向无环图也是一种中间表示
assign a + + a assign +
+ c uminus d uminus c c d d b b (b) DAG (a) 语法树 a = (b + cd) + cd的图形表示
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 – 一个变量在不同路径上都定值的解决办法 if (flag) x = 1; else x = 1; y = x a; 改成 if (flag) x1 = 1; else x2 = 1; x3 = (x1, x2); //由flag的值决定用x1还是x2
E E1 E2 E.nptr = mkNode( ‘’, E1.nptr, E2.nptr) E.nptr = mkUNode( ‘uminus’, E1.nptr) E E1 E (E1) F id E.nptr = E1.nptr E.nptr = mkLeaf (id, id.entry)
符号表实例
7.2 声 明 语 句
• 符号表的特点
–各过程有各自的符号表 –符号表之间有双向链 –构造符号表时需要符号表栈 –构造符号表需要活动记录栈 sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…;
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.2 声 明 语 句
7.2.3 记录的域名 T record D end 记录类型单独建符号表,作为类型表达式的 主要部分,域的相对地址从0开始 record T record L D end a :…; r : record {T.type = record (top(tblptr) ); i :…; T.width = top(offset); ... pop(tblptr); pop(offset) } end; L {t = mkTable(nil); k : …; push(t, tblprt); push(0, offset) }
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.1 中 间 语 言
• 三地址代码是语法树或DAG的一种线性表示 • 例 a = ( b + c d ) + c d 语法树的代码 DAG的代码 t1 = b t1 = b assign t2 = c d t2 = c d a + t3 = t1 + t2 t3 = t1 + t2 + t4 = c d t4 = t3 + t2 uminus c d t5 = t3 + t4 a = t4 b a = t5
7.1 中 间 语 言
构造赋值语句语法树的语法制导定义 修改构造结点的函数可生成有向无环图
产 生 式 S id =E E E1 +E2 语 义 规 则 S.nptr = mkNode(‘assign’, mkLeaf (id, id.entry), E.nptr) E.nptr = mkNode( ‘+’, E1.nptr, E2.nptr)
7.1 中 间 语 言
7.1.3 三地址代码 一般形式:x = y op z • 例 表达式x + y z翻译成的三地址语句序列是 t1 = y z t2 = x + t1
7.1 中 间 语 言
• 三地址代码是语法树或DAG的一种线性表示 • 例 a = ( b + c d ) + c d 语法树的代码 t1 = b assign t2 = c d a + t3 = t1 + t2 + t4 = c d c uminus d c d t5 = t3 + t4 b a = t5
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 三地址代码 静态单赋值形式 p = a +b p1 = a +b q=pc q1 = p 1 c p=qd p2 = q1 d p=ep p3 = e p2 q=p+q q 2 = p3 + q1
• 语义动作用到的函数
mkTable(previous) enter(table, name, type, offset) addWidth(table, width) 图6.14的程序 enterProc(table, name, newtable) 参数被略去
7.2 声 明 语 句
P M D; S {addWidth (top (tblptr), top (offset)); pop(tblptr); pop (offset) } M {t = mkTable (nil); push(t, tblprt); push (0, offset) } D D1 ; D2 D proc id ; N D1; S {t = top(tblptr); addWidth(t, top(offset) ); pop(tblptr); pop(offset); enterProc(top(tblptr), id.lexeme, t) } Did :T {enter(top(tblptr), id.lexeme, T.type, top(offset)); top(offset) = top(offset) + T.width } N {t = mkTable(top(tblptr) ); push(t, tblptr); push(0, offset) }
7.2 声 明 语 句
7.2.2 作用域信息的保存 • 所讨论语言的文法
P D; S D D ; D | id : T | proc id ; D ; S sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…; 图6.14的程序 参数被略去
7.1 中 间 语 言
7.1.1 后缀表示 E E opE | uopE | (E) | id | num 表达式E的后缀表示可以如下归纳定义: 表达式E 后缀式E id num E1 opE2 uopE (E) id num E1 E2 op E.2 声 明 语 句
计算被声明名字的类型和相对地址 P {offset = 0} D; S DD;D D id : T {enter ( id.lexeme, T.type, offset); offset = offset + T.width } T integer {T.type = integer; T.width = 4 } T real {T.type = real; T.width = 8 } T array [ num ] of T1 {T.type = array (num.val, T1.type); T.width = num.val T1.width} T T1 {T.type = pointer (T1.type); T.width = 4 }
7.2 声 明 语 句
本节介绍 • 为局部名字建立符号表条目 • 为它分配存储单元 • 符号表中包含名字的类型和分配给它的存储 单元的相对地址等信息
7.2 声 明 语 句
7.2.1 过程中的声明
7.2 声 明 语 句
计算被声明名字的类型和相对地址 P {offset = 0} D; S DD;D D id : T {enter ( id.lexeme, T.type, offset); offset = offset + T.width } T integer {T.type = integer; T.width = 4 } T real {T.type = real; T.width = 8 } T array [ num ] of T1 {T.type = array (num.val, T1.type); T.width = num.val T1.width} T T1 {T.type = pointer (T1.type); T.width = 4 }
7.2 声 明 语 句
sort readarray exchange quicksort partition readarray 表头 i 空 sort 表头 指向readarray 指向exchange quicksort 表头 k v partition partition a x readarray exchange quicksort exchange 表头
7.1 中 间 语 言
本书常用的三地址语句 • 赋值语句x = y op z, x = op y, x=y • 无条件转移goto L • 条件转移if x relop y goto L • 过程调用param x 和call p , n • 过程返回 return y • 索引赋值x = y[i]和 x[i] = y • 地址和指针赋值x = &y,x = y和x = y
• 后缀表示不需要括号 (8 5) + 2 的后缀表示是8 5 2 + • 后缀表示的最大优点是便于计算机处理表达 式
计算栈 8 85 3 32 5 输入串 8 5 2 + 5 2 + 2 + 2+ +
7.1 中 间 语 言
• 后缀表示不需要括号 (8 5) + 2 的后缀表示是8 5 2 + • 后缀表示的最大优点是便于计算机处理表达 式 • 后缀表示也可以拓广到表示赋值语句和控制 语句,但很难用栈来描述控制语句的计算