上一节中,我们已经实现了逻辑运算和负数,在本节中,我们将要实现比较难的局部变量。
现在,我们所有的变量对所有函数都是全局可见的。我们想添加一个本地范围对于变量,这样每个函数都有自己的变量,不能被其他函数看到。此外,在递归函数的情况下,同一个函数的每个实例都有自己的局部变量。
要为同一函数的多个实例创建本地作用域,为了提供一个地方来存储函数的参数,我们需要一个堆。
让我们从局部变量和全局变量之间的区别开始。全局变量必须对所有函数可见,但局部变量只是对一个函数可见。
SubC使用一个符号表来存储有关本地和全局变量。全局变量在一端分配,局部变量存储在另一个。有代码来确保有中间两端没有碰撞。我们可以借鉴这一点。
在将局部符号优先于全局符号方面,我们可以首先搜索符号表的本地端,如果我们没有找到符号,然后我们可以搜索全局端。而且,一旦我们完成解析一个函数,我们可以简单地擦除符号表的本地端。
我们将如何确定参数或局部变量在堆栈中的位置,一旦它们被复制或放置在那里?为此,我将添加一个 posn 字段到每个本地符号表条目。这将指示变量距离栈基指针的偏移地址。
修改符号表
为了区分全局变量和局部变量,我们修改局部变量结构体。
// 变量类型
enum
{
C_GLOBAL = 1, // 全局变量
C_LOCAL // 局部变量
};
// 符号表结构体
struct symbol_table
{
char *name; // 符号名
int type; // 类型void或int
int stype; // 结构类型
int endlabel; // 函数的结束标签
int size; // 数组大小
int class; // 符号类别
int posn; // 距离栈基指针的偏移地址
};
我们添加了class和posn字段。如上一部分所述,posn为负数,并保存与堆栈基指针的偏移量,即局部变量存储在堆栈中。
在这部分,我只实现了局部变量,没有实现参数。另请注意,我们现在有标记为C_GLOBAL或C_LOCAL的符号。
因此,符号表的名称也发生了变化,其中的索引改变了
int Globals = 0; // 下一个空闲全局变量槽的位置
int Locals = SYMBOL_NUM - 1; // 下一个空闲局部变量槽的位置
从视觉上看,全局符号存储在符号表的左侧,“Globs”指向下一个空闲全局符号槽,而“Locls”指向下一个空闲局部符号槽。
0xxxx......................................xxxxxxxxxxxxNSYMBOLS-1
^ ^
| |
Globals Locals
我们现在有的find_global()和new_global()函数,用于查找或分配全局符号,我们现在新增find_local()和new_local()函数,来查找或分配局部符号。他们有代码来检测Locals和Globals之间的冲突。
// 检查符号s是否在全局符号表中。
// 返回其插槽位置或-1
int find_global(char *s)
{
int i;
for (i = 0; i < Globals; i++)
{
if (*s == *Tsym[i].name && !strcmp(s, Tsym[i].name))
return i;
}
return -1;
}
// 获取新的全局符号槽的位置
int new_global()
{
int p;
if ((p = Globals++) >= Locals)
{
fprintf(stderr, "Too many global symbols on line %d\n", Line);
exit(1);
}
return p;
}
// 确定符号s是否在本地符号表中,
// 返回其插槽位置或-1
int find_local(char *s)
{
int i;
for (i = Locals + 1; i < SYMBOL_NUM; i++)
{
if (*s == *Tsym[i].name && !strcmp(s, Tsym[i].name))
return i

本节详细介绍了如何在编译器中实现局部变量,包括符号表的修改以区分全局和局部变量,以及堆栈管理以存储局部变量。通过增加`class`和`posn`字段来区分变量类型和位置,同时实现`find_local()`和`new_local()`函数以处理局部符号。此外,更新了语法分析和汇编代码以支持局部变量的声明和访问。测试案例展示了局部变量的正确工作情况。
——局部变量&spm=1001.2101.3001.5002&articleId=118490322&d=1&t=3&u=66fbccb9a1974a9fbb89cd3e4e289f81)
1064

被折叠的 条评论
为什么被折叠?



