commit 08ba275b6cb0ab3047b40f87254ba8a992a2672d
parent 10baff0e69f05d04e6a273216f9baefcfc91ee50
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 12 Jan 2021 17:20:45 -0500
eval: implement basic casts
Diffstat:
M | src/eval.c | | | 68 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
M | src/gen.c | | | 6 | +++++- |
2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/src/eval.c b/src/eval.c
@@ -16,13 +16,79 @@ eval_const(struct context *ctx, struct expression *in, struct expression *out)
}
enum eval_result
+eval_cast(struct context *ctx, struct expression *in, struct expression *out)
+{
+ struct expression val = {0};
+ enum eval_result r = eval_expr(ctx, in->cast.value, &val);
+ if (r != EVAL_OK) {
+ return r;
+ }
+
+ const struct type *to = type_dealias(in->result),
+ *from = type_dealias(val.result);
+ if (to->storage == from->storage) {
+ *out = val;
+ return EVAL_OK;
+ }
+
+ // XXX: We should also be able to handle expressions which use
+ // symbols/identifiers
+ out->type = EXPR_CONSTANT;
+ out->result = to;
+
+ switch (to->storage) {
+ case TYPE_STORAGE_POINTER:
+ if (from->storage == TYPE_STORAGE_NULL) {
+ out->constant.uval = 0;
+ return EVAL_OK;
+ }
+ assert(0); // TODO
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_NULL:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_TAGGED_UNION:
+ assert(0); // TODO
+ case TYPE_STORAGE_ALIAS:
+ assert(0); // Handled above
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_UNION:
+ assert(0); // Invariant
+ case TYPE_STORAGE_VOID:
+ break; // no-op
+ }
+
+ assert(0); // Unreachable
+}
+
+enum eval_result
eval_expr(struct context *ctx, struct expression *in, struct expression *out)
{
switch (in->type) {
case EXPR_ACCESS:
case EXPR_BINARITHM:
- case EXPR_CAST:
assert(0); // TODO
+ case EXPR_CAST:
+ return eval_cast(ctx, in, out);
case EXPR_CONSTANT:
return eval_const(ctx, in, out);
case EXPR_CONTINUE:
diff --git a/src/gen.c b/src/gen.c
@@ -1367,9 +1367,13 @@ gen_global_decl(struct gen_context *ctx, const struct declaration *decl)
assert(0); // TODO
case TYPE_STORAGE_UINTPTR:
assert(0); // TODO: What are the semantics for this?
+ case TYPE_STORAGE_POINTER:
+ assert(global->value->type == EXPR_CONSTANT); // TODO?
+ item->type = QD_VALUE;
+ constl(&item->value, (uint64_t)constant->uval); // XXX: ARCH
+ break;
case TYPE_STORAGE_ARRAY:
case TYPE_STORAGE_ENUM:
- case TYPE_STORAGE_POINTER:
case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_STRING:
case TYPE_STORAGE_STRUCT: