harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 8472620074ff6434c3dacafdb411b15794a42815
parent 732522cb68bf3fd61ad9e3003cb57d293c8b2762
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 20 Dec 2020 10:54:20 -0500

Add emit scaffolding

Diffstat:
Mconfigure | 1+
Ainclude/emit.h | 7+++++++
Minclude/qbe.h | 6++++--
Asrc/emit.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/gen.c | 2++
Msrc/main.c | 11++++++++++-
Msrc/qbe.c | 7+++++++
7 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/configure b/configure @@ -5,6 +5,7 @@ eval ". $srcdir/config.sh" harec() { genrules harec \ src/check.c \ + src/emit.c \ src/gen.c \ src/identifier.c \ src/lex.c \ diff --git a/include/emit.h b/include/emit.h @@ -0,0 +1,7 @@ +#ifndef HAREC_EMIT_H +#define HAREC_EMIT_H + +struct qbe_program; +void emit(struct qbe_program *program, FILE *out); + +#endif diff --git a/include/qbe.h b/include/qbe.h @@ -185,10 +185,12 @@ struct qbe_program { struct qbe_def *defs; }; +void qbe_append_def(struct qbe_program *prog, struct qbe_def *def); + // 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). +// set of values to match with fmt to produce a label (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, ...); diff --git a/src/emit.c b/src/emit.c @@ -0,0 +1,60 @@ +#include <assert.h> +#include <stdio.h> +#include "emit.h" +#include "qbe.h" + +static void +emit_qtype(const struct qbe_type *type, FILE *out) +{ + switch (type->stype) { + case Q_BYTE: + case Q_HALF: + case Q_WORD: + case Q_LONG: + case Q_SINGLE: + case Q_DOUBLE: + fprintf(out, "%c ", (char)type->stype); + break; + case Q__VOID: + break; // no-op + case Q__AGGREGATE: + assert(0); // TODO + } +} + +static void +emit_func(struct qbe_def *def, FILE *out) +{ + assert(def->type == Q_FUNC); + // TODO: Parameters + fprintf(out, "%sfunction ", def->exported ? "export " : ""); + emit_qtype(def->func.returns, out); + fprintf(out, "$%s() {\n", def->name); // TODO: Parameters + // TODO: Body + fprintf(out, "}\n\n"); +} + +static void +emit_def(struct qbe_def *def, FILE *out) +{ + switch (def->type) { + case Q_TYPE: + assert(0); // TODO + case Q_FUNC: + emit_func(def, out); + break; + case Q_DATA: + assert(0); // TODO + } +} + +void +emit(struct qbe_program *program, FILE *out) +{ + struct qbe_def *def = program->defs; + assert(def); // At least one + while (def) { + emit_def(def, out); + def = def->next; + } +} diff --git a/src/gen.c b/src/gen.c @@ -178,6 +178,8 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) assert(fntype->func.params == NULL); // TODO // TODO: Gen function body + + qbe_append_def(ctx->out, qdef); } static void diff --git a/src/main.c b/src/main.c @@ -3,6 +3,7 @@ #include <string.h> #include "ast.h" #include "check.h" +#include "emit.h" #include "gen.h" #include "lex.h" #include "parse.h" @@ -13,13 +14,14 @@ enum stage { STAGE_PARSE, STAGE_CHECK, STAGE_GEN, + STAGE_EMIT, }; enum stage parse_stage(const char *s) { if (s == NULL) { - return STAGE_GEN; + return STAGE_EMIT; } else if (strcmp(s, "lex") == 0) { return STAGE_LEX; } else if (strcmp(s, "parse") == 0) { @@ -28,6 +30,8 @@ parse_stage(const char *s) return STAGE_CHECK; } else if (strcmp(s, "gen") == 0) { return STAGE_GEN; + } else if (strcmp(s, "emit") == 0) { + return STAGE_EMIT; } else { fprintf(stderr, "Unknown HA_STAGE value '%s'\n", s); exit(1); @@ -63,5 +67,10 @@ main(int argc, char *argv[]) struct qbe_program prog = {0}; gen(&unit, &prog); + if (stage == STAGE_GEN) { + return 0; + } + + emit(&prog, stdout); return 0; } diff --git a/src/qbe.c b/src/qbe.c @@ -137,6 +137,13 @@ const char *qbe_instr[Q_LAST_INSTR] = { }; void +qbe_append_def(struct qbe_program *prog, struct qbe_def *def) +{ + def->next = prog->defs; + prog->defs = def; +} + +void geni(struct qbe_statement *stmt, enum qbe_instr instr, ...) { assert(0); // TODO