Make dereferencing operator binary, to account for segmentation

This commit is contained in:
Mid 2025-10-17 18:16:58 +03:00
parent fee8ea5cb3
commit 7a8b14308b
9 changed files with 113 additions and 101 deletions

View File

@ -55,8 +55,12 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
generic_visitor(&n->stmtReturn.val, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
}
} else if(n->nodeKind == AST_EXPR_BINARY_OP) {
generic_visitor(&n->exprBinOp.operands[0], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
generic_visitor(&n->exprBinOp.operands[1], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
if(n->exprBinOp.operands[0]) {
generic_visitor(&n->exprBinOp.operands[0], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
}
if(n->exprBinOp.operands[1]) {
generic_visitor(&n->exprBinOp.operands[1], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
}
} else if(n->nodeKind == AST_EXPR_CALL) {
generic_visitor(&n->exprCall.what, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
@ -101,6 +105,9 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
}
int ast_expression_equal(AST *a, AST *b) {
if(!a && !b) return 1;
if(a == b) return 1;
if(a->nodeKind != b->nodeKind) return 0;
if(a->nodeKind == AST_EXPR_PRIMITIVE) {

View File

@ -77,6 +77,8 @@ typedef enum ENUMPAK {
BINOP_LOGICAL_AND = 15,
BINOP_LOGICAL_OR = 16,
BINOP_DEREF = 17,
BINOP_WTF = 999,
} BinaryOp;
@ -106,7 +108,6 @@ static inline BinaryOp binop_comp_opposite(BinaryOp op) {
}
typedef enum ENUMPAK {
UNOP_DEREF = 0,
UNOP_NEGATE = 1,
UNOP_BITWISE_NOT = 2,
UNOP_REF = 3,

View File

@ -62,55 +62,29 @@ static void ast_segmented_dereference_visitor(AST **aptr, AST *stmt, AST *stmtPr
}
AST *n = *aptr;
if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_DEREF && type_is_segmented_pointer(n->exprUnOp.operand->expression.type)) {
if(n->nodeKind == AST_EXPR_BINARY_OP && n->exprBinOp.operator == BINOP_DEREF && type_is_segmented_pointer(n->exprBinOp.operands[0]->expression.type)) {
static size_t idx = 0;
AST *v;
if(n->exprUnOp.operand->nodeKind == AST_EXPR_VAR)
v = n->exprUnOp.operand;
if(n->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR)
v = n->exprBinOp.operands[0];
else
v = varify(tlc, chunk, &stmtPrev, stmt, n->exprUnOp.operand);
ScopeItem *si = calloc(1, sizeof(*si));
si->kind = SCOPEITEM_VAR;
si->type = primitive_parse("u16");
si->data.var.preclassed = true;
si->data.var.registerClass = REG_CLASS_DATASEGS;
si->data.var.precolored = true;
si->data.var.color = 0;
si->data.var.name = malp("$segtemp_%lu", idx++);
ast_tlc_add_var(tlc, si);
ASTExprVar *ev = calloc(1, sizeof(*ev));
ev->nodeKind = AST_EXPR_VAR;
ev->type = si->type;
ev->thing = si;
v = varify(tlc, chunk, &stmtPrev, stmt, n->exprBinOp.operands[0]);
ASTExprDot *edseg = calloc(1, sizeof(*edseg));
edseg->type = n->exprUnOp.operand->expression.type->record.fieldTypes[0];
edseg->type = n->exprBinOp.operands[0]->expression.type->record.fieldTypes[0];
edseg->nodeKind = AST_EXPR_DOT;
edseg->a = v;
edseg->b = strdup("segment");
ASTStmtAssign *ass = calloc(1, sizeof(*ass));
ass->nodeKind = AST_STMT_ASSIGN;
ass->what = (AST*) ev;
ass->to = (AST*) edseg;
ass->next = (AST*) stmt;
si->data.var.declaration = (AST*) ass;
if(stmtPrev)
stmtPrev->statement.next = (AST*) ass;
else
chunk->chunk.statementFirst = (AST*) ass;
stmtPrev = (AST*) ass;
ASTExprDot *ed = calloc(1, sizeof(*ed));
ed->type = n->exprUnOp.operand->expression.type->record.fieldTypes[1];
ed->type = n->exprBinOp.operands[0]->expression.type->record.fieldTypes[1];
ed->nodeKind = AST_EXPR_DOT;
ed->a = ast_deep_copy(v);
ed->b = strdup("offset");
n->exprUnOp.operand = (AST*) ed;
n->exprBinOp.operands[0] = (AST*) ed;
n->exprBinOp.operands[1] = (AST*) edseg;
}
}

View File

@ -65,9 +65,6 @@ static char *ast_dumpe(AST *tlc, AST *e) {
case UNOP_REF:
op = "&";
break;
case UNOP_DEREF:
op = "*";
break;
case UNOP_BITWISE_NOT:
op = "~";
break;
@ -84,6 +81,18 @@ static char *ast_dumpe(AST *tlc, AST *e) {
char *r = malp("%s%s", op, c);
free(c);
return r;
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF) {
char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]);
char *r;
if(e->exprBinOp.operands[1]) {
char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]);
r = malp("*[%s]%s", b, a);
free(b);
} else {
r = malp("*%s", a);
}
free(a);
return r;
} else if(e->nodeKind == AST_EXPR_BINARY_OP) {
char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]);
char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]);

View File

@ -46,11 +46,11 @@ static void spill2stack_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk
bop->operands[0] = (AST*) rsp;
bop->operands[1] = (AST*) offset;
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_UNARY_OP;
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_BINARY_OP;
deref->type = a->expression.type;
deref->operator = UNOP_DEREF;
deref->operand = (AST*) bop;
deref->operator = BINOP_DEREF;
deref->operands[0] = (AST*) bop;
*aptr = (AST*) deref;
}

