mirror of https://github.com/rui314/chibicc
Add char type
This commit is contained in:
parent
a4d3223a72
commit
be38d63d1b
|
@ -125,6 +125,7 @@ Obj *parse(Token *tok);
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
TY_CHAR,
|
||||||
TY_INT,
|
TY_INT,
|
||||||
TY_PTR,
|
TY_PTR,
|
||||||
TY_FUNC,
|
TY_FUNC,
|
||||||
|
@ -157,6 +158,7 @@ struct Type {
|
||||||
Type *next;
|
Type *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern Type *ty_char;
|
||||||
extern Type *ty_int;
|
extern Type *ty_int;
|
||||||
|
|
||||||
bool is_integer(Type *ty);
|
bool is_integer(Type *ty);
|
||||||
|
|
28
codegen.c
28
codegen.c
|
@ -1,7 +1,8 @@
|
||||||
#include "chibicc.h"
|
#include "chibicc.h"
|
||||||
|
|
||||||
static int depth;
|
static int depth;
|
||||||
static char *argreg[] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"};
|
static char *argreg8[] = {"%dil", "%sil", "%dl", "%cl", "%r8b", "%r9b"};
|
||||||
|
static char *argreg64[] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"};
|
||||||
static Obj *current_fn;
|
static Obj *current_fn;
|
||||||
|
|
||||||
static void gen_expr(Node *node);
|
static void gen_expr(Node *node);
|
||||||
|
@ -60,13 +61,20 @@ static void load(Type *ty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" mov (%%rax), %%rax\n");
|
if (ty->size == 1)
|
||||||
|
printf(" movsbq (%%rax), %%rax\n");
|
||||||
|
else
|
||||||
|
printf(" mov (%%rax), %%rax\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store %rax to an address that the stack top is pointing to.
|
// Store %rax to an address that the stack top is pointing to.
|
||||||
static void store(void) {
|
static void store(Type *ty) {
|
||||||
pop("%rdi");
|
pop("%rdi");
|
||||||
printf(" mov %%rax, (%%rdi)\n");
|
|
||||||
|
if (ty->size == 1)
|
||||||
|
printf(" mov %%al, (%%rdi)\n");
|
||||||
|
else
|
||||||
|
printf(" mov %%rax, (%%rdi)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate code for a given node.
|
// Generate code for a given node.
|
||||||
|
@ -94,7 +102,7 @@ static void gen_expr(Node *node) {
|
||||||
gen_addr(node->lhs);
|
gen_addr(node->lhs);
|
||||||
push();
|
push();
|
||||||
gen_expr(node->rhs);
|
gen_expr(node->rhs);
|
||||||
store();
|
store(node->ty);
|
||||||
return;
|
return;
|
||||||
case ND_FUNCALL: {
|
case ND_FUNCALL: {
|
||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
|
@ -105,7 +113,7 @@ static void gen_expr(Node *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = nargs - 1; i >= 0; i--)
|
for (int i = nargs - 1; i >= 0; i--)
|
||||||
pop(argreg[i]);
|
pop(argreg64[i]);
|
||||||
|
|
||||||
printf(" mov $0, %%rax\n");
|
printf(" mov $0, %%rax\n");
|
||||||
printf(" call %s\n", node->funcname);
|
printf(" call %s\n", node->funcname);
|
||||||
|
@ -246,8 +254,12 @@ static void emit_text(Obj *prog) {
|
||||||
|
|
||||||
// Save passed-by-register arguments to the stack
|
// Save passed-by-register arguments to the stack
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Obj *var = fn->params; var; var = var->next)
|
for (Obj *var = fn->params; var; var = var->next) {
|
||||||
printf(" mov %s, %d(%%rbp)\n", argreg[i++], var->offset);
|
if (var->ty->size == 1)
|
||||||
|
printf(" mov %s, %d(%%rbp)\n", argreg8[i++], var->offset);
|
||||||
|
else
|
||||||
|
printf(" mov %s, %d(%%rbp)\n", argreg64[i++], var->offset);
|
||||||
|
}
|
||||||
|
|
||||||
// Emit code
|
// Emit code
|
||||||
gen_stmt(fn->body);
|
gen_stmt(fn->body);
|
||||||
|
|
14
parse.c
14
parse.c
|
@ -118,8 +118,13 @@ static int get_number(Token *tok) {
|
||||||
return tok->val;
|
return tok->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// declspec = "int"
|
// declspec = "char" | "int"
|
||||||
static Type *declspec(Token **rest, Token *tok) {
|
static Type *declspec(Token **rest, Token *tok) {
|
||||||
|
if (equal(tok, "char")) {
|
||||||
|
*rest = tok->next;
|
||||||
|
return ty_char;
|
||||||
|
}
|
||||||
|
|
||||||
*rest = skip(tok, "int");
|
*rest = skip(tok, "int");
|
||||||
return ty_int;
|
return ty_int;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +209,11 @@ static Node *declaration(Token **rest, Token *tok) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if a given token represents a type.
|
||||||
|
static bool is_typename(Token *tok) {
|
||||||
|
return equal(tok, "char") || equal(tok, "int");
|
||||||
|
}
|
||||||
|
|
||||||
// stmt = "return" expr ";"
|
// stmt = "return" expr ";"
|
||||||
// | "if" "(" expr ")" stmt ("else" stmt)?
|
// | "if" "(" expr ")" stmt ("else" stmt)?
|
||||||
// | "for" "(" expr-stmt expr? ";" expr? ")" stmt
|
// | "for" "(" expr-stmt expr? ";" expr? ")" stmt
|
||||||
|
@ -270,7 +280,7 @@ static Node *compound_stmt(Token **rest, Token *tok) {
|
||||||
Node head = {};
|
Node head = {};
|
||||||
Node *cur = &head;
|
Node *cur = &head;
|
||||||
while (!equal(tok, "}")) {
|
while (!equal(tok, "}")) {
|
||||||
if (equal(tok, "int"))
|
if (is_typename(tok))
|
||||||
cur = cur->next = declaration(&tok, tok);
|
cur = cur->next = declaration(&tok, tok);
|
||||||
else
|
else
|
||||||
cur = cur->next = stmt(&tok, tok);
|
cur = cur->next = stmt(&tok, tok);
|
||||||
|
|
8
test.sh
8
test.sh
|
@ -163,4 +163,12 @@ assert 3 'int x[4]; int main() { x[0]=0; x[1]=1; x[2]=2; x[3]=3; return x[3]; }'
|
||||||
assert 8 'int x; int main() { return sizeof(x); }'
|
assert 8 'int x; int main() { return sizeof(x); }'
|
||||||
assert 32 'int x[4]; int main() { return sizeof(x); }'
|
assert 32 'int x[4]; int main() { return sizeof(x); }'
|
||||||
|
|
||||||
|
assert 1 'int main() { char x=1; return x; }'
|
||||||
|
assert 1 'int main() { char x=1; char y=2; return x; }'
|
||||||
|
assert 2 'int main() { char x=1; char y=2; return y; }'
|
||||||
|
|
||||||
|
assert 1 'int main() { char x; return sizeof(x); }'
|
||||||
|
assert 10 'int main() { char x[10]; return sizeof(x); }'
|
||||||
|
assert 1 'int main() { return sub_char(7, 3, 3); } int sub_char(char a, char b, char c) { return a-b-c; }'
|
||||||
|
|
||||||
echo OK
|
echo OK
|
||||||
|
|
|
@ -90,7 +90,7 @@ static int read_punct(char *p) {
|
||||||
|
|
||||||
static bool is_keyword(Token *tok) {
|
static bool is_keyword(Token *tok) {
|
||||||
static char *kw[] = {
|
static char *kw[] = {
|
||||||
"return", "if", "else", "for", "while", "int", "sizeof",
|
"return", "if", "else", "for", "while", "int", "sizeof", "char",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)
|
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)
|
||||||
|
|
3
type.c
3
type.c
|
@ -1,9 +1,10 @@
|
||||||
#include "chibicc.h"
|
#include "chibicc.h"
|
||||||
|
|
||||||
|
Type *ty_char = &(Type){TY_CHAR, 1};
|
||||||
Type *ty_int = &(Type){TY_INT, 8};
|
Type *ty_int = &(Type){TY_INT, 8};
|
||||||
|
|
||||||
bool is_integer(Type *ty) {
|
bool is_integer(Type *ty) {
|
||||||
return ty->kind == TY_INT;
|
return ty->kind == TY_CHAR || ty->kind == TY_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *copy_type(Type *ty) {
|
Type *copy_type(Type *ty) {
|
||||||
|
|
Loading…
Reference in New Issue