diff --git a/Makefile b/Makefile index b7e93e9..a6e3d13 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +ARCH_TARGET = x86_64 +BACKEND = backend/$(ARCH_TARGET).c + CFILES = $(shell find core/ -name "*.c") OFILES = $(CFILES:.c=.o) DFILES = $(CFILES:.c=.d) @@ -7,7 +10,7 @@ CFLAGS = -Wall -pedantic -Iinc/ -MMD .PHONY: all all: $(OFILES) - $(CC) $(OFILES) -o rifle + $(CC) $(BACKEND) $(CFLAGS) $(OFILES) -o rifle -include $(DFILES) %.o: %.c diff --git a/backend/x86_64.c b/backend/x86_64.c new file mode 100644 index 0000000..07b2b41 --- /dev/null +++ b/backend/x86_64.c @@ -0,0 +1,19 @@ +#include +#include "rifle/mu.h" + +int +mu_gen_label(struct rifle_state *state, const char *name) +{ + if (state == NULL || name == NULL) { + return -1; + } + + fprintf( + state->out_fp, + "%s:\n", + name + ); + + return 0; +} + diff --git a/core/codegen.c b/core/codegen.c new file mode 100644 index 0000000..726ebfa --- /dev/null +++ b/core/codegen.c @@ -0,0 +1,42 @@ +#include +#include +#include "rifle/codegen.h" +#include "rifle/trace.h" +#include "rifle/mu.h" + +static int +resolve_func(struct rifle_state *state, struct ast_node *root) +{ + struct symbol *symbol; + + if (state == NULL || root == NULL) { + return -1; + } + + if ((symbol = root->symbol) == NULL) { + trace_error(state, "internal: no symbol associated with func node\n"); + return -1; + } + + return mu_gen_label(state, symbol->name); +} + +int +cg_resolve_node(struct rifle_state *state, struct ast_node *root) +{ + if (state == NULL || root == NULL) { + return -1; + } + + switch (root->type) { + case AST_FUNC: + if (resolve_func(state, root) < 0) { + return -1; + } + + break; + default: + trace_error(state, "unknown ast node %d\n", root->type); + break; + } +} diff --git a/core/parser.c b/core/parser.c index 4da4e3e..0eaae49 100644 --- a/core/parser.c +++ b/core/parser.c @@ -9,6 +9,7 @@ #include "rifle/types.h" #include "rifle/ast.h" #include "rifle/scope.h" +#include "rifle/codegen.h" /* Symbolic token */ #define symtok(tok) \ @@ -438,6 +439,8 @@ parse_func(struct rifle_state *state, struct token *tok, struct ast_node **res) return -1; } + root->symbol = symbol; + /* EXPECT '(' */ if (parse_expect(state, TT_LPAREN, tok) < 0) { return -1; @@ -468,6 +471,7 @@ parse_func(struct rifle_state *state, struct token *tok, struct ast_node **res) return -1; } + *res = root; return 0; } @@ -501,7 +505,7 @@ static int parse_begin(struct rifle_state *state) { struct token tok; - struct ast_node *root; + struct ast_node *root = NULL; while (parse_scan(state, &tok) == 0) { switch (tok.type) { @@ -523,6 +527,11 @@ parse_begin(struct rifle_state *state) } } + if (root != NULL) { + if (cg_resolve_node(state, root) < 0) + return -1; + } + return 0; } diff --git a/core/state.c b/core/state.c index c61fdaf..9b84fd1 100644 --- a/core/state.c +++ b/core/state.c @@ -16,19 +16,28 @@ rifle_state_init(struct rifle_state *state, const char *in_path) return -1; } + state->out_fp = fopen(ASMOUT, "w"); + if (state->out_fp == NULL) { + close(state->in_fd); + return -1; + } + if (ptrbox_init(&state->ptrbox) < 0) { close(state->in_fd); + fclose(state->out_fp); return -1; } if (symbol_table_init(&state->symtab) < 0) { close(state->in_fd); + fclose(state->out_fp); ptrbox_destroy(&state->ptrbox); return -1; } if (tokbuf_init(&state->tokbuf) < 0) { ptrbox_destroy(&state->ptrbox); + fclose(state->out_fp); symbol_table_destroy(&state->symtab); close(state->in_fd); return -1; @@ -49,4 +58,5 @@ rifle_state_destroy(struct rifle_state *state) state->in_fd = -1; tokbuf_destroy(&state->tokbuf); symbol_table_destroy(&state->symtab); + fclose(state->out_fp); } diff --git a/inc/rifle/ast.h b/inc/rifle/ast.h index b12ba4e..5a4efa4 100644 --- a/inc/rifle/ast.h +++ b/inc/rifle/ast.h @@ -24,12 +24,14 @@ typedef enum { * @dtype: Data type * @left: Left leaf * @right: Right leaf + * @symbol: Symbol associated with node */ struct ast_node { ast_type_t type; struct data_type dtype; struct ast_node *left; struct ast_node *right; + struct symbol *symbol; }; /* diff --git a/inc/rifle/codegen.h b/inc/rifle/codegen.h new file mode 100644 index 0000000..9e5ad0d --- /dev/null +++ b/inc/rifle/codegen.h @@ -0,0 +1,20 @@ +#ifndef RIFLE_CODEGEN_H +#define RIFLE_CODEGEN_H 1 + +#include +#include +#include "rifle/ast.h" +#include "rifle/state.h" + +/* + * Resolve a node and generate assembly code as an + * output. + * + * @state: Compiler state + * @root: Root input node to resolve + * + * Returns zero on success + */ +int cg_resolve_node(struct rifle_state *state, struct ast_node *root); + +#endif /* !RIFLE_CODEGEN_H */ diff --git a/inc/rifle/mu.h b/inc/rifle/mu.h new file mode 100644 index 0000000..6e15746 --- /dev/null +++ b/inc/rifle/mu.h @@ -0,0 +1,18 @@ +#ifndef RIFLE_MU_H +#define RIFLE_MU_H 1 + +#include +#include +#include "rifle/state.h" + +/* + * Generate a named label + * + * @state: Compiler state + * @name: Name of label to generate + * + * Returns zero on success + */ +int mu_gen_label(struct rifle_state *state, const char *name); + +#endif /* !RIFLE_MU_H */ diff --git a/inc/rifle/state.h b/inc/rifle/state.h index 09eeec6..1b67c33 100644 --- a/inc/rifle/state.h +++ b/inc/rifle/state.h @@ -2,6 +2,7 @@ #define RIFLE_STATE_H 1 #include +#include #include #include "rifle/tokbuf.h" #include "rifle/ptrbox.h" @@ -11,10 +12,14 @@ /* Maximum scope depth */ #define SCOPE_STACK_MAX 8 +/* Default assembly output path */ +#define ASMOUT "rifleout.asm" + /* * Represents the compiler state * * @in_fd: Input file descriptor + * @out_fp: Output file * @line_num: Current line number * @pass_num: Current pass * @tokbuf: Global token buffer @@ -27,6 +32,7 @@ */ struct rifle_state { int in_fd; + FILE *out_fp; size_t line_num; size_t pass_num; struct tokbuf tokbuf;