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

    每个节点生成的指令都是一个长长的指令列表,那么得弄几个小工具将这些列表给连接起来。

// 将一个指令追加到表末尾
static struct List* appendIns(struct List* list, void* ins)
{
    list->addTo(list, ins, list->count(list));
    return list;
}

// 将 back 连接到 front 之后
static struct List* appendInsList(struct List* front, struct List* back)
{
    while (0 != back->count(back)) {
        appendIns(front, back->popElementAt(back, 0));
    }
    back->finalize(back);
    return front;
}
// 这两个函数的返回值设计是为了支持链式操作,所以……
// 有些代码可能看起来很晕

 

    指令生成,先挑简单的上。

BasicBlockNode

    在符号表那里定义过两个函数 enterBasicBlock 和 leaveBasicBlock,现在它们要被调用了。

struct List* insBasicBlockNode(void* node)
{
    struct BasicBlockNode* self = (struct BasicBlockNode*)node;
    enterBasicBlock();
    struct List* list = (struct List*)newArrayList(),* sublist;
    struct AbstractSyntaxNode* sub = self->block;
    while (NULL != sub) {
        sublist = sub->createInstruction(sub);
        appendInsList(list, sublist);
        sub = sub->nextNode;
    }
    leaveBasicBlock();
    return list;
}

这两个调用的中间,基本块的生成了内部每个语句的指令,将它们全部拼接在一起。

IntegerNodeRealNode

    这两个嘛……

struct List* insIntegerNode(void* node)
{
    struct List* list = (struct List*)newArrayList();
    struct IntParamInstruction* loadInt = (struct IntParamInstruction*)
                                   allocate(sizeof(struct IntParamInstruction));
    loadInt->code = CONST_INT;
    loadInt->param = ((struct IntegerNode*)node)->intValue;
    appendIns(list, loadInt);
    return list;
}

struct List* insRealNode(void* node)
{
    struct List* list = (struct List*)newArrayList();
    struct RealParamInstruction* loadReal = (struct RealParamInstruction*)
                                  allocate(sizeof(struct RealParamInstruction));
    loadReal->code = CONST_REAL;
    loadReal->param = ((struct RealNode*)node)->realValue;
    appendIns(list, loadReal);
    return list;
}

小心,LOAD_XXXX 指的是从内存某个地址上取一个数到栈顶,而这里用到的是 CONST_XXX,是直接将指令中的常数放在栈顶。

ArithmaticNode

struct List* insArithmaticNode(void* node)
{
    struct AbstractValueNode* arith = ((struct ArithmaticNode*)node)->arith;
    AcceptType type = arith->typeOf(arith); // 取得算式的类型
    struct List* insList = arith->createInstruction(arith);
    struct IntParamInstruction* pop = (struct IntParamInstruction*)
                                   allocate(sizeof(struct IntParamInstruction));
    pop->code = POP; // 算式结束后,弹出栈顶的数
    // 根据类型确定该怎么来弹
    if (INTEGER == type) {
        pop->param = INT_SIZE;
    } else {
        pop->param = REAL_SIZE;
    }
    appendIns(insList, pop);
    return insList;
}

VariableNode

    Q:这个难道会很简单?

    A:有的时候我们得把架子搭在没有实现的东西上面。

struct List* insVariableNode(void* node)
{
    struct List* getAddr = addrOfVar(node); // here,先用着再说
    struct NoParamInstruction* loadVal = (struct NoParamInstruction*)
                                    allocate(sizeof(struct NoParamInstruction));
    loadVal->code = (INTEGER == ((struct VariableNode*)node)->typeOf(node)) ?
                    LOAD_INT : LOAD_REAL; // 确定类型
    return appendIns(getAddr, loadVal); // 把 LOAD 指令加上
}

下回分解:

    流程控制语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值