aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-02-24 17:47:39 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-02-24 17:47:39 +0200
commit6b5838f72fe535afb542e888d7d2d2da3571bea2 (patch)
treeaa615a75223027a87ff56c089c0c5b2cc45d00c7 /include
downloadqbt-6b5838f72fe535afb542e888d7d2d2da3571bea2.tar.gz
qbt-6b5838f72fe535afb542e888d7d2d2da3571bea2.zip
initial commit
+ Now to do the actual hard parts, heh
Diffstat (limited to 'include')
-rw-r--r--include/qbt/debug.h74
-rw-r--r--include/qbt/nodes.h253
-rw-r--r--include/qbt/parser.h65
-rw-r--r--include/qbt/vec.h29
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 */