commit af16fa5d315b6f30b0e999e31c18d763839b7d93
parent 65a8d225e0098a23f8edd929d8b5256add800eda
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 16 Jan 2021 09:55:47 -0500
gen: fix gen_copy for signed b/h types
Diffstat:
4 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/include/qbe.h b/include/qbe.h
@@ -30,7 +30,7 @@ struct qbe_type {
// Aggregate types only:
char *name;
size_t align;
- bool is_union;
+ bool is_union, is_signed;
struct qbe_field fields;
const struct type *base;
};
@@ -46,7 +46,7 @@ extern const struct qbe_type
qbe_void,
qbe_aggregate;
-const struct qbe_type *qtype_for_xtype(enum qbe_stype type);
+const struct qbe_type *qtype_for_xtype(enum qbe_stype type, bool is_signed);
enum qbe_value_kind {
QV_CONST,
diff --git a/src/gen.c b/src/gen.c
@@ -173,6 +173,9 @@ gen_copy(struct gen_context *ctx,
while (field) {
temp.type = field->type;
+ if (temp.type->stype == Q_HALF || temp.type->stype == Q_BYTE) {
+ temp.type = &qbe_word;
+ }
for (size_t i = field->count; i > 0; --i) {
struct qbe_value a, b;
@@ -183,10 +186,9 @@ gen_copy(struct gen_context *ctx,
case Q_LONG:
case Q_SINGLE:
case Q_DOUBLE:
- // TODO: This might be broken for unsigned types
- // b and h
pushi(ctx->current, &temp,
- load_for_type(field->type->stype, true),
+ load_for_type(field->type->stype,
+ field->type->is_signed),
&srcp, NULL);
pushi(ctx->current, NULL,
store_for_type(field->type->stype),
diff --git a/src/qbe.c b/src/qbe.c
@@ -12,10 +12,20 @@ qbe_byte = {
.stype = Q_BYTE,
.size = 1,
},
+qbe_byte_s = {
+ .stype = Q_BYTE,
+ .size = 1,
+ .is_signed = true,
+},
qbe_half = {
.stype = Q_HALF,
.size = 2,
},
+qbe_half_s = {
+ .stype = Q_HALF,
+ .size = 2,
+ .is_signed = true,
+},
qbe_word = {
.stype = Q_WORD,
.size = 4,
@@ -42,13 +52,13 @@ qbe_aggregate = {
};
const struct qbe_type *
-qtype_for_xtype(enum qbe_stype type)
+qtype_for_xtype(enum qbe_stype type, bool is_signed)
{
switch (type) {
case Q_BYTE:
- return &qbe_byte;
+ return is_signed ? &qbe_byte_s : &qbe_byte;
case Q_HALF:
- return &qbe_half;
+ return is_signed ? &qbe_half_s : &qbe_half;
case Q_WORD:
return &qbe_word;
case Q_LONG:
diff --git a/src/qtype.c b/src/qtype.c
@@ -238,7 +238,9 @@ qtype_for_type(struct gen_context *ctx, const struct type *type, bool extended)
case TYPE_STORAGE_I16:
case TYPE_STORAGE_U16:
if (extended) {
- return qtype_for_xtype(qxtype_for_type(type));
+ return qtype_for_xtype(
+ qxtype_for_type(type),
+ type_is_signed(type));
}
// Fallthrough
case TYPE_STORAGE_BOOL:
@@ -256,7 +258,7 @@ qtype_for_type(struct gen_context *ctx, const struct type *type, bool extended)
case TYPE_STORAGE_F32:
case TYPE_STORAGE_F64:
case TYPE_STORAGE_VOID:
- return qtype_for_xtype(qstype_for_type(type));
+ return qtype_for_xtype(qstype_for_type(type), false);
case TYPE_STORAGE_ARRAY:
case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_SLICE:
@@ -266,7 +268,7 @@ qtype_for_type(struct gen_context *ctx, const struct type *type, bool extended)
case TYPE_STORAGE_UNION:
return lookup_aggregate(ctx, type);
case TYPE_STORAGE_FUNCTION:
- return qtype_for_xtype(Q__AGGREGATE);
+ return qtype_for_xtype(Q__AGGREGATE, false);
case TYPE_STORAGE_ALIAS:
return qtype_for_type(ctx, type->alias.type, extended);
}