[qfcc] Simplify offset_cast for correctness

I don't know why I didn't think to do it this way before, but simply
recursing into each operand for + or - expressions makes it much easier
to generate correct code. Fixes the motor-point test.
This commit is contained in:
Bill Currie 2023-09-18 19:36:15 +09:00
parent 7646f6b51e
commit 068f685fde
2 changed files with 24 additions and 17 deletions

View file

@ -601,11 +601,19 @@ print_extend (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
{
int indent = level * 2 + 2;
ex_extend_t extend = e->e.extend;
int ext = extend.extend;
if (ext < 0 || ext > 3) {
ext = 4;
}
_print_expr (dstr, extend.src, level, id, next);
dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, extend.src);
dasprintf (dstr, "%*se_%p [label=\"extend %d\\n%d\"];\n", indent, "", e,
extend.extend, e->line);
dasprintf (dstr, "%*se_%p [label=\"extend [%d>%d%s:%s]\\n%d\"];\n",
indent, "", e,
type_width (get_type (extend.src)), type_width (extend.type),
extend.reverse ? ":r" : "",
((const char *[]){"0", "1", "c", "-1", "?"})[ext],
e->line);
}
static void

View file

@ -144,24 +144,23 @@ offset_cast (type_t *type, expr_t *expr, int offset)
if (type->meta != ty_basic) {
internal_error (expr, "offset cast to non-basic type");
}
if (expr->type == ex_expr && expr->e.expr.op == '+') {
auto e1 = expr->e.expr.e1;
auto e2 = expr->e.expr.e2;
if (e1->type == ex_extend) {
auto ext = e1->e.extend;
if (type_width (get_type (ext.src)) == type_width (type)) {
return alias_expr (type, ext.src, 0);
if (expr->type == ex_expr
&& (expr->e.expr.op == '+' || expr->e.expr.op == '-')) {
auto e1 = offset_cast (type, expr->e.expr.e1, offset);
auto e2 = offset_cast (type, expr->e.expr.e2, offset);
int op = expr->e.expr.op;
if (!e1) {
if (op == '-') {
e2 = neg_expr (e2);
}
return e2;
}
if (e2->type == ex_extend) {
auto ext = e2->e.extend;
if (type_width (get_type (ext.src)) == type_width (type)) {
return alias_expr (type, ext.src, 0);
}
if (offset >= type_width (get_type (ext.src))) {
return 0;
}
if (!e2) {
return e1;
}
auto cast = new_binary_expr (op, e1, e2);
cast->e.expr.type = type;
return cast;
}
if (expr->type == ex_extend) {
auto ext = expr->e.extend;