Make dereferencing operator binary, to account for segmentation
This commit is contained in:
parent
fee8ea5cb3
commit
7a8b14308b
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
34
src/parse.c
34
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
44
src/x86/cg.c
44
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]);
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user