<编译器> 6. 活动记录 | 1. 栈帧
tips
栈
栈指针
帧
帧指针
Frame 模块: 栈帧相关信息
F_frame : 栈帧
F_access : 表示 寄存器 / 栈帧 的地址偏移, 即位置
Symbol Temp_label : 标识符
F_newFrame(label, boolList) : 生成 符号 label 对应的新栈帧
F_formals() : 返回形参的 access
F_allocLocal() : 返回局部变量的 access
Translate 模块: 关联 栈帧 和 语义分析 , 相比 F_access, 添加了 level 信息
Tr_access : 函数层 (标识嵌套信息) 与 栈帧信息 F_frame { Tr_level, F_access}
Tr_level : 嵌套层, 函数嵌套关系
Tr_allocLocal() : 带 level 信息的局部变量 Tr_access
Tr_formals() : 带 level 信息的形参 Tr_access
Tr_newLevel() : 创建新的函数层
Tr_newLevel(
level_包围层, ( 函数 f 的包围层, 即调用者 )
f_当前层函数,
[ 标记形参是否逃逸的 Bool 数组 (第一个元素对应静态链)]
)
Tr_outermost() : 最外层函数标识
transDec()
transExp()
transVar()
LIFO: 递归函数调用 -> 栈 存储
高阶函数: 支持递归调用, 支持以函数做为返回值, 不能用简单的 栈来存储,(在15章讨论)
栈 + 栈指针:
指针右侧: 垃圾回收
指针左侧: local 变量
活动记录: activity record , 栈帧: stack frame
标准结构 : 可以实现 跨语言调用
栈地址 : 从高到低
栈帧 Stack Frames
帧指针 Frame Pointer & 栈指针 Stack Pointer
Stack Frame: 栈帧
SP: Stack Pointer 栈指针
FP: Frame Pointer 帧指针
f( ... ) {
...
g(x,y,....)
...
}
执行 函数 f()时,栈指针SP 在位置A,
执行到 g(x,y,... )时发现要调用函数 g, 则SP -= FRAME_SIZE, 新的FP指向 SP 的地址。
新 FP ~ 新SP 的 FRAME_SIZE 个地址则保存调用过程中的所有数据, 以备后来之用。
参数传递
前 k 个放在寄存器中 (一般中 k=4 或 k=6)
f(g()):
临时变量 x 在函数 f() 调用以后不再需要: 放入一个调用者保护的寄存器中, 调用 g() 时不保护它
局部变量 i (f()内部)在函数 g( ) 调用前后都需要: f() 入口 放入被 调用保护 寄存器 ri 一次 , f()出口取回一次
返回地址
call 指令地址 + 1 => 放入 寄存器 => 非叶过程 后面还有指令要跑, 所有结束后 还要等, 需要把地址存在自己的栈帧里面
寄存器 or 栈帧 ?
寄存器中:
参数:寄存器中
返回地址:寄存器中
函数结果:寄存器中 返回
局部变量,中间结果:寄存器中
栈帧(存储)中:
1. 传址变量:变量为一地址 ( &p )
2. 该变量被嵌套在当前过程(函数)内的过程(其他函数)访问
3. 变量值太大,不能放在单个寄存器中 ( 32位,4字节 或 64位, 8字节 )
4. 变量是一个数组,元素需要地址运算(C语言)
5. 需要使用存放该变量的寄存器
6. 太多局部变量 临时变量, 无法全部放入寄存器中
7. 函数参数大于k个 (k一般为 4 到 5个)