cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 9150901e4ebde2273bf266d608a7a05228e1d0df
parent 1d47a3f01bd5ea43ce798fa6624b65dfdc6a37c0
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 20 Feb 2019 14:06:45 -0800

eval: Handle nested offset address constants

Diffstat:
Meval.c | 146++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Atests/initializer-nested-array-address.c | 2++
Atests/initializer-nested-array-address.qbe | 2++
3 files changed, 90 insertions(+), 60 deletions(-)

diff --git a/eval.c b/eval.c @@ -9,6 +9,66 @@ #include "token.h" #include "type.h" +static void +binary(struct expression *expr, enum tokenkind op, struct expression *l, struct expression *r) +{ + expr->kind = EXPRCONST; +#define F (1<<8) +#define S (2<<8) + if (typeprop(l->type) & PROPFLOAT) + op |= F; + else if (l->type->basic.issigned) + op |= S; + switch (op) { + case TMUL: + case TMUL|S: expr->constant.i = l->constant.i * r->constant.i; break; + case TMUL|F: expr->constant.f = l->constant.f * r->constant.f; break; + case TDIV: expr->constant.i = l->constant.i / r->constant.i; break; + case TDIV|S: expr->constant.i = (int64_t)l->constant.i / (int64_t)r->constant.i; break; + case TDIV|F: expr->constant.f = l->constant.f / r->constant.f; break; + case TMOD: expr->constant.i = l->constant.i % r->constant.i; break; + case TMOD|S: expr->constant.i = (int64_t)l->constant.i % (int64_t)r->constant.i; break; + case TADD: + case TADD|S: expr->constant.i = l->constant.i + r->constant.i; break; + case TADD|F: expr->constant.f = l->constant.f + r->constant.f; break; + case TSUB: + case TSUB|S: expr->constant.i = l->constant.i - r->constant.i; break; + case TSUB|F: expr->constant.f = l->constant.f - r->constant.f; break; + case TSHL: + case TSHL|S: expr->constant.i = l->constant.i << r->constant.i; break; + case TSHR: expr->constant.i = l->constant.i >> r->constant.i; break; + case TSHR|S: expr->constant.i = (int64_t)l->constant.i >> r->constant.i; break; + case TBAND: + case TBAND|S: expr->constant.i = l->constant.i & r->constant.i; break; + case TBOR: + case TBOR|S: expr->constant.i = l->constant.i | r->constant.i; break; + case TXOR: + case TXOR|S: expr->constant.i = l->constant.i ^ r->constant.i; break; + case TLESS: expr->constant.i = l->constant.i < r->constant.i; break; + case TLESS|S: expr->constant.i = (int64_t)l->constant.i < (int64_t)r->constant.i; break; + case TLESS|F: expr->constant.i = l->constant.f < r->constant.f; break; + case TGREATER: expr->constant.i = l->constant.i > r->constant.i; break; + case TGREATER|S: expr->constant.i = (int64_t)l->constant.i > (int64_t)r->constant.i; break; + case TGREATER|F: expr->constant.i = l->constant.f > r->constant.f; break; + case TLEQ: expr->constant.i = l->constant.i <= r->constant.i; break; + case TLEQ|S: expr->constant.i = (int64_t)l->constant.i <= (int64_t)r->constant.i; break; + case TLEQ|F: expr->constant.i = l->constant.f <= r->constant.f; break; + case TGEQ: expr->constant.i = l->constant.i >= r->constant.i; break; + case TGEQ|S: expr->constant.i = (int64_t)l->constant.i >= (int64_t)r->constant.i; break; + case TGEQ|F: expr->constant.i = l->constant.f >= r->constant.f; break; + case TEQL: + case TEQL|S: expr->constant.i = l->constant.i == r->constant.i; break; + case TEQL|F: expr->constant.i = l->constant.f == r->constant.f; break; + case TNEQ: + case TNEQ|S: expr->constant.i = l->constant.i != r->constant.i; break; + case TNEQ|F: expr->constant.i = l->constant.f != r->constant.f; break; + default: + fatal("internal error; unknown binary expression"); + } +#undef F +#undef S +} + struct expression * eval(struct expression *expr) { @@ -65,70 +125,36 @@ eval(struct expression *expr) r = eval(expr->binary.r); expr->binary.l = l; expr->binary.r = r; - if (l->kind != EXPRCONST) + switch (expr->binary.op) { + case TADD: + if (r->kind == EXPRBINARY) + c = l, l = r, r = c; + if (r->kind != EXPRCONST) + break; + if (l->kind == EXPRCONST) { + binary(expr, expr->binary.op, l, r); + } else if (l->kind == EXPRBINARY && l->type->kind == TYPEPOINTER && l->binary.r->kind == EXPRCONST) { + if (l->binary.op == TADD || l->binary.op == TSUB) { + /* (P ± C1) + C2 -> P + (C2 ± C1) */ + expr->binary.l = l->binary.l; + binary(expr->binary.r, l->binary.op, r, l->binary.r); + } + } break; - if (expr->binary.op == TLOR) - return !l->constant.i ? r : l; - if (expr->binary.op == TLAND) + /* TODO: TSUB pointer handling */ + case TLOR: + if (l->kind != EXPRCONST) + break; + return l->constant.i ? l : r; + case TLAND: + if (l->kind != EXPRCONST) + break; return l->constant.i ? r : l; - if (r->kind != EXPRCONST) - break; - expr->kind = EXPRCONST; - op = expr->binary.op; -#define F (1<<8) -#define S (2<<8) - if (typeprop(l->type) & PROPFLOAT) - op |= F; - else if (l->type->basic.issigned) - op |= S; - switch (op) { - case TMUL: - case TMUL|S: expr->constant.i = l->constant.i * r->constant.i; break; - case TMUL|F: expr->constant.f = l->constant.f * r->constant.f; break; - case TDIV: expr->constant.i = l->constant.i / r->constant.i; break; - case TDIV|S: expr->constant.i = (int64_t)l->constant.i / (int64_t)r->constant.i; break; - case TDIV|F: expr->constant.f = l->constant.f / r->constant.f; break; - case TMOD: expr->constant.i = l->constant.i % r->constant.i; break; - case TMOD|S: expr->constant.i = (int64_t)l->constant.i % (int64_t)r->constant.i; break; - case TADD: - case TADD|S: expr->constant.i = l->constant.i + r->constant.i; break; - case TADD|F: expr->constant.f = l->constant.f + r->constant.f; break; - case TSUB: - case TSUB|S: expr->constant.i = l->constant.i - r->constant.i; break; - case TSUB|F: expr->constant.f = l->constant.f - r->constant.f; break; - case TSHL: - case TSHL|S: expr->constant.i = l->constant.i << r->constant.i; break; - case TSHR: expr->constant.i = l->constant.i >> r->constant.i; break; - case TSHR|S: expr->constant.i = (int64_t)l->constant.i >> r->constant.i; break; - case TBAND: - case TBAND|S: expr->constant.i = l->constant.i & r->constant.i; break; - case TBOR: - case TBOR|S: expr->constant.i = l->constant.i | r->constant.i; break; - case TXOR: - case TXOR|S: expr->constant.i = l->constant.i ^ r->constant.i; break; - case TLESS: expr->constant.i = l->constant.i < r->constant.i; break; - case TLESS|S: expr->constant.i = (int64_t)l->constant.i < (int64_t)r->constant.i; break; - case TLESS|F: expr->constant.i = l->constant.f < r->constant.f; break; - case TGREATER: expr->constant.i = l->constant.i > r->constant.i; break; - case TGREATER|S: expr->constant.i = (int64_t)l->constant.i > (int64_t)r->constant.i; break; - case TGREATER|F: expr->constant.i = l->constant.f > r->constant.f; break; - case TLEQ: expr->constant.i = l->constant.i <= r->constant.i; break; - case TLEQ|S: expr->constant.i = (int64_t)l->constant.i <= (int64_t)r->constant.i; break; - case TLEQ|F: expr->constant.i = l->constant.f <= r->constant.f; break; - case TGEQ: expr->constant.i = l->constant.i >= r->constant.i; break; - case TGEQ|S: expr->constant.i = (int64_t)l->constant.i >= (int64_t)r->constant.i; break; - case TGEQ|F: expr->constant.i = l->constant.f >= r->constant.f; break; - case TEQL: - case TEQL|S: expr->constant.i = l->constant.i == r->constant.i; break; - case TEQL|F: expr->constant.i = l->constant.f == r->constant.f; break; - case TNEQ: - case TNEQ|S: expr->constant.i = l->constant.i != r->constant.i; break; - case TNEQ|F: expr->constant.i = l->constant.f != r->constant.f; break; default: - fatal("internal error; unknown binary expression"); + if (l->kind != EXPRCONST || r->kind != EXPRCONST) + break; + binary(expr, expr->binary.op, l, r); } -#undef F -#undef S break; case EXPRCOND: l = expr->cond.t; diff --git a/tests/initializer-nested-array-address.c b/tests/initializer-nested-array-address.c @@ -0,0 +1,2 @@ +int x[2][3]; +int *y = &x[1][2]; diff --git a/tests/initializer-nested-array-address.qbe b/tests/initializer-nested-array-address.qbe @@ -0,0 +1,2 @@ +export data $y = align 8 { l $x + 20, } +export data $x = align 4 { z 24 }