commit 86e0a84d07bbdb4fbe47607d5233f51c1a3877e1
parent 689bdd02034adc68233d4e93dd233ead6d508108
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 31 Dec 2020 10:47:23 -0500
Implement str -> *const char cast
Diffstat:
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -556,9 +556,23 @@ gen_expr_cast(struct gen_context *ctx,
bool is_signed = type_is_signed(from);
struct qbe_value in = {0}, result = {0};
+ gen_temp(ctx, &result, qtype_for_type(ctx, to, false), "cast.out.%d");
+
+ // Special case: str -> *const char
+ if (to->storage == TYPE_STORAGE_POINTER
+ && to->pointer.referent->storage == TYPE_STORAGE_CHAR
+ && from->storage == TYPE_STORAGE_STRING) {
+ gen_temp(ctx, &in, &qbe_long, "cast.in.%d");
+ qval_address(&in);
+ gen_expression(ctx, expr->cast.value, &in);
+ qval_deref(&in);
+ gen_load(ctx, &result, &in, false);
+ gen_store(ctx, out, &result);
+ return;
+ }
+
gen_temp(ctx, &in, qtype_for_type(ctx, from, false), "cast.in.%d");
gen_expression(ctx, expr->cast.value, &in);
- gen_temp(ctx, &result, qtype_for_type(ctx, to, false), "cast.out.%d");
enum qbe_instr op;
switch (to->storage) {
@@ -608,22 +622,16 @@ gen_expr_cast(struct gen_context *ctx,
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_ENUM:
assert(0); // TODO
- case TYPE_STORAGE_STRING:
- assert(0); // TODO
- case TYPE_STORAGE_POINTER:
- if (to->pointer.referent->storage == TYPE_STORAGE_CHAR
- && from->storage == TYPE_STORAGE_STRING) {
- assert(0); // TODO
- }
- // Fallthrough
// Can be implemented with a copy
case TYPE_STORAGE_ARRAY:
- case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_NULL:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
pushi(ctx->current, &result, Q_COPY, &in, NULL);
break;
case TYPE_STORAGE_BOOL:
case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_STRING:
case TYPE_STORAGE_STRUCT:
case TYPE_STORAGE_UNION:
case TYPE_STORAGE_VOID:
diff --git a/src/type_store.c b/src/type_store.c
@@ -154,13 +154,14 @@ type_is_castable(const struct type *to,
return to->storage == TYPE_STORAGE_POINTER
|| to->storage == TYPE_STORAGE_NULL
|| to->storage == TYPE_STORAGE_UINTPTR;
- case TYPE_STORAGE_STRING:
- return to == &builtin_type_const_ptr_char;
case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_ARRAY:
case TYPE_STORAGE_ALIAS:
case TYPE_STORAGE_TAGGED_UNION:
assert(0); // TODO
+ case TYPE_STORAGE_STRING:
+ return to->pointer.referent->storage == TYPE_STORAGE_CHAR
+ && to->pointer.referent->flags & TYPE_CONST;
case TYPE_STORAGE_RUNE:
return to->storage == TYPE_STORAGE_U32;
// Cannot be cast: