Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
diohabara committed Aug 2, 2023
1 parent f80b4e7 commit 3d2ae21
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 608 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ tmp*
*.vsix

# for debug
test
.vscode/
tests
ext
test.*
test.s
ext.*
.gdb_history

# stages
stage1/
stage2/
stage3/
Makefile
14 changes: 0 additions & 14 deletions .vscode/settings.json

This file was deleted.

73 changes: 41 additions & 32 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,12 @@ lint:
clang-format -i ./*.c
clang-format -i ./*.h

lintx:
docker run --platform=linux/amd64 -v "${PWD}:/src" -w/src ccc make lint

test: ccc
./ccc tests > tmp.s
echo 'int char_fn() { return 257; }' | gcc -xc -c -o tmp2.o -
echo 'int ext1 = 5; int *ext2 = &ext1;' | gcc -xc -c -o tmp3.o -
echo 'int ext_fn1(int x) { return x; }; int ext_fn2(int x) { return x;}' | gcc -xc -c -o tmp4.o -
gcc -static -o tmp tmp.s tmp2.o tmp3.o tmp4.o
./ccc test/test.c > tmp.s
cat test/helper.c | gcc -xc -c -o tmp2.o -
gcc -static -o tmp tmp.s tmp2.o
./tmp

testx:
docker run --platform=linux/amd64 -v "${PWD}:/src" -w/src ccc make test

clean:
rm -f ccc *.o *~ tmp* stage*/*

Expand All @@ -43,25 +35,42 @@ clean:
# stage2: ccc on X86-64 machine generated by stage1
# stage3: ccc on X86-64 machine generated by stage2

STAGES = stage1 stage2 stage3

define PROCESS_STAGE_RULE
$(1)/%.c: %.c
mkdir -p $(1)
gcc -E -P $$< -o $$@
endef

$(foreach stage,$(STAGES),$(eval $(call PROCESS_STAGE_RULE,$(stage))))

PROCESSED_SRCS = $(foreach stage,$(STAGES),$(addprefix $(stage)/,$(SRCS)))

process: $(PROCESSED_SRCS)

ccc-stage1: $(OBJS)
$(CC) -o $@ $(OBJS) $(CFLAGS)

ccc-stage2:
@echo TODO

ccc-stage3:
@echo TODO
@rm -rf stage1
@mkdir stage1
$(CC) -o stage1/$@ $(OBJS) $(CFLAGS)

ccc-stage2: ccc-stage1 $(SRCS)
@rm -rf stage2
@mkdir stage2
$(CC) -D__ccc_self__ -E -P codegen.c -o stage2/codegen.c
$(CC) -D__ccc_self__ -E -P main.c -o stage2/main.c
$(CC) -D__ccc_self__ -E -P parse.c -o stage2/parse.c
$(CC) -D__ccc_self__ -E -P tokenize.c -o stage2/tokenize.c
$(CC) -D__ccc_self__ -E -P type.c -o stage2/type.c
stage1/ccc-stage1 stage2/codegen.c > stage2/codegen.s
stage1/ccc-stage1 stage2/main.c > stage2/main.s
stage1/ccc-stage1 stage2/parse.c > stage2/parse.s
stage1/ccc-stage1 stage2/tokenize.c > stage2/tokenize.s
stage1/ccc-stage1 stage2/type.c > stage2/type.s
$(CC) -o stage2/$@

ccc-stage3: ccc-stage2 $(SRCS)
@rm -rf stage3
@mkdir stage3
$(CC) -D__ccc_self__ -E -P type.c -o stage3/type.c
$(CC) -D__ccc_self__ -E -P codegen.c -o stage3/codegen.c
$(CC) -D__ccc_self__ -E -P main.c -o stage3/main.c
$(CC) -D__ccc_self__ -E -P parse.c -o stage3/parse.c
$(CC) -D__ccc_self__ -E -P tokenize.c -o stage3/tokenize.c
stage2/ccc-stage2 stage3/codegen.c > stage3/codegen.s
stage2/ccc-stage2 stage3/main.c > stage3/main.s
stage2/ccc-stage2 stage3/parse.c > stage3/parse.s
stage2/ccc-stage2 stage3/tokenize.c > stage3/tokenize.s
stage2/ccc-stage2 stage3/type.c > stage3/type.s
$(CC) -o stage3/$@

test-self-host: ccc-stage1 ccc-stage2 ccc-stage3
strip stage2/ccc-stage2
strip stage3/ccc-stage3
diff -s stage2/ccc-stage2 stage3/ccc-stage3
63 changes: 63 additions & 0 deletions ccc.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,64 @@
#ifdef __ccc_self__

typedef int bool;
typedef int size_t;
typedef void FILE;
typedef void *va_list;

#define SEEK_SET 0
#define SEEK_END 2

// struct _reent {
// int _errno;
// void *_stdin;
// void *_stdout;
// void *_stderr;
// };

extern struct _reent *_impure_ptr;

#define stdin (_impure_ptr->_stdin)
#define stderr (_impure_ptr->_stderr)

extern int errno;

#define __attribute__(x)
#define noreturn

#define NULL (0)
#define true (1)
#define false (0)
#define static

#define assert(x) 1

int printf();
int fopen();
int strncmp();
int strlen();
int fprintf();
char *strerror();
int vsnprintf();
int vfprintf();
void *calloc();
int isalnum();
int isspace();
int snprintf();
int strstr();
int strchr();
int isdigit();
int strtol();
void exit();
int fseek();
int ftell();
int fread();
int fclose();
int realloc();
int ferror();
int feof();

#else

#include <assert.h>
#include <ctype.h>
#include <errno.h>
Expand All @@ -7,6 +68,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#endif
typedef struct Type Type;
typedef struct Member Member;
typedef struct Initializer Initializer;
Expand Down
147 changes: 80 additions & 67 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,78 @@ Program *program() {
return prog;
}

// global-var
// = type-specifier declarator type-suffix ("=" gvar-initializer)? ";"
void global_var() {
Type *ty = type_specifier();
bool is_extern = ty->is_extern;
char *name = NULL;
Token *tok = token;
ty = declarator(ty, &name);
ty = type_suffix(ty);
ty->is_extern = is_extern;

// TODO: write tyepdef here
if (ty->is_typedef) {
expect(";");
ty->is_typedef = false;
push_scope(name)->type_def = ty;
return;
}

Var *var = push_var(name, ty, false, tok);
push_scope(name)->var = var;

if (consume("=")) {
Initializer head;
head.next = NULL;
gvar_initializer(&head, ty);
var->initializer = head.next;
}
expect(";");
}

// function = type-specifier declarator "(" params? ")" ("{" stmt* "}" | ";")
// params = param ("," param)* | "void"
// param = type-specifier declarator type-suffix
Function *function() {
locals = NULL;

Type *ty = type_specifier();
char *name = NULL;
Token *tok = token;
ty = declarator(ty, &name);

// Add a function type to the scope
Var *var = push_var(name, func_type(ty), false, tok);
push_scope(name)->var = var;

// construct a function object
Function *fn = calloc(1, sizeof(Function));
fn->name = name;
fn->is_static = ty->is_static;
expect("(");
fn->params = read_func_params();

if (consume(";")) {
return NULL;
}

// read function body
Node head;
head.next = NULL;
Node *cur = &head;
expect("{");
while (!consume("}")) {
cur->next = stmt();
cur = cur->next;
}

fn->node = head.next;
fn->locals = locals;
return fn;
}

// type-specifier = builtin-type | struct-decl | typedef-name | enum-specifier
// builtin-type = "void"
// | "_Bool"
Expand All @@ -238,6 +310,7 @@ Type *type_specifier() {
SHORT = 1 << 7,
INT = 1 << 9,
LONG = 1 << 11,
UNSIGNED = 1 << 13,
};

int base_type = 0;
Expand All @@ -256,6 +329,8 @@ Type *type_specifier() {
is_static = true;
} else if (consume("extern")) {
is_extern = true;
} else if (consume("const")) {
continue;
} else if (consume("void")) {
base_type += VOID;
} else if (consume("_Bool")) {
Expand All @@ -268,6 +343,8 @@ Type *type_specifier() {
base_type += INT;
} else if (consume("long")) {
base_type += LONG;
} else if (consume("unsigned")) {
base_type += UNSIGNED;
} else if (peek("struct")) {
if (base_type || user_type) {
break;
Expand Down Expand Up @@ -575,47 +652,6 @@ VarList *read_func_params() {
return head;
}

// function = type-specifier declarator "(" params? ")" ("{" stmt* "}" | ";")
// params = param ("," param)* | "void"
// param = type-specifier declarator type-suffix
Function *function() {
locals = NULL;

Type *ty = type_specifier();
char *name = NULL;
Token *tok = token;
ty = declarator(ty, &name);

// Add a function type to the scope
Var *var = push_var(name, func_type(ty), false, tok);
push_scope(name)->var = var;

// construct a function object
Function *fn = calloc(1, sizeof(Function));
fn->name = name;
fn->is_static = ty->is_static;
expect("(");
fn->params = read_func_params();

if (consume(";")) {
return NULL;
}

// read function body
Node head;
head.next = NULL;
Node *cur = &head;
expect("{");
while (!consume("}")) {
cur->next = stmt();
cur = cur->next;
}

fn->node = head.next;
fn->locals = locals;
return fn;
}

// Initializer list can end either with "}" or "," followed by "}" to allow a
// trailing comm. This function returns true if it looks like we are at the end
// of an initializer list
Expand Down Expand Up @@ -773,29 +809,6 @@ Initializer *gvar_initializer(Initializer *cur, Type *ty) {
return new_init_val(cur, size_of(ty, token), addend);
}

// global-var
// = type-specifier declarator type-suffix ("=" gvar-initializer)? ";"
void global_var() {
Type *ty = type_specifier();
bool is_extern = ty->is_extern;
char *name = NULL;
Token *tok = token;
ty = declarator(ty, &name);
ty = type_suffix(ty);
ty->is_extern = is_extern;

Var *var = push_var(name, ty, false, tok);
push_scope(name)->var = var;

if (consume("=")) {
Initializer head;
head.next = NULL;
gvar_initializer(&head, ty);
var->initializer = head.next;
}
expect(";");
}

typedef struct Designator Designator;

struct Designator {
Expand Down Expand Up @@ -995,9 +1008,9 @@ Node *read_expr_stmt() {

bool is_typename() {
return peek("typedef") || peek("void") || peek("_Bool") || peek("char") ||
peek("short") || peek("int") || peek("long") || peek("struct") ||
peek("enum") || peek("static") || peek("extern") ||
find_typedef(token);
peek("unsigned") || peek("short") || peek("int") || peek("long") ||
peek("struct") || peek("enum") || peek("static") || peek("extern") ||
peek("const") || find_typedef(token);
}

// stmt = "return" expr ";"
Expand Down
Loading

0 comments on commit 3d2ae21

Please sign in to comment.