commit 8da76fb718bc17bc9b3993935393bce14a8586df
parent 31b201a7c616fa09319dc433792fb968a8b9655f
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 20 Dec 2020 09:00:22 -0500
Lay out riggings for qbe abstraction
This should be MUCH simpler than the one used for v1, albiet somewhat
less strongly typed. Should be worth the tradeoff in terms of simplicity
and readability of the resulting code.
Diffstat:
M | configure | | | 1 | + |
A | include/qbe.h | | | 191 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/gen.c | | | 3 | +++ |
A | src/qbe.c | | | 134 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 329 insertions(+), 0 deletions(-)
diff --git a/configure b/configure
@@ -10,6 +10,7 @@ harec() {
src/lex.c \
src/main.c \
src/parse.c \
+ src/qbe.c \
src/trace.c \
src/type_store.c \
src/types.c \
diff --git a/include/qbe.h b/include/qbe.h
@@ -0,0 +1,191 @@
+#ifndef HAREC_QBE_H
+#define HAREC_QBE_H
+#include <stdarg.h>
+#include <stdint.h>
+
+enum qbe_stype {
+ Q_BYTE = 'b',
+ Q_HALF = 'h',
+ Q_WORD = 'w',
+ Q_LONG = 'l',
+ Q_SINGLE = 's',
+ Q_DOUBLE = 'd',
+ Q__AGGREGATE,
+ Q__VOID,
+};
+
+struct qbe_type {
+ enum qbe_stype stype;
+ // TODO: Aggregate type details
+};
+
+// Simple type singletons
+extern const struct qbe_type
+ qbe_byte,
+ qbe_half,
+ qbe_word,
+ qbe_long,
+ qbe_single,
+ qbe_double;
+
+enum qbe_value_kind {
+ QV_CONST,
+ QV_GLOBAL,
+ QV_LABEL,
+ QV_TEMPORARY,
+};
+
+struct qbe_value {
+ enum qbe_value_kind kind;
+ const struct qbe_type *type;
+ union {
+ char *name;
+ // TODO: const storage
+ };
+};
+
+enum qbe_instr {
+ Q_ADD,
+ Q_ALLOC16,
+ Q_ALLOC4,
+ Q_ALLOC8,
+ Q_AND,
+ Q_CEQD,
+ Q_CEQL,
+ Q_CEQS,
+ Q_CEQW,
+ Q_CGED,
+ Q_CGES,
+ Q_CGTD,
+ Q_CGTS,
+ Q_CLED,
+ Q_CLES,
+ Q_CLTD,
+ Q_CLTS,
+ Q_CNED,
+ Q_CNEL,
+ Q_CNES,
+ Q_CNEW,
+ Q_COD,
+ Q_COS,
+ Q_CSGEL,
+ Q_CSGEW,
+ Q_CSGTL,
+ Q_CSGTW,
+ Q_CSLEL,
+ Q_CSLEW,
+ Q_CSLTL,
+ Q_CSLTW,
+ Q_CUGEL,
+ Q_CUGEW,
+ Q_CUGTL,
+ Q_CUGTW,
+ Q_CULEL,
+ Q_CULEW,
+ Q_CULTL,
+ Q_CULTW,
+ Q_CUOD,
+ Q_CUOS,
+ Q_DIV,
+ Q_DTOSI,
+ Q_EXTS,
+ Q_EXTSB,
+ Q_EXTSH,
+ Q_EXTSW,
+ Q_EXTUB,
+ Q_EXTUH,
+ Q_EXTUW,
+ Q_JMP,
+ Q_JNZ,
+ Q_LOADD,
+ Q_LOADL,
+ Q_LOADS,
+ Q_LOADSB,
+ Q_LOADSH,
+ Q_LOADSW,
+ Q_LOADUB,
+ Q_LOADUH,
+ Q_LOADUW,
+ Q_MUL,
+ Q_OR,
+ Q_REM,
+ Q_RET,
+ Q_SAR,
+ Q_SHL,
+ Q_SHR,
+ Q_SLTOF,
+ Q_STOREB,
+ Q_STORED,
+ Q_STOREH,
+ Q_STOREL,
+ Q_STORES,
+ Q_STOREW,
+ Q_STOSI,
+ Q_SUB,
+ Q_SWTOF,
+ Q_TRUNCD,
+ Q_UDIV,
+ Q_UREM,
+ Q_XOR,
+
+ Q_LAST_INSTR,
+};
+
+extern const char *qbe_instr[Q_LAST_INSTR];
+
+enum qbe_statement_type {
+ Q_INSTR,
+ Q_LABEL,
+};
+
+struct qbe_arguments {
+ struct qbe_value value;
+ struct qbe_arguments *next;
+};
+
+struct qbe_statement {
+ enum qbe_statement_type type;
+ union {
+ struct {
+ enum qbe_instr instr;
+ struct qbe_arguments *args;
+ };
+ char *label;
+ };
+};
+
+struct qbe_func {
+ char *name;
+ // TODO: Parameters, return type
+ size_t blen, bsiz;
+ struct qbe_statement *body;
+};
+
+enum qbe_deftype {
+ Q_TYPE,
+ Q_FUNC,
+ Q_DATA,
+};
+
+struct qbe_def {
+ enum qbe_deftype type;
+ union {
+ struct qbe_func func;
+ };
+ struct qbe_def *next;
+};
+
+struct qbe_program {
+ struct qbe_def *defs;
+};
+
+// The "i" family of functions take a list of qbe_values as the parameters to
+// provide to the given instruction. The "l" family takes a printf-compatible
+// set of values to match with fmt to produce the label name (plus the ID
+// postfix, which is added for you).
+void geni(struct qbe_statement *stmt, enum qbe_instr instr, ...);
+void genl(struct qbe_statement *stmt, uint64_t *id, const char *fmt, ...);
+void pushi(struct qbe_func *func, enum qbe_instr instr, ...);
+void pushl(struct qbe_func *func, uint64_t *id, const char *fmt, ...);
+
+#endif
diff --git a/src/gen.c b/src/gen.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -6,12 +7,14 @@
#include "expr.h"
#include "gen.h"
#include "identifier.h"
+#include "qbe.h"
#include "trace.h"
#include "types.h"
struct gen_context {
FILE *out;
struct identifier *ns;
+ uint64_t id;
};
static char *
diff --git a/src/qbe.c b/src/qbe.c
@@ -0,0 +1,134 @@
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "qbe.h"
+
+// Simple type singletons
+const struct qbe_type
+qbe_byte = {
+ .stype = Q_BYTE,
+},
+qbe_half = {
+ .stype = Q_HALF,
+},
+qbe_word = {
+ .stype = Q_WORD,
+},
+qbe_long = {
+ .stype = Q_LONG,
+},
+qbe_single = {
+ .stype = Q_SINGLE,
+},
+qbe_double = {
+ .stype = Q_DOUBLE,
+};
+
+const char *qbe_instr[Q_LAST_INSTR] = {
+ [Q_ADD] = "add",
+ [Q_ALLOC16] = "alloc16",
+ [Q_ALLOC4] = "alloc4",
+ [Q_ALLOC8] = "alloc8",
+ [Q_AND] = "and",
+ [Q_CEQD] = "ceqd",
+ [Q_CEQL] = "ceql",
+ [Q_CEQS] = "ceqs",
+ [Q_CEQW] = "ceqw",
+ [Q_CGED] = "cged",
+ [Q_CGES] = "cges",
+ [Q_CGTD] = "cgtd",
+ [Q_CGTS] = "cgts",
+ [Q_CLED] = "cled",
+ [Q_CLES] = "cles",
+ [Q_CLTD] = "cltd",
+ [Q_CLTS] = "clts",
+ [Q_CNED] = "cned",
+ [Q_CNEL] = "cnel",
+ [Q_CNES] = "cnes",
+ [Q_CNEW] = "cnew",
+ [Q_COD] = "cod",
+ [Q_COS] = "cos",
+ [Q_CSGEL] = "csgel",
+ [Q_CSGEW] = "csgew",
+ [Q_CSGTL] = "csgtl",
+ [Q_CSGTW] = "csgtw",
+ [Q_CSLEL] = "cslel",
+ [Q_CSLEW] = "cslew",
+ [Q_CSLTL] = "csltl",
+ [Q_CSLTW] = "csltw",
+ [Q_CUGEL] = "cugel",
+ [Q_CUGEW] = "cugew",
+ [Q_CUGTL] = "cugtl",
+ [Q_CUGTW] = "cugtw",
+ [Q_CULEL] = "culel",
+ [Q_CULEW] = "culew",
+ [Q_CULTL] = "cultl",
+ [Q_CULTW] = "cultw",
+ [Q_CUOD] = "cuod",
+ [Q_CUOS] = "cuos",
+ [Q_DIV] = "div",
+ [Q_DTOSI] = "dtosi",
+ [Q_EXTS] = "exts",
+ [Q_EXTSB] = "extsb",
+ [Q_EXTSH] = "extsh",
+ [Q_EXTSW] = "extsw",
+ [Q_EXTUB] = "extub",
+ [Q_EXTUH] = "extuh",
+ [Q_EXTUW] = "extuw",
+ [Q_JMP] = "jmp",
+ [Q_JNZ] = "jnz",
+ [Q_LOADD] = "loadd",
+ [Q_LOADL] = "loadl",
+ [Q_LOADS] = "loads",
+ [Q_LOADSB] = "loadsb",
+ [Q_LOADSH] = "loadsh",
+ [Q_LOADSW] = "loadsw",
+ [Q_LOADUB] = "loadub",
+ [Q_LOADUH] = "loaduh",
+ [Q_LOADUW] = "loaduw",
+ [Q_MUL] = "mul",
+ [Q_OR] = "or",
+ [Q_REM] = "rem",
+ [Q_RET] = "ret",
+ [Q_SAR] = "sar",
+ [Q_SHL] = "shl",
+ [Q_SHR] = "shr",
+ [Q_SLTOF] = "sltof",
+ [Q_STOREB] = "storeb",
+ [Q_STORED] = "stored",
+ [Q_STOREH] = "storeh",
+ [Q_STOREL] = "storel",
+ [Q_STORES] = "stores",
+ [Q_STOREW] = "storew",
+ [Q_STOSI] = "stosi",
+ [Q_SUB] = "sub",
+ [Q_SWTOF] = "swtof",
+ [Q_TRUNCD] = "truncd",
+ [Q_UDIV] = "udiv",
+ [Q_UREM] = "urem",
+ [Q_XOR] = "xor",
+};
+
+void
+geni(struct qbe_statement *stmt, enum qbe_instr instr, ...)
+{
+ assert(0); // TODO
+}
+
+void
+genl(struct qbe_statement *stmt, uint64_t *id, const char *fmt, ...)
+{
+ assert(0); // TODO
+}
+
+void
+pushi(struct qbe_func *func, enum qbe_instr instr, ...)
+{
+ assert(0); // TODO
+}
+
+void
+pushl(struct qbe_func *func, uint64_t *id, const char *fmt, ...)
+{
+ assert(0); // TODO
+}