diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/qbt/debug.h | 74 | ||||
| -rw-r--r-- | include/qbt/nodes.h | 253 | ||||
| -rw-r--r-- | include/qbt/parser.h | 65 | ||||
| -rw-r--r-- | include/qbt/vec.h | 29 |
4 files changed, 421 insertions, 0 deletions
diff --git a/include/qbt/debug.h b/include/qbt/debug.h new file mode 100644 index 0000000..525ad0d --- /dev/null +++ b/include/qbt/debug.h @@ -0,0 +1,74 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include <stdio.h> + +/* quite a lot of DNA shared with ek, + * should I make a shared library out of this or something? */ + +struct file_ctx { + const char *fname; + const char *fbuf; +}; + +enum issue_level { + SRC_INFO, + SRC_WARN, + SRC_ERROR, +}; + +struct src_loc { + int first_line; + int last_line; + int first_col; + int last_col; +}; + +struct src_issue { + enum issue_level level; + struct src_loc loc; + struct file_ctx fctx; +}; + +void src_issue(struct src_issue issue, const char *err_msg, ...); + +void internal_error(const char *fmt, ...); +void internal_warn(const char *fmt, ...); + +#if DEBUG +/** + * Print debugging message. Only active if \c DEBUG is defined, + * + * @param x Format string. Follows standard printf() formatting. + */ +#define debug(x, ...) \ + do {fprintf(stderr, "debug: " x "\n",##__VA_ARGS__);} while(0) +#else +#define debug(x, ...) +#endif + +/** + * Print error message. + * + * @param x Format string. Follows standard printf() formatting. + */ +#define error(x, ...) \ + do {fprintf(stderr, "error: " x "\n",##__VA_ARGS__);} while(0) + +/** + * Print warning message. + * + * @param x Format string. Follows standard printf() formatting. + */ +#define warn(x, ...) \ + do {fprintf(stderr, "warn: " x "\n",##__VA_ARGS__);} while(0) + +/** + * Print info message. + * + * @param x Format string. Follows standard printf() formatting. + */ +#define info(x, ...) \ + do {fprintf(stderr, "info: " x "\n",##__VA_ARGS__);} while(0) + +#endif /* DEBUG_H */ diff --git a/include/qbt/nodes.h b/include/qbt/nodes.h new file mode 100644 index 0000000..0821663 --- /dev/null +++ b/include/qbt/nodes.h @@ -0,0 +1,253 @@ +#ifndef NODES_H +#define NODES_H + +#include <stdint.h> +#include <stdbool.h> + +#include <qbt/vec.h> + +enum insn_type { + ADD, + SUB, + MUL, + DIV, + REM, + CALL, + LABEL, + STORE, + LOAD, + ALLOC, + COPY, + MOVE, + EQ, + NE, + LE, + GE, + LT, + GT, + NOT, + NEG, + LSHIFT, + RSHIFT, + BEQ, + BNE, + BLE, + BGE, + BLT, + BGT, + J, + RET, + ARG, + PARAM, + RETVAL, +}; + +#define FOREACH_INSN_TYPE(M)\ + M(ADD)\ + M(SUB)\ + M(MUL)\ + M(DIV)\ + M(REM)\ + M(CALL)\ + M(LABEL)\ + M(STORE)\ + M(LOAD)\ + M(ALLOC)\ + M(COPY)\ + M(MOVE)\ + M(EQ)\ + M(NE)\ + M(LE)\ + M(GE)\ + M(LT)\ + M(GT)\ + M(NOT)\ + M(NEG)\ + M(LSHIFT)\ + M(RSHIFT)\ + M(BEQ)\ + M(BNE)\ + M(BLE)\ + M(BGE)\ + M(BLT)\ + M(BGT)\ + M(J)\ + M(ARG)\ + M(PARAM)\ + M(RET)\ + M(RETVAL)\ + +enum val_class { + REG, + TMP, + IMM, + MEM, + REF, + NOCLASS, +}; + +enum val_type { + NOTYPE, I9, I27 +}; + +struct val { + enum val_class class; + int64_t r; + union { + int64_t v; + const char *s; + }; +}; + +struct insn { + enum insn_type type; + enum val_type vtype; + struct val out; + struct val in[2]; +}; + +struct blk { + const char *name; + int64_t id; + enum insn_type btype; + struct val cmp[2]; + struct blk *s1; + struct blk *s2; + struct vec insns; + + /* used to temporarily store label targets */ + const char *to; +}; + +struct fn { + const char *name; + size_t ntmp; + size_t nblk; + struct vec blks; + struct vec labels; + struct vec tmps; +}; + +static inline bool hasclass(struct val v) +{ + return v.class != NOCLASS; +} + +static inline bool hasnoclass(struct val v) +{ + return v.class == NOCLASS; +} + +static inline struct val noclass() +{ + return (struct val){ + .class = NOCLASS, + .r = 0, + .v = 0, + }; +} + +static inline struct val imm_ref(const char *s) +{ + return (struct val){ + .class = REF, + .r = 0, + .s = s, + }; +} + +static inline struct val mem_val(int64_t base, int64_t offset) +{ + return (struct val){ + .class = MEM, + .r = base, + .v = offset, + }; +} + +static inline struct val imm_val(int64_t imm, int64_t type) +{ + return (struct val) { + .class = IMM, + .r = type, + .v = imm, + }; +} + +static inline struct val tmp_val(int64_t t) +{ + return (struct val) { + .class = TMP, + .r = t, + .v = 0, + }; +} + +static inline struct insn insn_create(enum insn_type o, enum val_type t, struct val r, struct val a0, struct val a1) +{ + return (struct insn) { + .type = o, + .vtype = t, + .out = r, + .in = {a0, a1} + }; +} + +int64_t idalloc(struct fn *f, const char *id); +int64_t idmatch(struct fn *f, const char *id); + +void insadd(struct blk *b, enum insn_type o, enum val_type t, struct val r, struct val a0, struct val a1); + +void finish_block(struct blk *b, enum insn_type cmp, struct val a0, struct val a1, const char *label); +struct blk *new_block(struct fn *f); +void destroy_block(struct blk *b); + +void finish_function(struct fn *f, const char *name); +struct fn *new_function(); +void dump_function(struct fn *f); +void destroy_function(struct fn *f); + +void new_label(struct fn *f, struct blk *b, const char *name); + +static inline bool empty_block(struct blk *b) { + return vec_len(&b->insns) == 0; +} + +struct tmp_map { + const char *id; + int64_t v; +}; + +struct label_map { + const char *id; + struct blk *b; +}; + +#define tmp_at(v, i)\ + vect_at(struct tmp_map, v, i) + +#define foreach_tmp(iter, tmps) \ + foreach_vec(iter, tmps) + +#define blk_at(v, i)\ + vect_at(struct blk *, v, i) + +#define blk_pop(v)\ + vect_pop(struct blk *, v) + +#define foreach_blk(iter, blocks)\ + foreach_vec(iter, blocks) + +#define label_at(v, i)\ + vect_at(struct label_map, v, i) + +#define foreach_label(iter, labels)\ + foreach_vec(iter, labels) + +#define insn_at(v, i)\ + vect_at(struct insn, v, i) + +#define foreach_insn(iter, insns)\ + foreach_vec(iter, insns) + +#endif /* NODES_H */ diff --git a/include/qbt/parser.h b/include/qbt/parser.h new file mode 100644 index 0000000..34912c9 --- /dev/null +++ b/include/qbt/parser.h @@ -0,0 +1,65 @@ +#ifndef PARSER_H +#define PARSER_H + +#include <stdbool.h> +#include <qbt/nodes.h> +#include <qbt/vec.h> + +struct fn_map { + const char *id; + struct fn *fn; +}; + +struct data_map { + const char *id; + struct data *data; +}; + +struct parser { + bool failed; + void *lexer; + + const char *buf; + const char *fname; + + /* generic index used to count args, params, ret... */ + size_t idx; + + size_t comment_nesting; + + struct vec fns; + struct vec datas; + /* the parser owns all strings, could maybe be moved to a helper + * resource handler or something in the future */ + struct vec strs; + + /* current function */ + struct fn *f; + + /* current block of current function */ + struct blk *b; +}; + +struct parser *create_parser(); +void parse(struct parser *p, const char *fname, const char *buf); +void destroy_parser(struct parser *p); + +#define foreach_fn(iter, v)\ + foreach_vec(iter, v) + +#define foreach_data(iter, v)\ + foreach_vec(iter, v) + +#define foreach_str(iter, v)\ + foreach_vec(iter, v) + +#define fn_at(v, i)\ + vect_at(struct fn_map, v, i) + +#define data_at(v, i)\ + vect_at(struct data_map, v, i) + +#define str_at(v, i)\ + vect_at(char *, v, i) + +#endif /* PARSER_H */ diff --git a/include/qbt/vec.h b/include/qbt/vec.h new file mode 100644 index 0000000..727c110 --- /dev/null +++ b/include/qbt/vec.h @@ -0,0 +1,29 @@ +#ifndef VEC_H +#define VEC_H + +#include <stddef.h> + +struct vec { + size_t n; + size_t s; + size_t ns; + void *buf; +}; + +struct vec vec_create(size_t s); +void vec_destroy(struct vec *v); +size_t vec_len(struct vec *v); +void *vec_at(struct vec *v, size_t i); +void *vec_pop(struct vec *v); +void vec_append(struct vec *v, void *n); + +#define foreach_vec(iter, v)\ + for (size_t iter = 0, __n = vec_len(&v); iter < __n; ++iter) + +#define vect_at(type, v, i)\ + *(type *)vec_at(&v, i) + +#define vect_pop(type, v)\ + *(type *)vec_pop(&v) + +#endif /* VEC_H */ |