View File

@ -297,11 +297,11 @@ AST *nct_parse_expression(Parser *P, int lOP) {
if(op.type == TOKEN_DOT) {
while(e->expression.type->type == TYPE_TYPE_POINTER) {
AST *deref = alloc_node(P, sizeof(ASTExprUnaryOp));
deref->nodeKind = AST_EXPR_UNARY_OP;
deref->exprUnOp.operator = UNOP_DEREF;
deref->exprUnOp.operand = (AST*) e;
deref->exprUnOp.type = type_dereference(e->expression.type);
AST *deref = alloc_node(P, sizeof(ASTExprBinaryOp));
deref->nodeKind = AST_EXPR_BINARY_OP;
deref->exprBinOp.operator = BINOP_DEREF;
deref->exprBinOp.operands[0] = (AST*) e;
deref->exprBinOp.type = type_dereference(e->expression.type);
e = (AST*) deref;
}
@ -434,11 +434,11 @@ AST *nct_parse_expression(Parser *P, int lOP) {
child->operands[1] = (AST*) mul;
}
ASTExprUnaryOp *unop = alloc_node(P, sizeof(*unop));
unop->nodeKind = AST_EXPR_UNARY_OP;
ASTExprBinaryOp *unop = alloc_node(P, sizeof(*unop));
unop->nodeKind = AST_EXPR_BINARY_OP;
unop->type = e->expression.type->array.of;
unop->operator = UNOP_DEREF;
unop->operand = (AST*) child;
unop->operator = BINOP_DEREF;
unop->operands[0] = (AST*) child;
expect(P, TOKEN_SQUAREN_R);
@ -452,16 +452,16 @@ AST *nct_parse_expression(Parser *P, int lOP) {
return e;
} else if(lOP == 6) {
if(maybe(P, TOKEN_STAR)) {
ASTExprUnaryOp *astop = alloc_node(P, sizeof(*astop));
astop->nodeKind = AST_EXPR_UNARY_OP;
astop->operator = UNOP_DEREF;
astop->operand = nct_parse_expression(P, lOP); /* Not +1! */
ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop));
astop->nodeKind = AST_EXPR_BINARY_OP;
astop->operator = BINOP_DEREF;
astop->operands[0] = nct_parse_expression(P, lOP); /* Not +1! */
if(type_is_segmented_pointer(astop->operand->expression.type)) {
astop->type = astop->operand->expression.type->record.fieldTypes[1]->pointer.of;
if(type_is_segmented_pointer(astop->operands[0]->expression.type)) {
astop->type = astop->operands[0]->expression.type->record.fieldTypes[1]->pointer.of;
} else {
assert(astop->operand->expression.type->type == TYPE_TYPE_POINTER);
astop->type = astop->operand->expression.type->pointer.of;
assert(astop->operands[0]->expression.type->type == TYPE_TYPE_POINTER);
astop->type = astop->operands[0]->expression.type->pointer.of;
}
return (AST*) astop;

View File

@ -133,12 +133,12 @@ static inline int is_xop(AST *e) {
return XOP_NOT_MEM;
} else if(e->nodeKind == AST_EXPR_VAR) {
return e->exprVar.thing->kind == SCOPEITEM_VAR ? XOP_NOT_MEM : XOP_MEM;
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operator == BINOP_ADD && is_xop(e->exprUnOp.operand->exprBinOp.operands[0]) == XOP_NOT_MEM && is_xop(e->exprUnOp.operand->exprBinOp.operands[1]) == XOP_NOT_MEM) {
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF && e->exprBinOp.operands[0]->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operands[0]->exprBinOp.operator == BINOP_ADD && is_xop(e->exprBinOp.operands[0]->exprBinOp.operands[0]) == XOP_NOT_MEM && is_xop(e->exprBinOp.operands[0]->exprBinOp.operands[1]) == XOP_NOT_MEM) {
return XOP_MEM;
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprVar.thing->kind == SCOPEITEM_SYMBOL) {
return XOP_NOT_MEM;
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
AST *c = e->exprUnOp.operand;
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF) {
AST *c = e->exprBinOp.operands[0];
if(c->nodeKind == AST_EXPR_CAST && c->exprCast.what->expression.type->type == TYPE_TYPE_POINTER && c->exprCast.to->type == TYPE_TYPE_POINTER) {
c = c->exprCast.what;

View File

@ -115,11 +115,11 @@ static const char *xj(BinaryOp op) {
}
static AST *is_field_access(AST *e) {
if(e->nodeKind != AST_EXPR_UNARY_OP || e->exprUnOp.operator != UNOP_DEREF) {
if(e->nodeKind != AST_EXPR_BINARY_OP || e->exprUnOp.operator != BINOP_DEREF) {
return NULL;
}
e = e->exprUnOp.operand;
e = e->exprBinOp.operands[0];
if(e->nodeKind == AST_EXPR_CAST && e->exprCast.what->expression.type->type == TYPE_TYPE_POINTER && e->exprCast.to->type == TYPE_TYPE_POINTER) {
e = e->exprCast.what;
@ -136,6 +136,16 @@ static AST *is_field_access(AST *e) {
return NULL;
}
static const char *segment_or_empty(AST *a) {
if(!a) {
return "ds";
}
assert(a->nodeKind == AST_EXPR_VAR);
assert(a->exprVar.thing->kind == SCOPEITEM_VAR);
assert(a->exprVar.thing->data.var.registerClass == REG_CLASS_DATASEGS);
return REG_CLASSES[REG_CLASS_DATASEGS].rsN[a->exprVar.thing->data.var.color];
}
/*
* Convert a XOP-able expression into an x86 operand.
* Result MUST be determinstic and always the same, for the same given expression.
@ -150,21 +160,24 @@ static const char *xop_sz(AST *tlc, AST *e, int sz) {
int pr = 0;
if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
AST *p = e->exprUnOp.operand;
if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF) {
AST *seg = e->exprBinOp.operands[1];
AST *p = e->exprBinOp.operands[0];
if(p->nodeKind == AST_EXPR_CAST && p->exprCast.to->type == TYPE_TYPE_POINTER) {
p = p->exprCast.what;
}
if(p->nodeKind == AST_EXPR_BINARY_OP && p->exprBinOp.operator == BINOP_ADD && p->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[0]->exprVar.thing->kind == SCOPEITEM_VAR && p->exprBinOp.operands[1]->exprVar.thing->kind == SCOPEITEM_VAR) {
pr = snprintf(ret, XOPBUFSZ, "%s [%s + %s]",
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s + %s]",
spec(sz),
segment_or_empty(seg),
xv_sz(p->exprBinOp.operands[0]->exprVar.thing, 0),
xv_sz(p->exprBinOp.operands[1]->exprVar.thing, 0));
} else if(p->nodeKind == AST_EXPR_BINARY_OP && p->exprBinOp.operator == BINOP_ADD && p->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && p->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && p->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == SCOPEITEM_SYMBOL && p->exprBinOp.operands[1]->exprVar.thing->kind == SCOPEITEM_VAR) {
pr = snprintf(ret, XOPBUFSZ, "%s [%s + %s]",
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s + %s]",
spec(sz),
segment_or_empty(seg),
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
xv_sz(p->exprBinOp.operands[1]->exprVar.thing, 0));
} else if(is_field_access(e)) {
@ -173,8 +186,9 @@ static const char *xop_sz(AST *tlc, AST *e, int sz) {
if(e->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP) {
assert(e->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF);
pr = snprintf(ret, XOPBUFSZ, "%s [%s + %i]",
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s + %i]",
spec(sz),
segment_or_empty(seg),
e->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
e->exprBinOp.operands[1]->exprPrim.val);
} else {
@ -182,19 +196,21 @@ static const char *xop_sz(AST *tlc, AST *e, int sz) {
ScopeItem *vte = e->exprBinOp.operands[0]->exprVar.thing;
pr = snprintf(ret, XOPBUFSZ, "%s [%s + %i]",
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s + %i]",
spec(sz),
segment_or_empty(seg),
REG_CLASSES[vte->data.var.registerClass].rsN[vte->data.var.color],
e->exprBinOp.operands[1]->exprPrim.val);
}
} else if(p->nodeKind == AST_EXPR_BINARY_OP && p->exprBinOp.operator == BINOP_ADD && p->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && p->exprBinOp.operands[1]->nodeKind == AST_EXPR_BINARY_OP && p->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && p->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == SCOPEITEM_SYMBOL && p->exprBinOp.operands[1]->exprBinOp.operator == BINOP_MUL && p->exprBinOp.operands[1]->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && p->exprBinOp.operands[1]->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && p->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing->kind == SCOPEITEM_VAR) {
pr = snprintf(ret, XOPBUFSZ, "%s [%s + %i * %s]",
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s + %i * %s]",
spec(sz),
segment_or_empty(seg),
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
p->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val,
xv_sz(p->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing, 0));
} else if(p->nodeKind == AST_EXPR_VAR && p->exprVar.thing->kind == SCOPEITEM_VAR) {
pr = snprintf(ret, XOPBUFSZ, "%s [%s]", spec(sz), xv_sz(p->exprVar.thing, 0));
pr = snprintf(ret, XOPBUFSZ, "%s %s:[%s]", spec(sz), segment_or_empty(seg), xv_sz(p->exprVar.thing, 0));
} else if(p->nodeKind == AST_EXPR_STACK_POINTER) {
if(x86_ia16()) {
pr = snprintf(ret, XOPBUFSZ, "[bp + %li]", 0 - tlc->chunk.stackReservation);
@ -632,14 +648,6 @@ void cg_chunk(CGState *cg, AST *a) {
printf("ret\n");
} else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_VAR) {
/* Loop guard, probably. */
} else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_UNARY_OP && s->stmtExpr.expr->exprUnOp.operator == UNOP_DEREF && s->stmtExpr.expr->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && s->stmtExpr.expr->exprUnOp.operand->exprBinOp.operator == BINOP_ADD && s->stmtExpr.expr->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_STACK_POINTER && s->stmtExpr.expr->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE) {
/* Loop guard for a spilled variable, probably. */
} else {
stahp_node(s, "Unknown statement %s caught by code generator.", AST_KIND_STR[s->nodeKind]);

View File

@ -307,18 +307,18 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
this->effective = 1;
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->exprUnOp.operator == UNOP_DEREF
&& s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) {
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.what->exprBinOp.operator == BINOP_DEREF
&& s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator == BINOP_DEREF) {
s->stmtAssign.to = varify(tlc, chu, stmtPrev, s, s->stmtAssign.to);
this->effective = 1;
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->exprUnOp.operator == UNOP_DEREF && !is_xop(s->stmtAssign.what)) {
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.what->exprBinOp.operator == BINOP_DEREF && !is_xop(s->stmtAssign.what)) {
s->stmtAssign.what->exprUnOp.operand = varify(tlc, chu, stmtPrev, s, s->stmtAssign.what->exprUnOp.operand);
s->stmtAssign.what->exprBinOp.operands[0] = varify(tlc, chu, stmtPrev, s, s->stmtAssign.what->exprBinOp.operands[0]);
mark_ptr(s->stmtAssign.what->exprUnOp.operand);
mark_ptr(s->stmtAssign.what->exprBinOp.operands[0]);
this->effective = 1;
@ -371,10 +371,10 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
this->effective = 1;
} else if(is_xop(s->stmtAssign.to) == XOP_NOT_XOP) {
if(s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) {
s->stmtAssign.to->exprUnOp.operand = varify(tlc, chu, stmtPrev, s, s->stmtAssign.to->exprUnOp.operand);
if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprUnOp.operator == BINOP_DEREF) {
s->stmtAssign.to->exprBinOp.operands[0] = varify(tlc, chu, stmtPrev, s, s->stmtAssign.to->exprBinOp.operands[0]);
mark_ptr(s->stmtAssign.to->exprUnOp.operand);
mark_ptr(s->stmtAssign.to->exprBinOp.operands[0]);
this->effective = 1;
} else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator == BINOP_MUL) {
@ -502,11 +502,11 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
sum->operands[1] = (AST*) offset;
sum->operator = BINOP_ADD;
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_UNARY_OP;
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_BINARY_OP;
deref->type = vte->type;
deref->operand = (AST*) sum;
deref->operator = UNOP_DEREF;
deref->operands[0] = (AST*) sum;
deref->operator = BINOP_DEREF;
ASTExprVar *evar = calloc(1, sizeof(*evar));
evar->nodeKind = AST_EXPR_VAR;
@ -567,11 +567,11 @@ static void decompose_symbol_record_field_access(AST **nptr, AST *stmt, AST *stm
AST *cast = ast_cast_expr((AST*) sum, type_pointer_wrap(n->exprDot.a->expression.type->record.fieldTypes[f]));
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_UNARY_OP;
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
deref->nodeKind = AST_EXPR_BINARY_OP;
deref->type = cast->expression.type->pointer.of;
deref->operator = UNOP_DEREF;
deref->operand = cast;
deref->operator = BINOP_DEREF;
deref->operands[0] = cast;
*nptr = (AST*) deref;
}
@ -608,13 +608,13 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
prim->val = ntc_get_int_default("null", 0);
*nptr = (AST*) prim;
} else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_REF && n->exprUnOp.operand->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operand->exprUnOp.operator == UNOP_DEREF) {
} else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_REF && n->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && n->exprUnOp.operand->exprBinOp.operator == BINOP_DEREF) {
// Turn `&*a` into `a`
// Artificially change type of casted expression to keep types valid for subsequent passes
n->exprUnOp.operand->exprUnOp.operand->expression.type = n->expression.type;
n->exprUnOp.operand->exprBinOp.operands[0]->expression.type = n->expression.type;
*nptr = n->exprUnOp.operand->exprUnOp.operand;
*nptr = n->exprUnOp.operand->exprBinOp.operands[0];
*success = true;
} else if(is_double_field_access(n)) {
@ -778,10 +778,23 @@ static void convention_correctness_visitor(AST **nptr, AST *stmt, AST *stmtPrev,
}
}
static void decompose_segmented_dereferences(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
AST *n = *nptr;
if(n->nodeKind == AST_EXPR_BINARY_OP && n->exprBinOp.operator == BINOP_DEREF && n->exprBinOp.operands[1]) {
AST *seg = n->exprBinOp.operands[1];
if(seg->nodeKind != AST_EXPR_VAR || seg->exprVar.thing->kind != SCOPEITEM_VAR || seg->exprVar.thing->data.var.registerClass != REG_CLASS_DATASEGS) {
seg = n->exprBinOp.operands[1] = varify(tlc, chunk, stmtPrev, stmt, seg);
seg->exprVar.thing->data.var.preclassed = true;
seg->exprVar.thing->data.var.registerClass = REG_CLASS_DATASEGS;
}
}
}
void arch_normalize_pre(AST *tlc) {
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, convention_correctness_visitor, NULL);
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, pre_norm_visitor, NULL);
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, decompose_symbol_record_field_access, NULL);
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, decompose_segmented_dereferences, NULL);
for(size_t t = 0; t < tlc->chunk.varCount;) {
if(ast_is_scopeitem_referenced(tlc, tlc->chunk.vars[t]) || tlc->chunk.vars[t]->type->type == TYPE_TYPE_RECORD) {