Add char type

This commit is contained in:
Rui Ueyama 2020-08-27 21:04:17 +09:00
parent a4d3223a72
commit be38d63d1b
6 changed files with 45 additions and 12 deletions

View File

@ -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);

View File

@ -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
View File

@ -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);

View File

@ -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

View File

@ -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
View File

@ -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) {