From 7a8b14308b5de1a3d6861b3dcf4964a7e1c4029b Mon Sep 17 00:00:00 2001 From: Mid <> Date: Fri, 17 Oct 2025 18:16:58 +0300 Subject: [PATCH] Make dereferencing operator binary, to account for segmentation --- src/ast/ast.c | 11 ++++++++-- src/ast/ast.h | 3 ++- src/ast/desegment.c | 42 +++++++------------------------------ src/ast/dump.c | 15 ++++++++++--- src/ast/stack.c | 8 +++---- src/parse.c | 34 +++++++++++++++--------------- src/x86/arch.h | 6 +++--- src/x86/cg.c | 44 ++++++++++++++++++++++---------------- src/x86/normalize.c | 51 ++++++++++++++++++++++++++++----------------- 9 files changed, 113 insertions(+), 101 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index ce85230..8e597f0 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -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) { diff --git a/src/ast/ast.h b/src/ast/ast.h index 422e052..07b9e31 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -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, diff --git a/src/ast/desegment.c b/src/ast/desegment.c index 99727ad..21d1a5b 100644 --- a/src/ast/desegment.c +++ b/src/ast/desegment.c @@ -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; } } diff --git a/src/ast/dump.c b/src/ast/dump.c index a4cafbe..ff20671 100644 --- a/src/ast/dump.c +++ b/src/ast/dump.c @@ -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]); diff --git a/src/ast/stack.c b/src/ast/stack.c index 560d3e5..003a082 100644 --- a/src/ast/stack.c +++ b/src/ast/stack.c @@ -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; } diff --git a/src/parse.c b/src/parse.c index 28ea10b..d801015 100644 --- a/src/parse.c +++ b/src/parse.c @@ -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; diff --git a/src/x86/arch.h b/src/x86/arch.h index 6a0bb27..56fb799 100644 --- a/src/x86/arch.h +++ b/src/x86/arch.h @@ -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; diff --git a/src/x86/cg.c b/src/x86/cg.c index 0cc568d..f782961 100644 --- a/src/x86/cg.c +++ b/src/x86/cg.c @@ -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]); diff --git a/src/x86/normalize.c b/src/x86/normalize.c index 943ae25..89b41a9 100644 --- a/src/x86/normalize.c +++ b/src/x86/normalize.c @@ -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) {