[指令生成]语法制导的指令生成[3]

首先回顾一下符号表提供的接口

AcceptType typeOf(struct VariableNode* var);
int staticOffset(struct VariableNode* var, int* offsets);

 前面一个获取类型在这里并不是特别需要——那是在加载变量值的时候考虑的。至于 staticOffset 这个函数,功能已经非常强大了,我们现在要做的就是,计算运行时才能确定的地址。先搭个架子,明确一下我们要干的主要工作

struct List* addrOfVar(void* node)
{
    struct VariableNode* self = (struct VariableNode*)node;
    struct List* insList = (struct List*)newArrayList();
    // 获取维数
    int addr, nrDim = self->dimInfor->length(self->dimInfor);
    struct IntParamInstruction* loadBase = (struct IntParamInstruction*)
                                   allocate(sizeof(struct IntParamInstruction));
    loadBase->code = CONST_INT;
    appendIns(insList, loadBase);
    if (0 == nrDim) { // 普通变量, 静态时就能确定地址.
        loadBase->param = staticOffset(self, NULL);
    } else {
        // 是数组, 这里是我们要做的
    }
    return insList;
}

当然首先得用符号表的接口,像这样

int* dims = (int*)allocate(nrDim * sizeof(int)); // 申请一块空间, 用来存放数组大小信息
int i;
struct IntParamInstruction* loadOffset;
struct NoParamInstruction* cast,* mult,* add;
struct AbstractValueNode* value;
addr = staticOffset(self, dims); // 取~
loadBase->param = addr;
// 这里增加指令
revert(dims); // 记得干掉这些空间. PS: GCC似乎是支持在栈中直接写变长数组的, 如 int dim[nrDim];

剩下的就是一个筛选过程了,筛选传入的数组中那些值为 -1 的项目,不过呢,因为我们没有限定数组下标必须是整数(声明时必须是,但是引用时可以是实型量),因此我们还要承担变量转型的责任(注意到上面的代码中,声明的无参数指令中有一个叫做 cast

for (i = 0; i < nrDim; ++i) {
    if (-1 != dims[i]) { // 这一维是变量~
        loadOffset = (struct IntParamInstruction*)
                           allocate(sizeof(struct IntParamInstruction));
        loadOffset->code = CONST_INT;
        loadOffset->param = dims[i]; // 取数组这一维的偏移量(还记得吧, 是偏移量哦)
        appendIns(insList, loadOffset);
        value = (struct AbstractValueNode*)
                (self->dimInfor->peekAt(self->dimInfor, i));
        appendInsList(insList, value->createInstruction(value)); // 下标的指令
        if (REAL == value->typeOf(value)) { // 如果是实型, 转型
            cast = (struct NoParamInstruction*)
                           allocate(sizeof(struct NoParamInstruction));
            cast->code = REAL_2_INT;
            appendIns(insList, cast);
        }
        mult = (struct NoParamInstruction*)
                           allocate(sizeof(struct NoParamInstruction));
        mult->code = INT_MULTIPLY; // 将偏移量和下标相乘
        appendIns(insList, mult);
        add = (struct NoParamInstruction*)
                           allocate(sizeof(struct NoParamInstruction));
        add->code = INT_PLUS; // 累加
        appendIns(insList, add);
    }
}

这样就完成了变量取址。还原一个完整的函数

struct List* addrOfVar(void* node)
{
    struct VariableNode* self = (struct VariableNode*)node;
    struct List* insList = (struct List*)newArrayList();
    int addr, nrDim = self->dimInfor->length(self->dimInfor);
    struct IntParamInstruction* loadBase = (struct IntParamInstruction*)
                                   allocate(sizeof(struct IntParamInstruction));
    loadBase->code = CONST_INT;
    appendIns(insList, loadBase);
    if (0 == nrDim) {
        loadBase->param = staticOffset(self, NULL);
    } else {
        int* dims = (int*)allocate(nrDim * sizeof(int));
        int i;
        struct IntParamInstruction* loadOffset;
        struct NoParamInstruction* cast,* mult,* add;
        struct AbstractValueNode* value;
        addr = staticOffset(self, dims);
        loadBase->param = addr;
        for (i = 0; i < nrDim; ++i) {
            if (-1 != dims[i]) {
                loadOffset = (struct IntParamInstruction*)
                                   allocate(sizeof(struct IntParamInstruction));
                loadOffset->code = CONST_INT;
                loadOffset->param = dims[i];
                appendIns(insList, loadOffset);
                value = (struct AbstractValueNode*)
                        (self->dimInfor->peekAt(self->dimInfor, i));
                appendInsList(insList, value->createInstruction(value));
                if (REAL == value->typeOf(value)) {
                    cast = (struct NoParamInstruction*)
                                   allocate(sizeof(struct NoParamInstruction));
                    cast->code = REAL_2_INT;
                    appendIns(insList, cast);
                }
                mult = (struct NoParamInstruction*)
                                   allocate(sizeof(struct NoParamInstruction));
                mult->code = INT_MULTIPLY;
                appendIns(insList, mult);
                add = (struct NoParamInstruction*)
                                   allocate(sizeof(struct NoParamInstruction));
                add->code = INT_PLUS;
                appendIns(insList, add);
            }
        }
        revert(dims);
    }
    return insList;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值