commit 6294e83e47c6544e86af1bc54e236737d09279b8
parent 2be84a5d9a548d102eb37f48d6aaa485f146e206
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 29 Dec 2020 09:43:38 -0500
gen: implement string constants
Diffstat:
5 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/include/qbe.h b/include/qbe.h
@@ -216,6 +216,27 @@ struct qbe_func {
struct qbe_statements prelude, body;
};
+enum qbe_datatype {
+ QD_VALUE,
+ QD_ZEROED,
+ QD_STRING,
+};
+
+struct qbe_data_item {
+ enum qbe_datatype type;
+ union {
+ struct qbe_value value;
+ size_t zeroed;
+ char *str;
+ };
+ struct qbe_data_item *next;
+};
+
+struct qbe_data {
+ size_t align;
+ struct qbe_data_item items;
+};
+
enum qbe_defkind {
Q_TYPE,
Q_FUNC,
@@ -229,6 +250,7 @@ struct qbe_def {
union {
struct qbe_func func;
struct qbe_type type;
+ struct qbe_data data;
};
struct qbe_def *next;
};
diff --git a/src/emit.c b/src/emit.c
@@ -161,8 +161,11 @@ static void
emit_func(struct qbe_def *def, FILE *out)
{
assert(def->kind == Q_FUNC);
- fprintf(out, "%sfunction ", def->exported ? "export " : "");
- emit_qtype(def->func.returns, out);
+ fprintf(out, "%sfunction", def->exported ? "export " : "");
+ if (def->func.returns->stype != Q__VOID) {
+ fprintf(out, " ");
+ emit_qtype(def->func.returns, out);
+ }
fprintf(out, " $%s(", def->name);
struct qbe_func_param *param = def->func.params;
while (param) {
@@ -189,6 +192,36 @@ emit_func(struct qbe_def *def, FILE *out)
}
static void
+emit_data(struct qbe_def *def, FILE *out)
+{
+ assert(def->kind == Q_DATA);
+ fprintf(out, "%sdata $%s = {",
+ def->exported ? "export " : "",
+ def->name);
+
+ struct qbe_data_item *item = &def->data.items;
+ while (item) {
+ switch (item->type) {
+ case QD_VALUE:
+ assert(0); // TODO
+ case QD_ZEROED:
+ assert(0); // TODO
+ case QD_STRING:
+ fprintf(out, " b \"%s\", b 0", item->str);
+ break;
+ }
+
+ if (item->next) {
+ fprintf(out, ",");
+ }
+
+ item = item->next;
+ }
+
+ fprintf(out, " }\n\n");
+}
+
+static void
emit_def(struct qbe_def *def, FILE *out)
{
switch (def->kind) {
@@ -199,7 +232,8 @@ emit_def(struct qbe_def *def, FILE *out)
emit_func(def, out);
break;
case Q_DATA:
- assert(0); // TODO
+ emit_data(def, out);
+ break;
}
}
diff --git a/src/gen.c b/src/gen.c
@@ -433,6 +433,41 @@ gen_array(struct gen_context *ctx,
}
static void
+gen_string(struct gen_context *ctx,
+ const struct expression *expr,
+ const struct qbe_value *out)
+{
+ assert(!out->indirect); // Invariant
+
+ struct qbe_value temp = {0};
+ gen_temp(ctx, &temp, &qbe_long, "strdata.%d");
+ temp.kind = QV_GLOBAL;
+
+ struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def));
+ def->name = temp.name;
+ def->kind = Q_DATA;
+ def->data.items.type = QD_STRING;
+ // TODO: Escape special characters
+ def->data.items.str = strdup(expr->constant.string.value);
+ qbe_append_def(ctx->out, def);
+
+ struct qbe_value str = {0};
+ gen_temp(ctx, &str, &qbe_long, "str.%d"); // XXX: ARCH
+ pushi(ctx->current, &str, Q_COPY, out, NULL);
+ str.indirect = true;
+
+ struct qbe_value size = {0};
+ constl(&size, expr->constant.string.len); // XXX: ARCH
+
+ gen_store(ctx, &str, &temp);
+ constl(&temp, 8); // XXX: ARCH
+ pushi(ctx->current, &str, Q_ADD, &str, &temp, NULL);
+ gen_store(ctx, &str, &size);
+ pushi(ctx->current, &str, Q_ADD, &str, &temp, NULL);
+ gen_store(ctx, &str, &size);
+}
+
+static void
gen_expr_constant(struct gen_context *ctx,
const struct expression *expr,
const struct qbe_value *out)
@@ -461,6 +496,9 @@ gen_expr_constant(struct gen_context *ctx,
case TYPE_STORAGE_ARRAY:
gen_array(ctx, expr, out);
return;
+ case TYPE_STORAGE_STRING:
+ gen_string(ctx, expr, out);
+ return;
default:
// Moving right along
break;
diff --git a/src/qtype.c b/src/qtype.c
@@ -124,10 +124,14 @@ lookup_aggregate(struct gen_context *ctx, const struct type *type)
def->type.name = name;
def->type.align = SIZE_UNDEFINED;
+ struct qbe_field *field = &def->type.fields;
switch (type->storage) {
+ case TYPE_STORAGE_STRING:
+ field->type = &qbe_long; // XXX: ARCH
+ field->count = 3;
+ break;
case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_SLICE:
- case TYPE_STORAGE_STRING:
case TYPE_STORAGE_STRUCT:
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_UNION:
diff --git a/todo.txt b/todo.txt
@@ -15,3 +15,7 @@ confidently implement the remainder of the features.
general todos, includes spec updates:
- zero-length arrays & slice initializers
- allocations
+- assign arrays from other arrays (memcpy)
+- pass arrays directly into function calls (alloc if needed flag?)
+- casts
+- implicit casts