mirror of https://github.com/rui314/chibicc
76 lines
1.3 KiB
C
76 lines
1.3 KiB
C
|
#include "chibicc.h"
|
||
|
|
||
|
static int depth;
|
||
|
|
||
|
static void push(void) {
|
||
|
printf(" push %%rax\n");
|
||
|
depth++;
|
||
|
}
|
||
|
|
||
|
static void pop(char *arg) {
|
||
|
printf(" pop %s\n", arg);
|
||
|
depth--;
|
||
|
}
|
||
|
|
||
|
static void gen_expr(Node *node) {
|
||
|
switch (node->kind) {
|
||
|
case ND_NUM:
|
||
|
printf(" mov $%d, %%rax\n", node->val);
|
||
|
return;
|
||
|
case ND_NEG:
|
||
|
gen_expr(node->lhs);
|
||
|
printf(" neg %%rax\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
gen_expr(node->rhs);
|
||
|
push();
|
||
|
gen_expr(node->lhs);
|
||
|
pop("%rdi");
|
||
|
|
||
|
switch (node->kind) {
|
||
|
case ND_ADD:
|
||
|
printf(" add %%rdi, %%rax\n");
|
||
|
return;
|
||
|
case ND_SUB:
|
||
|
printf(" sub %%rdi, %%rax\n");
|
||
|
return;
|
||
|
case ND_MUL:
|
||
|
printf(" imul %%rdi, %%rax\n");
|
||
|
return;
|
||
|
case ND_DIV:
|
||
|
printf(" cqo\n");
|
||
|
printf(" idiv %%rdi\n");
|
||
|
return;
|
||
|
case ND_EQ:
|
||
|
case ND_NE:
|
||
|
case ND_LT:
|
||
|
case ND_LE:
|
||
|
printf(" cmp %%rdi, %%rax\n");
|
||
|
|
||
|
if (node->kind == ND_EQ)
|
||
|
printf(" sete %%al\n");
|
||
|
else if (node->kind == ND_NE)
|
||
|
printf(" setne %%al\n");
|
||
|
else if (node->kind == ND_LT)
|
||
|
printf(" setl %%al\n");
|
||
|
else if (node->kind == ND_LE)
|
||
|
printf(" setle %%al\n");
|
||
|
|
||
|
printf(" movzb %%al, %%rax\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
error("invalid expression");
|
||
|
}
|
||
|
|
||
|
void codegen(Node *node) {
|
||
|
printf(" .globl main\n");
|
||
|
printf("main:\n");
|
||
|
|
||
|
gen_expr(node);
|
||
|
printf(" ret\n");
|
||
|
|
||
|
assert(depth == 0);
|
||
|
}
|