深入解析DoctorWkt/acwj项目中的局部变量实现

深入解析DoctorWkt/acwj项目中的局部变量实现

acwj A Compiler Writing Journey acwj 项目地址: https://gitcode.com/gh_mirrors/ac/acwj

前言

在编译器开发领域,局部变量的处理是一个重要里程碑。本文将详细分析DoctorWkt/acwj项目中局部变量的实现机制,帮助读者理解编译器如何处理不同作用域的变量。

符号表的结构改造

项目首先对符号表进行了扩展,新增了两个关键字段:

struct symtable {
  char *name;                   // 符号名称
  int type;                     // 基本数据类型
  int stype;                    // 结构类型
  int class;                    // 存储类别(全局/局部)
  int endlabel;                 // 函数结束标签
  int size;                     // 元素数量
  int posn;                     // 局部变量:相对于栈基指针的负偏移量
};

新增的class字段用于区分变量是全局(C_GLOBAL)还是局部(C_LOCAL),而posn字段则记录局部变量在栈帧中的位置。

符号表管理策略

项目采用了一种高效的符号表管理方式:

  1. 全局变量从符号表起始位置开始存储
  2. 局部变量从符号表末尾向前存储
  3. 使用两个指针GlobsLocls分别跟踪下一个可用的全局和局部符号位置

这种双向填充策略有效利用了符号表空间,同时保持了符号查找的效率。

变量声明处理

项目对变量声明处理进行了重构,通过var_declaration()函数的islocal参数区分全局和局部变量声明:

void var_declaration(int type, int islocal) {
    ...
    if (islocal) {
        addlocl(Text, type, S_VARIABLE, 0, 1);  // 添加局部变量
    } else {
        addglob(Text, type, S_VARIABLE, 0, 1);  // 添加全局变量
    }
    ...
}

x86-64代码生成优化

在代码生成层面,项目实现了以下关键功能:

  1. 局部变量偏移量计算:通过cggetlocaloffset()函数为每个局部变量分配栈空间
  2. 栈对齐处理:确保栈指针按16字节对齐,满足x86-64调用约定
  3. 函数序言和尾声:正确设置和恢复栈指针
void cgfuncpreamble(int id) {
    ...
    stackOffset= (localOffset+15) & ~15;  // 计算对齐后的栈偏移
    fprintf(Outfile, "\taddq\t$%d,%%rsp\n", -stackOffset);
    ...
}

实际案例分析

通过测试程序input25.c,我们可以观察编译器生成的汇编代码:

int main() {
  char z; int y; int x;
  x=10; y=20; z=30;
}

生成的汇编代码展示了局部变量在栈上的布局:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    addq    $-16,%rsp          ; 分配栈空间
    movq    $10, %r8
    movl    %r8d, -12(%rbp)    ; z在-12偏移处
    movq    $20, %r8
    movl    %r8d, -8(%rbp)     ; y在-8偏移处
    movq    $30, %r8
    movb    %r8b, -4(%rbp)     ; x在-4偏移处
    ...

技术要点总结

  1. 作用域管理:通过符号表的class字段实现变量作用域区分
  2. 栈帧布局:局部变量通过负偏移量访问,基于%rbp寄存器
  3. 内存对齐:虽然x86-64对数据访问对齐要求宽松,但栈指针必须16字节对齐
  4. 符号查找findsymbol()函数实现了先局部后全局的查找顺序

展望

本文详细分析了DoctorWkt/acwj项目中局部变量的实现机制。这种实现方式为后续添加函数参数等功能奠定了良好基础。理解这些底层细节对于深入学习编译器设计和x86-64架构都非常有帮助。

建议读者可以尝试扩展这个实现,比如添加更复杂的作用域规则或优化栈空间利用率,这将是对所学知识的很好实践。

acwj A Compiler Writing Journey acwj 项目地址: https://gitcode.com/gh_mirrors/ac/acwj

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邬楠满Seaman

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值