harec

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

commit e75a186f908f2dbc7b2ef5e506a4c5e9c8177358
parent ca270dd081d4878f0863339779c6383a3f14f16d
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 26 Feb 2021 17:48:56 -0500

Support referencing symbols in global initializers

This kind of half-assed, we'll have to flesh out all of the edge cases
later

Diffstat:
Minclude/expr.h | 30+++++++++++++++++-------------
Minclude/qbe.h | 5+++++
Msrc/emit.c | 7+++++++
Msrc/eval.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/gen.c | 9++++++++-
Msrc/typedef.c | 3++-
6 files changed, 96 insertions(+), 17 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -161,18 +161,22 @@ struct struct_constant { struct struct_constant *next; }; -union expression_constant { - bool bval; - double fval; - intmax_t ival; - uintmax_t uval; - uint32_t rune; - struct { - size_t len; - char *value; - } string; - struct array_constant *array; - struct struct_constant *_struct; +struct expression_constant { + // If non-null, ival is an offset from this object's address + const struct scope_object *object; + union { + bool bval; + double fval; + intmax_t ival; + uintmax_t uval; + uint32_t rune; + struct { + size_t len; + char *value; + } string; + struct array_constant *array; + struct struct_constant *_struct; + }; }; struct expression_control { @@ -315,7 +319,7 @@ struct expression { struct expression_binding binding; struct expression_call call; struct expression_cast cast; - union expression_constant constant; + struct expression_constant constant; struct expression_defer defer; struct expression_delete delete; struct expression_control control; diff --git a/include/qbe.h b/include/qbe.h @@ -221,6 +221,7 @@ enum qbe_datatype { QD_VALUE, QD_ZEROED, QD_STRING, + QD_SYMOFFS, }; struct qbe_data_item { @@ -232,6 +233,10 @@ struct qbe_data_item { char *str; size_t sz; }; + struct { + char *sym; + long offset; + }; }; struct qbe_data_item *next; }; diff --git a/src/emit.c b/src/emit.c @@ -277,6 +277,9 @@ is_zeroes(struct qbe_data_item *data) return false; } } + break; + case QD_SYMOFFS: + return false; } if (!data->next) { return true; @@ -315,6 +318,10 @@ emit_data(struct qbe_def *def, FILE *out) case QD_STRING: emit_data_string(item->str, item->sz, out); break; + case QD_SYMOFFS: + // XXX: ARCH + fprintf(out, "l $%s + %ld", item->sym, item->offset); + break; } fprintf(out, item->next ? ", " : " "); diff --git a/src/eval.c b/src/eval.c @@ -2,6 +2,7 @@ #include <stdbool.h> #include <stdlib.h> #include <string.h> +#include "check.h" #include "eval.h" #include "expr.h" #include "scope.h" @@ -9,6 +10,30 @@ #include "types.h" #include "util.h" +static enum eval_result +eval_access(struct context *ctx, struct expression *in, struct expression *out) +{ + out->type = EXPR_CONSTANT; + out->result = in->result; + + // TODO: Probably have not considered all of the edge cases here + switch (in->access.type) { + case ACCESS_IDENTIFIER: + out->constant.object = in->access.object; + out->constant.ival = 0; + assert(in->access.object->otype == O_DECL); // TODO: Bubble this up + break; + case ACCESS_INDEX: + assert(0); // TODO + case ACCESS_FIELD: + assert(0); // TODO + case ACCESS_TUPLE: + assert(0); // TODO + } + + return EVAL_OK; +} + static uintmax_t itrunc(const struct type *type, uintmax_t val) { @@ -510,12 +535,41 @@ eval_struct(struct context *ctx, struct expression *in, struct expression *out) return EVAL_OK; } +static enum eval_result +eval_unarithm(struct context *ctx, struct expression *in, struct expression *out) +{ + struct expression lvalue = {0}; + enum eval_result r = eval_expr(ctx, in->binarithm.lvalue, &lvalue); + if (r != EVAL_OK) { + return r; + } + + out->type = EXPR_CONSTANT; + switch (in->unarithm.op) { + case UN_ADDRESS: + assert(lvalue.type == EXPR_CONSTANT); + assert(lvalue.constant.object); + out->result = type_store_lookup_pointer( + ctx->store, lvalue.result, 0); + out->constant = lvalue.constant; + break; + case UN_BNOT: + case UN_DEREF: + case UN_LNOT: + case UN_MINUS: + case UN_PLUS: + assert(0); // TODO + } + + return EVAL_OK; +} + enum eval_result eval_expr(struct context *ctx, struct expression *in, struct expression *out) { switch (in->type) { case EXPR_ACCESS: - assert(0); // TODO + return eval_access(ctx, in, out); case EXPR_BINARITHM: return eval_binarithm(ctx, in, out); case EXPR_CAST: @@ -528,8 +582,9 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) return eval_struct(ctx, in, out); case EXPR_SLICE: case EXPR_TUPLE: - case EXPR_UNARITHM: assert(0); // TODO + case EXPR_UNARITHM: + return eval_unarithm(ctx, in, out); case EXPR_ALLOC: case EXPR_APPEND: case EXPR_ASSERT: diff --git a/src/gen.c b/src/gen.c @@ -2599,8 +2599,15 @@ gen_data_item(struct gen_context *ctx, struct expression *expr, assert(expr->type == EXPR_CONSTANT); struct qbe_def *def; - const union expression_constant *constant = &expr->constant; + const struct expression_constant *constant = &expr->constant; const struct type *type = type_dealias(expr->result); + if (constant->object) { + item->type = QD_SYMOFFS; + item->sym = ident_to_sym(&constant->object->ident); + item->offset = constant->ival; + return item; + } + switch (type->storage) { case STORAGE_I8: case STORAGE_U8: diff --git a/src/typedef.c b/src/typedef.c @@ -54,7 +54,8 @@ static void emit_const(const struct expression *expr, FILE *out) { assert(expr->type == EXPR_CONSTANT); - const union expression_constant *val = &expr->constant; + const struct expression_constant *val = &expr->constant; + assert(!val->object); switch (expr->result->storage) { case STORAGE_BOOL: fprintf(out, "%s", val->bval ? "false" : "true");