aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-09-29 15:03:15 -0700
committerMichael Forney <mforney@mforney.org>2021-09-29 15:04:44 -0700
commite36dc296f50cb2d60d3b27ce62217762b9655313 (patch)
tree91c5e1d3ede6ae92d2310866c2f71db28c840a2f
parent8a08b602e30054c283adb8fc1a4077aaf99efbca (diff)
eval: Allow subtraction in address constants
-rw-r--r--eval.c14
-rw-r--r--test/initializer-address-subtract.c2
-rw-r--r--test/initializer-address-subtract.qbe2
3 files changed, 11 insertions, 7 deletions
diff --git a/eval.c b/eval.c
index 958f517..0c68051 100644
--- a/eval.c
+++ b/eval.c
@@ -157,19 +157,19 @@ eval(struct expr *expr, enum evalkind kind)
case TADD:
if (r->kind == EXPRBINARY)
c = l, l = r, r = c;
+ /* fallthrough */
+ case TSUB:
if (r->kind != EXPRCONST)
break;
if (l->kind == EXPRCONST) {
binary(expr, expr->op, l, r);
- } else if (l->kind == EXPRBINARY && l->type->kind == TYPEPOINTER && l->binary.r->kind == EXPRCONST) {
- if (l->op == TADD || l->op == TSUB) {
- /* (P ± C1) + C2 -> P + (C2 ± C1) */
- expr->binary.l = l->binary.l;
- binary(expr->binary.r, l->op, r, l->binary.r);
- }
+ } else if (l->kind == EXPRBINARY && l->type->kind == TYPEPOINTER && l->op == TADD && l->binary.r->kind == EXPRCONST) {
+ /* (P + C1) ± C2 -> P + (C1 ± C2) */
+ binary(expr->binary.r, expr->op, l->binary.r, r);
+ expr->op = TADD;
+ expr->binary.l = l->binary.l;
}
break;
- /* TODO: TSUB pointer handling */
case TLOR:
if (l->kind != EXPRCONST)
break;
diff --git a/test/initializer-address-subtract.c b/test/initializer-address-subtract.c
new file mode 100644
index 0000000..f273d33
--- /dev/null
+++ b/test/initializer-address-subtract.c
@@ -0,0 +1,2 @@
+int a[4];
+int *p = a + 2 - 1;
diff --git a/test/initializer-address-subtract.qbe b/test/initializer-address-subtract.qbe
new file mode 100644
index 0000000..e6aa8cd
--- /dev/null
+++ b/test/initializer-address-subtract.qbe
@@ -0,0 +1,2 @@
+export data $p = align 8 { l $a + 4, }
+export data $a = align 4 { z 16 }