commit 1b18c38423bcaf53678fa69f41a3d27c2cde9174
parent 5acb5c6f08f6ebfe939b1028d647ec7611d26a04
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 20 Dec 2020 15:05:33 -0500
gen: implement expression lists
Diffstat:
5 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/include/qbe.h b/include/qbe.h
@@ -141,6 +141,7 @@ enum qbe_instr {
extern const char *qbe_instr[Q_LAST_INSTR];
enum qbe_statement_type {
+ Q_COMMENT,
Q_INSTR,
Q_LABEL,
};
@@ -159,6 +160,7 @@ struct qbe_statement {
struct qbe_arguments *args;
};
char *label;
+ char *comment;
};
};
@@ -195,6 +197,7 @@ void geni(struct qbe_statement *stmt, enum qbe_instr instr, const struct qbe_val
const char *genl(struct qbe_statement *stmt, uint64_t *id, const char *fmt);
void pushi(struct qbe_func *func, enum qbe_instr instr, const struct qbe_value *out, ...);
const char *pushl(struct qbe_func *func, uint64_t *id, const char *fmt);
+void pushc(struct qbe_func *func, const char *text);
void constw(struct qbe_value *val, uint32_t l);
void constl(struct qbe_value *val, uint64_t l);
diff --git a/src/check.c b/src/check.c
@@ -93,6 +93,7 @@ check_expr_list(struct context *ctx,
while (alist) {
struct expression *lexpr = calloc(1, sizeof(struct expression));
check_expression(ctx, alist->expr, lexpr);
+ list->expr = lexpr;
alist = alist->next;
if (alist) {
diff --git a/src/emit.c b/src/emit.c
@@ -67,6 +67,9 @@ static void
emit_stmt(struct qbe_statement *stmt, FILE *out)
{
switch (stmt->type) {
+ case Q_COMMENT:
+ fprintf(out, "\t# %s\n", stmt->comment);
+ break;
case Q_INSTR:
fprintf(out, "\t");
if (stmt->out != NULL) {
diff --git a/src/gen.c b/src/gen.c
@@ -90,11 +90,19 @@ gen_loadtemp(struct gen_context *ctx,
gen_load(ctx, dest, src, is_signed);
}
+static void gen_expression(struct gen_context *ctx,
+ const struct expression *expr, struct qbe_value *out);
+
static void
gen_constant(struct gen_context *ctx,
const struct expression *expr,
struct qbe_value *out)
{
+ if (out == NULL) {
+ pushc(ctx->current, "useless constant expression discarded");
+ return;
+ }
+
const struct qbe_type *qtype = qtype_for_type(ctx, expr->result, false);
struct qbe_value val = {0};
switch (qtype->stype) {
@@ -117,10 +125,28 @@ gen_constant(struct gen_context *ctx,
case Q__VOID:
assert(0); // Invariant
}
+
gen_store(ctx, out, &val);
}
static void
+gen_expr_list(struct gen_context *ctx,
+ const struct expression *expr,
+ struct qbe_value *out)
+{
+ const struct expression_list *list = &expr->list;
+ while (list) {
+ struct qbe_value *dest = NULL;
+ if (!list->next) {
+ // Last value determines expression result
+ dest = out;
+ }
+ gen_expression(ctx, list->expr, dest);
+ list = list->next;
+ }
+}
+
+static void
gen_expression(struct gen_context *ctx,
const struct expression *expr,
struct qbe_value *out)
@@ -143,7 +169,10 @@ gen_expression(struct gen_context *ctx,
case EXPR_FUNC:
case EXPR_IF:
case EXPR_INDEX:
+ assert(0); // TODO
case EXPR_LIST:
+ gen_expr_list(ctx, expr, out);
+ break;
case EXPR_MATCH:
case EXPR_MEASURE:
case EXPR_SLICE:
diff --git a/src/qbe.c b/src/qbe.c
@@ -239,6 +239,14 @@ pushl(struct qbe_func *func, uint64_t *id, const char *fmt)
}
void
+pushc(struct qbe_func *func, const char *text)
+{
+ struct qbe_statement stmt = {0};
+ stmt.comment = strdup(text);
+ push(func, &stmt);
+}
+
+void
constw(struct qbe_value *val, uint32_t w)
{
val->kind = QV_CONST;