美文网首页
编译原理五

编译原理五

作者: 小屋的快乐 | 来源:发表于2019-06-17 19:37 被阅读0次

    目标程序运行时存储空间的组织

    静态存储分配

    • 如果编译时就能够确定一个程序在运行时所需的存储空间大小,则在编译时就能够安排好目标程序运行时的全部数据空间。
    • 静态存储分配条件:
      1. 数组的上下界必须是常数(维数不能变)
      2. 过程调用不允许递归
      3. 不允许动态数组结构(即在程序运行过程中申请和释放的数据结构)比如FORRTRAN,BASIC
      临时变量
      数组
      简单变量
      形式单元(参数的传递)
      隐参数(寄存器保护区,返回地址)

    简单的栈式存储分配(C语言除去可变数组)

    • 活动记录:程序活动时相关信息保留的程序数据区,调用一个过程,栈顶建立活动记录。变异可以静态确定活动记录体积。
    • 内情向量是描述数组内部情况的数据结构(维数,类型,开始地址)。
    • 先考虑没分程序结构(子程序(没返回值),不是函数),过程定义不允许嵌套,允许过程的递归调用,允许过程含有可变数组。
    • 912833853.jpg 261488133.jpg

      具体有老SP,返回地址,参数个数,形式单元(参数),<简单变量,内情向量,临时工作单元>
      TOP和SP永远指向当前正在执行的。老TOP=SP-1
      绝对地址=SP+相对地址

    • 过程执行情况如下(P181):
    1. 过程调用
      遇到par T1,就要为其构建活动记录。(TOP+1是老SP)
      过程进入:SP=TOP+1,1[SP]=返回地址(PC),TOP=TOP+L;
      之后数据分配(数组内情向量),运行时数组起始地址回填。
    2. 过程返回:
      返回值有一个寄存器,只能有一个。
      销毁活动记录:TOP=SP-1,SP=0[SP](变址寻址,里面存着老SP),X=2[TOP] UJ0[x]

    嵌套过程语言的栈式实现

    用嵌套层次显示(DISPLAY表)嵌套层次简称层数。主程序是0层,之后不断+1。DISPLAY表就是把从直接外层到第0层所有活动记录基址组建成一个表,这个表叫DISPLAY表。第i层display表中有i+1个单元。(当前到第0层),把父层一抄+自己(存SP现行值)。

    找变量:不断往外层找。
    位置:放到活动记录。活动记录存放DISPLAY表(直接外层的)在形式单元上边。全局DISPLAY表也是连接数据。返回地址上有全局DISPLAY表地址。
    1[TOP]=SP
    3[TOP]=SP+d
    ......
    之后JSR P(准备P的入口地址放PC)
    过程进入:SP=TOP+1;
    1【SP】=返回地址(还没放,可保护)
    TOP=TOP+L
    之后按照第三项连接数据抄k个单元内容,最后填新SP形成新SP。

    过程返回:与第二节相同。

    • 存取链(静态链)
      加地址(直接外层活动记录的基址),返回地址上加存取链。

    例题

    • 有动态变量,堆式(空闲表,空闲链)FIRSTfit bestfit worstfit

    目标代码的生成

    • 绝对地址(放在指定位置.COM .EXE)通常放固定存储区可直接执行。
    • 相对地址(.OBJ)
    • 汇编语言(查表翻译到目标代码)

    简单代码生成器(1、寄存器呆时间长 2、寄存器优于内存)

    • 待用信息与活跃信息:
      一个基础块,翻译四元式A=BopC,看后面还有那些四元式用A=BopC,有人用ABC,说ABC代用,不用不活跃,临时变量不用生成信息。
      四元式i对A的定值,四元式j引用A,但之间无A定值,只有i里的A影响j。A在四元式j中待用。活跃。A在后边多出被待用,生成待用信息链。(知道是否待用从后往前扫描)
    • 构建待用信息链和活跃信息链:
      1. 初值:(从基本块最后开始讨论)符号表中所有变量初值构建为非待用,临时变量不活跃,简单变量活跃
      2. 出口到入口,由后向前,每个四元式逐一处理。比如A=BopC。
      3. A待用活跃信息标注四元式,之后置非待用非活跃(定值之前认为未被引用)。BC也标注四元式i,待用信息置i,活跃信息置为活跃。
      4. 非待用非活跃F,活跃L,待用用四元式编号。
      待用可以放寄存器,活跃不待用直接放内存。。。。。。
    例子: 待用活跃.jpg
    • 代码生成算法(生成目标代码):
      1. 寄存器给多个变量用说明它们有同样的值。
      2. 寄存器描述数组RVALUE:寄存器名称作为下标,存放某某某的值。变量地址描述数组:记录变量存储位置AVALUE,Ri表示在寄存器Ri放,A表示在内存里放。

    • 代码生成算法步骤(A=BopC):
      1. 调用GETREG,为了处理四元式给A获取一个寄存器,
      2. 通过地址描述数组获取B,C的存放位置,放寄存器,寄存器就叫B',C'。
      3. 给A选择的寄存器R不是B',则给B'内容传到R里边去,之后拿R和C'执行op操作,否则不用做转移(R是B')。如果B'或C'为R,删除AVALUE[B],AVALUE[C]中的R。
      4. 令A的描述数组=R,R的寄存器数组=A(R只为A服务)
      5. B和C不待用不活跃,寄存器描述数组的BC删掉。地址描述数组的
      Rk也去掉。

    • 申请寄存器的算法:
      1. 如果B的值在Ri中放着了,且Ri中只包含B的值。给A选Ri。或者B和A是同一个标识符(A=AopC),或B在该四元式之后不再被引用了(B单独用一个寄存器是大前提)。
      2. 有没有空闲寄存器
      3. 每空闲的从已分配的寄存器中选一个Ri。原则:占用Ri的值最好同时也在内存中,或该值在基本块最远的位置会被引用到。这是对寄存器Ri调整:对于AVALUE【Ri】每个变量M:M是A,A不用做任何操作。M不是A,如果D的地址描述数组不包含D(只在寄存器不再内存),做如下操作:1、MOVE D,Ri(存到内存里边去 ) 2、D的数组里边写上M把Ri去掉。3、寄存器描述数组D删除掉。4.接着处理其他。最后空着给A用。

      (注意:寄存器里有B咋整?地址描述数组得有B,同时又有Ri。之后就可去B,去不去无所谓) 目标代码生成.jpg
      注意:A=B只改描述数组不mov,出基本块后不活跃不用存内存,否则Mov D,Ri
    • 寄存器的分配:
      指令执行代价=每条指令访问内存次数+1
      比如A=BopC,A要保护,访存1次,BC若放内存还要访存两次。

    • 代价算法:1、变量在基本块定值,分配寄存器,定值之前分配,每用一次省一次(不一定定值,只要定值之前即可,最终定不定值不管,a=a-f定值之前引用了a)。 2、基本块中定值,出基本块之后活跃,省的代价为2.。


      算式.jpg
    • 源程序到目标代码:1、生成中间代码 2、划分基本块 3、翻译

    练习(重要):

    符号表与错误处理

    符号表

    • 符号表是一个统称,又叫名字表:标识符+跟名字相关信息
    • 符号表的组织:
      • 标识符命名为固定长度可以直接组织(BASIC),直接方式名字信息摆在那,有的不合适比如255。还有间接方式:字符串数组存放所有标识符,符号表名字表有指针指标识符(数组里的起始位置),还有长度;还有按标识符种属分类。
      • 信息栏组织分两类:固定信息内容(按种属分,特征相同,信息可一一记录信息栏,好管理),仅记录信息存放地址(不分种属,专门开辟空间存信息,数组,函数亦可采用词法)。
    • 分程序结构语言符号表的建立(带嵌套定义pascal):符号表分层建立。1、扫描声明部分,查找与本层相关的符号表,没有则加入。冲突(声明类型不同,重名)错误处理(建符号表)2、语句中(使用部分)扫描到标识符,查符号表,查不到往外层查。都找不到错误处理。
    • 组织如下:
      • 同一层标识符放在一起,分层处理。
      • 分程序表:OUTERN外层分程序编号,COUNT符号表登记项个数,POINTER指向分程序符号表起始位置。
    • 从外层往内扫描,先构建内层,先来后出用堆栈(先构建,后转移到正式符号表中)
    • 扫描开始建分程序表,扫描标识符查表,无构建,COUNT+1,最后一道正式符号表中。退出分程序,返回外层继续处理外层。
    • 一次扫描扫描完符号表删除,栈式(往后没用不用转移了)。
    • 符号表结构:线性(建简单用麻烦)(10000个平均查5000回),有序符号表(建表有开销)(新加一个往后移),二叉排序树(构建快,查找比有序差4倍,1+4log2N),散列符号表

    错误处理

    查错,改错。(语法错误,语义错误)

    • 语法错误校正。1、修补 2、跳过(错误的局部化) 动态编译时的错误发现不了。

    相关文章

      网友评论

          本文标题:编译原理五

          本文链接:https://www.haomeiwen.com/subject/lubnfctx.html