📜  编译器设计中的运行时环境

📅  最后修改于: 2021-06-28 07:48:22             🧑  作者: Mango

转换需要将程序的静态源文本与在运行时为实现程序而必须执行的动态动作相关联。该程序由过程名称,标识符等组成,它们需要在运行时与实际内存位置进行映射。

运行时环境是目标计算机的状态,可以包括软件库,环境变量等,以向系统中运行的进程提供服务。

源语言问题

激活树

程序由过程组成,过程定义是一个声明,该声明以其最简单的形式将标识符(过程名称)与语句(过程主体)相关联。程序的每次执行都称为该程序的激活。激活的生命周期是该过程执行中存在的步骤序列。如果“ a”和“ b”是两个过程,则它们的激活将是不重叠的(当一个被另一个调用时)或嵌套的(嵌套过程)。如果新的激活在同一过程的较早激活结束之前开始,则该过程是递归的。激活树显示控件进入和离开激活的方式。
激活树的属性是:

  • 每个节点代表一个过程的激活。
  • 根表示主要函数的激活。
  • 当且仅当控件从过程x流向过程y时,过程’x’的节点才是过程’y’的节点的父节点。

示例–考虑以下Quicksort程序

main() {

      Int n;
      readarray();
      quicksort(1,n);
}

quicksort(int m, int n) {

     Int i= partition(m,n);
     quicksort(m,i-1);
     quicksort(i+1,n);
}

该程序的激活树为:

1个

首先将主函数作为根,然后主调用readarray和quicksort。 Quicksort依次调用分区和quicksort。程序中的控制流与从根部开始的激活树的深度优先遍历相对应。

控制堆栈和激活记录

控制堆栈或运行时堆栈用于跟踪实时过程激活,即尚未完成执行的过程。过程名称在调用时(激活开始)被压入堆栈,并在返回时(激活结束)被弹出。使用激活记录或框架来管理过程的一次执行所需的信息。调用过程时,激活记录被推入堆栈,并且控件返回到调用者函数,就会弹出激活记录。

2个

常规激活记录包含以下内容:

  • 局部变量:保存过程执行局部的数据。
  • 临时值:存储在表达式求值中出现的值。
  • 机器状态:在函数调用之前保存有关机器状态的信息。
  • 访问链接(可选):指保存在其他激活记录中的非本地数据。
  • 控制链接(可选):指向呼叫者的激活记录。
  • 返回值:被调用过程用来将值返回给调用过程
  • 实际参数

上面的quicksort示例的控制堆栈:

3

4

运行内存的细分

运行时存储可以细分为:

  • 目标代码-程序代码,它是静态的,因为它的大小可以在编译时确定
  • 静态数据对象
  • 动态数据对象-堆
  • 自动数据对象-堆栈

5

存储分配技术

一,静态存储分配

    • 对于任何程序,如果我们在编译时创建内存,则会在静态区域中创建内存。
    • 对于任何程序,如果我们仅在编译时创建内存,则内存仅创建一次。
    • 它不支持动态数据结构,即在编译时创建内存,并在程序完成后释放内存。
    • 静态存储分配的缺点是不支持递归。
    • 另一个缺点是在编译时应该知道数据的大小

例如,FORTRAN被设计为允许静态存储分配。

二。堆栈存储分配

  • 存储组织为堆栈,激活记录分别在激活开始和结束时被推送和弹出。本地记录包含在激活记录中,因此它们在每次激活时都绑定到新存储。
  • 堆栈分配支持递归

三,堆存储分配

  • 取决于用户的要求,可以在任何时间,任何位置进行内存分配和释放。
  • 堆分配用于为变量动态分配内存,并在不再需要变量时将其收回。
  • 支持递归。

activation_5

参数传递

程序之间的通信介质称为参数传递。来自调用过程的变量的值通过某种机制转移到被调用过程。

基本术语:

  • R值:表达式的值称为其R值。如果单个变量中包含的值出现在赋值运算符的右侧,那么它也将成为r值。 R值可以始终分配给其他变量。
  • L值:存储表达式的内存(地址)的位置称为该表达式的L值。如果赋值运算符,它总是出现在左侧。
    activation_6

    i。形式参数:将调用者过程传递的信息作为变量的形式参数称为形式参数。这些变量在被调用函数的定义中声明。

    ii。实际参数:将其值和函数传递给被调用函数的变量称为实际参数。这些变量在函数调用中作为参数指定。

将参数传递给过程的不同方式

  • 按价值致电
    在按值调用中,调用过程将传递实际参数的r值,然后编译器将其放入被调用过程的激活记录中。形式参数保留调用过程传递的值,因此形式参数中的任何更改都不会影响实际参数。 activation_7
  • 按引用调用在按引用调用中,形式参数和实际参数引用相同的内存位置。实际参数的l值将复制到被调用函数的激活记录中。因此,被调用函数具有实际参数的地址。如果实际参数没有l值(例如i + 3),则会在新的临时位置进行评估,并传递该位置的地址。形式参数中所做的任何更改都会反映在实际参数中(因为在地址处进行了更改)。

    activation_8

  • 通过复制还原呼叫
    在复制复制调用中,编译器在调用过程时将值复制为形式参数,并在控制权返回到被调用函数时将其复制回实际参数。传递r值,并在返回时将形式的r值复制到实数的l值。
    activation_9
  • 按姓名致电
    按名称调用时,实际参数会在过程中所有形式形式出现的地方替换形式形式。这也称为延迟评估,因为仅在需要时才对参数进行评估。 activation_10