Compare commits
10 Commits
692ed4d21c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f406b2a032 | ||
|
|
7a8b14308b | ||
|
|
fee8ea5cb3 | ||
|
|
2aa64f4a37 | ||
|
|
8c164a3b09 | ||
|
|
8c4754b563 | ||
|
|
9d975eeceb | ||
|
|
ecab77f9e9 | ||
|
|
132cedff09 | ||
|
|
f978b66662 |
@@ -46,8 +46,28 @@ MapDQCOaLDhS_try_add: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this, K* key, V* value)
|
|||||||
};
|
};
|
||||||
|
|
||||||
MapDQCOaLDhS_expand: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this) -> {
|
MapDQCOaLDhS_expand: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this) -> {
|
||||||
/* Unimplemented. */
|
S capacity = this.capacity;
|
||||||
return 0;
|
KVPair[K, V][?]* old_data = this.data;
|
||||||
|
u8[?]* old_occupied = this.occupied;
|
||||||
|
|
||||||
|
S new_capacity = capacity * 2;
|
||||||
|
this.capacity = new_capacity;
|
||||||
|
this.data = calloc(new_capacity, @sizeof KVPair[K, V]);
|
||||||
|
this.occupied = calloc(new_capacity, @sizeof((*this.occupied)[0]));
|
||||||
|
|
||||||
|
S i = 0;
|
||||||
|
loop {
|
||||||
|
if(i == capacity) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((*old_occupied)[i] != 0) {
|
||||||
|
KVPair[K, V]* pair = &((*old_data)[i]);
|
||||||
|
MapDQCOaLDhS_try_add[K, V, S](this, &pair.key, &pair.value);
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
MapDQCOaLDhS_add: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this, K* key, V* value) -> {
|
MapDQCOaLDhS_add: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this, K* key, V* value) -> {
|
||||||
|
|||||||
@@ -49,14 +49,22 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
|
|||||||
} else if(n->nodeKind == AST_STMT_EXPR) {
|
} else if(n->nodeKind == AST_STMT_EXPR) {
|
||||||
generic_visitor(&n->stmtExpr.expr, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
generic_visitor(&n->stmtExpr.expr, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
||||||
} else if(n->nodeKind == AST_STMT_EXT_ORG) {
|
} else if(n->nodeKind == AST_STMT_EXT_ORG) {
|
||||||
} else if(n->nodeKind == AST_STMT_EXT_SECTION) {
|
} else if(n->nodeKind == AST_SECTION) {
|
||||||
|
generic_visitor(&n->section.tlc, stmt, stmtPrev, n->section.tlc, n->section.tlc, ud, preHandler, postHandler);
|
||||||
|
if(n->section.next) {
|
||||||
|
generic_visitor(&n->section.next, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
||||||
|
}
|
||||||
} else if(n->nodeKind == AST_STMT_RETURN) {
|
} else if(n->nodeKind == AST_STMT_RETURN) {
|
||||||
if(n->stmtReturn.val) {
|
if(n->stmtReturn.val) {
|
||||||
generic_visitor(&n->stmtReturn.val, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
generic_visitor(&n->stmtReturn.val, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
||||||
}
|
}
|
||||||
} else if(n->nodeKind == AST_EXPR_BINARY_OP) {
|
} else if(n->nodeKind == AST_EXPR_BINARY_OP) {
|
||||||
|
if(n->exprBinOp.operands[0]) {
|
||||||
generic_visitor(&n->exprBinOp.operands[0], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
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);
|
generic_visitor(&n->exprBinOp.operands[1], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
||||||
|
}
|
||||||
} else if(n->nodeKind == AST_EXPR_CALL) {
|
} else if(n->nodeKind == AST_EXPR_CALL) {
|
||||||
generic_visitor(&n->exprCall.what, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
generic_visitor(&n->exprCall.what, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
||||||
|
|
||||||
@@ -101,6 +109,9 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ast_expression_equal(AST *a, AST *b) {
|
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 != b->nodeKind) return 0;
|
||||||
|
|
||||||
if(a->nodeKind == AST_EXPR_PRIMITIVE) {
|
if(a->nodeKind == AST_EXPR_PRIMITIVE) {
|
||||||
@@ -238,7 +249,8 @@ AST *ast_cast_expr(AST *what, Type *to) {
|
|||||||
ASTExprPrimitive *ret = calloc(1, sizeof(*ret));
|
ASTExprPrimitive *ret = calloc(1, sizeof(*ret));
|
||||||
ret->nodeKind = AST_EXPR_PRIMITIVE;
|
ret->nodeKind = AST_EXPR_PRIMITIVE;
|
||||||
ret->type = to;
|
ret->type = to;
|
||||||
memcpy(&ret->val, what->exprStrLit.data, sizeof(ret->val));
|
ret->val = 0;
|
||||||
|
memcpy(&ret->val, what->exprStrLit.data, what->exprStrLit.length);
|
||||||
return (AST*) ret;
|
return (AST*) ret;
|
||||||
} else abort();
|
} else abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
K(AST_EXPR_ARRAY) \
|
K(AST_EXPR_ARRAY) \
|
||||||
K(AST_EXPR_FUNC) \
|
K(AST_EXPR_FUNC) \
|
||||||
K(AST_STMT_EXT_ORG) \
|
K(AST_STMT_EXT_ORG) \
|
||||||
K(AST_STMT_EXT_SECTION) \
|
K(AST_SECTION) \
|
||||||
K(AST_STMT_RETURN) \
|
K(AST_STMT_RETURN) \
|
||||||
K(AST_EXPR_EXT_SALLOC) \
|
K(AST_EXPR_EXT_SALLOC) \
|
||||||
K(AST_EXPR_DOT) \
|
K(AST_EXPR_DOT) \
|
||||||
@@ -77,6 +77,8 @@ typedef enum ENUMPAK {
|
|||||||
BINOP_LOGICAL_AND = 15,
|
BINOP_LOGICAL_AND = 15,
|
||||||
BINOP_LOGICAL_OR = 16,
|
BINOP_LOGICAL_OR = 16,
|
||||||
|
|
||||||
|
BINOP_DEREF = 17,
|
||||||
|
|
||||||
BINOP_WTF = 999,
|
BINOP_WTF = 999,
|
||||||
} BinaryOp;
|
} BinaryOp;
|
||||||
|
|
||||||
@@ -106,7 +108,6 @@ static inline BinaryOp binop_comp_opposite(BinaryOp op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef enum ENUMPAK {
|
typedef enum ENUMPAK {
|
||||||
UNOP_DEREF = 0,
|
|
||||||
UNOP_NEGATE = 1,
|
UNOP_NEGATE = 1,
|
||||||
UNOP_BITWISE_NOT = 2,
|
UNOP_BITWISE_NOT = 2,
|
||||||
UNOP_REF = 3,
|
UNOP_REF = 3,
|
||||||
@@ -203,7 +204,17 @@ typedef struct {
|
|||||||
union AST *expression;
|
union AST *expression;
|
||||||
} ASTStmtDecl;
|
} ASTStmtDecl;
|
||||||
|
|
||||||
typedef struct {
|
struct ASTChunk;
|
||||||
|
typedef struct ASTSection {
|
||||||
|
ASTBase;
|
||||||
|
|
||||||
|
Token name;
|
||||||
|
struct ASTChunk *tlc;
|
||||||
|
|
||||||
|
struct ASTSection *next;
|
||||||
|
} ASTSection;
|
||||||
|
|
||||||
|
typedef struct ASTChunk {
|
||||||
ASTBase;
|
ASTBase;
|
||||||
|
|
||||||
/* Flattened variable array for global register allocation */
|
/* Flattened variable array for global register allocation */
|
||||||
@@ -299,12 +310,6 @@ typedef struct {
|
|||||||
size_t val;
|
size_t val;
|
||||||
} ASTStmtExtOrg;
|
} ASTStmtExtOrg;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ASTStmt;
|
|
||||||
|
|
||||||
Token name;
|
|
||||||
} ASTStmtExtSection;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ASTStmt;
|
ASTStmt;
|
||||||
|
|
||||||
@@ -363,7 +368,7 @@ typedef union AST {
|
|||||||
ASTExprDot exprDot;
|
ASTExprDot exprDot;
|
||||||
ASTExprExtSalloc exprExtSalloc;
|
ASTExprExtSalloc exprExtSalloc;
|
||||||
ASTStmtExtOrg stmtExtOrg;
|
ASTStmtExtOrg stmtExtOrg;
|
||||||
ASTStmtExtSection stmtExtSection;
|
ASTSection section;
|
||||||
ASTExprExtSizeOf exprExtSizeOf;
|
ASTExprExtSizeOf exprExtSizeOf;
|
||||||
ASTStmtJump stmtJump;
|
ASTStmtJump stmtJump;
|
||||||
ASTStmtLabel stmtLabel;
|
ASTStmtLabel stmtLabel;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ static AST *varify(AST *tlc, AST *chunk, AST **stmtPrev, AST *stmt, AST *e) {
|
|||||||
assign->nodeKind = AST_STMT_ASSIGN;
|
assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
assign->what = (AST*) ev[0];
|
assign->what = (AST*) ev[0];
|
||||||
assign->to = e;
|
assign->to = e;
|
||||||
|
vte->data.var.declaration = (AST*) assign;
|
||||||
|
|
||||||
if(*stmtPrev) {
|
if(*stmtPrev) {
|
||||||
(*stmtPrev)->statement.next = (AST*) assign;
|
(*stmtPrev)->statement.next = (AST*) assign;
|
||||||
@@ -61,54 +62,29 @@ static void ast_segmented_dereference_visitor(AST **aptr, AST *stmt, AST *stmtPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
AST *n = *aptr;
|
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;
|
static size_t idx = 0;
|
||||||
|
|
||||||
AST *v;
|
AST *v;
|
||||||
if(n->exprUnOp.operand->nodeKind == AST_EXPR_VAR)
|
if(n->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR)
|
||||||
v = n->exprUnOp.operand;
|
v = n->exprBinOp.operands[0];
|
||||||
else
|
else
|
||||||
v = varify(tlc, chunk, &stmtPrev, stmt, n->exprUnOp.operand);
|
v = varify(tlc, chunk, &stmtPrev, stmt, n->exprBinOp.operands[0]);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
ASTExprDot *edseg = calloc(1, sizeof(*edseg));
|
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->nodeKind = AST_EXPR_DOT;
|
||||||
edseg->a = v;
|
edseg->a = v;
|
||||||
edseg->b = strdup("segment");
|
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;
|
|
||||||
if(stmtPrev)
|
|
||||||
stmtPrev->statement.next = (AST*) ass;
|
|
||||||
else
|
|
||||||
chunk->chunk.statementFirst = (AST*) ass;
|
|
||||||
stmtPrev = (AST*) ass;
|
|
||||||
|
|
||||||
ASTExprDot *ed = calloc(1, sizeof(*ed));
|
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->nodeKind = AST_EXPR_DOT;
|
||||||
ed->a = ast_deep_copy(v);
|
ed->a = ast_deep_copy(v);
|
||||||
ed->b = strdup("offset");
|
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:
|
case UNOP_REF:
|
||||||
op = "&";
|
op = "&";
|
||||||
break;
|
break;
|
||||||
case UNOP_DEREF:
|
|
||||||
op = "*";
|
|
||||||
break;
|
|
||||||
case UNOP_BITWISE_NOT:
|
case UNOP_BITWISE_NOT:
|
||||||
op = "~";
|
op = "~";
|
||||||
break;
|
break;
|
||||||
@@ -84,6 +81,18 @@ static char *ast_dumpe(AST *tlc, AST *e) {
|
|||||||
char *r = malp("%s%s", op, c);
|
char *r = malp("%s%s", op, c);
|
||||||
free(c);
|
free(c);
|
||||||
return r;
|
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) {
|
} else if(e->nodeKind == AST_EXPR_BINARY_OP) {
|
||||||
char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]);
|
char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]);
|
||||||
char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]);
|
char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ static void ast_decompose_automatic_record(AST *tlc, ScopeItem *target) {
|
|||||||
si->kind = SCOPEITEM_VAR;
|
si->kind = SCOPEITEM_VAR;
|
||||||
si->type = target->type->record.fieldTypes[f];
|
si->type = target->type->record.fieldTypes[f];
|
||||||
si->data.var.name = malp("%s_sroa_%s", target->data.var.name, target->type->record.fieldNames[f]);
|
si->data.var.name = malp("%s_sroa_%s", target->data.var.name, target->type->record.fieldNames[f]);
|
||||||
|
si->data.var.declaration = target->data.var.declaration;
|
||||||
state.replacements[f] = si;
|
state.replacements[f] = si;
|
||||||
|
|
||||||
tlc->chunk.vars[tlc->chunk.varCount++] = si;
|
tlc->chunk.vars[tlc->chunk.varCount++] = si;
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ static void spill2stack_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk
|
|||||||
bop->operands[0] = (AST*) rsp;
|
bop->operands[0] = (AST*) rsp;
|
||||||
bop->operands[1] = (AST*) offset;
|
bop->operands[1] = (AST*) offset;
|
||||||
|
|
||||||
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
|
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
|
||||||
deref->nodeKind = AST_EXPR_UNARY_OP;
|
deref->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
deref->type = a->expression.type;
|
deref->type = a->expression.type;
|
||||||
deref->operator = UNOP_DEREF;
|
deref->operator = BINOP_DEREF;
|
||||||
deref->operand = (AST*) bop;
|
deref->operands[0] = (AST*) bop;
|
||||||
|
|
||||||
*aptr = (AST*) deref;
|
*aptr = (AST*) deref;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ void ast_usedef_reset(AST *chu) {
|
|||||||
for(size_t sii = 0; sii < chu->chunk.varCount; sii++) {
|
for(size_t sii = 0; sii < chu->chunk.varCount; sii++) {
|
||||||
ScopeItem *si = chu->chunk.vars[sii];
|
ScopeItem *si = chu->chunk.vars[sii];
|
||||||
|
|
||||||
|
assert(si->data.var.declaration != NULL && "All local vars must have defined declaration location");
|
||||||
|
|
||||||
if(ast_stmt_is_after(chu, si->data.var.liveRangeEnd, s) == 0 && ast_stmt_is_after(chu, target, si->data.var.liveRangeEnd) == 0 && ast_stmt_is_after(chu, si->data.var.declaration, target) == 0) {
|
if(ast_stmt_is_after(chu, si->data.var.liveRangeEnd, s) == 0 && ast_stmt_is_after(chu, target, si->data.var.liveRangeEnd) == 0 && ast_stmt_is_after(chu, si->data.var.declaration, target) == 0) {
|
||||||
|
|
||||||
si->data.var.liveRangeEnd = s;
|
si->data.var.liveRangeEnd = s;
|
||||||
|
|||||||
22
src/ntc.c
22
src/ntc.c
@@ -86,28 +86,30 @@ int main(int argc_, char **argv_) {
|
|||||||
|
|
||||||
if(in) fclose(f);
|
if(in) fclose(f);
|
||||||
|
|
||||||
AST *chunk = nct_parse(tokens);
|
AST *sects = nct_parse(tokens);
|
||||||
|
|
||||||
free(tokens);
|
free(tokens);
|
||||||
|
|
||||||
if(ntc_get_int("pdbg")) {
|
if(ntc_get_int("pdbg")) {
|
||||||
char *astdump = ast_dump(chunk);
|
char *astdump = ast_dump(sects);
|
||||||
fprintf(stderr, "### ORIGINAL ###\n%s\n", astdump);
|
fprintf(stderr, "### ORIGINAL ###\n%s\n", astdump);
|
||||||
free(astdump);
|
free(astdump);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_segmented_dereference(chunk);
|
ast_segmented_dereference(sects);
|
||||||
ast_secondclass_record(chunk);
|
ast_secondclass_record(sects);
|
||||||
ast_sroa(chunk);
|
ast_sroa(sects);
|
||||||
|
|
||||||
ast_linearize(chunk);
|
ast_linearize(sects);
|
||||||
|
|
||||||
arch_normalize_pre(chunk);
|
arch_normalize_pre(sects);
|
||||||
|
|
||||||
arch_normalize(chunk);
|
arch_normalize(sects);
|
||||||
while(!cg_go(chunk)) {
|
while(!cg_attempt_sections(sects)) {
|
||||||
arch_normalize(chunk);
|
arch_normalize(sects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cg_go_sections(sects);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ bool arch_verify_target();
|
|||||||
int arch_ptr_size();
|
int arch_ptr_size();
|
||||||
void arch_normalize_pre(union AST *tlc);
|
void arch_normalize_pre(union AST *tlc);
|
||||||
void arch_normalize(union AST *tlc);
|
void arch_normalize(union AST *tlc);
|
||||||
int cg_go(union AST *tlc);
|
int cg_attempt_sections(union AST *tlc);
|
||||||
|
void cg_go_sections(union AST *tlc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
106
src/parse.c
106
src/parse.c
@@ -297,11 +297,11 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
|
|
||||||
if(op.type == TOKEN_DOT) {
|
if(op.type == TOKEN_DOT) {
|
||||||
while(e->expression.type->type == TYPE_TYPE_POINTER) {
|
while(e->expression.type->type == TYPE_TYPE_POINTER) {
|
||||||
AST *deref = alloc_node(P, sizeof(ASTExprUnaryOp));
|
AST *deref = alloc_node(P, sizeof(ASTExprBinaryOp));
|
||||||
deref->nodeKind = AST_EXPR_UNARY_OP;
|
deref->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
deref->exprUnOp.operator = UNOP_DEREF;
|
deref->exprBinOp.operator = BINOP_DEREF;
|
||||||
deref->exprUnOp.operand = (AST*) e;
|
deref->exprBinOp.operands[0] = (AST*) e;
|
||||||
deref->exprUnOp.type = type_dereference(e->expression.type);
|
deref->exprBinOp.type = type_dereference(e->expression.type);
|
||||||
|
|
||||||
e = (AST*) deref;
|
e = (AST*) deref;
|
||||||
}
|
}
|
||||||
@@ -434,11 +434,11 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
child->operands[1] = (AST*) mul;
|
child->operands[1] = (AST*) mul;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTExprUnaryOp *unop = alloc_node(P, sizeof(*unop));
|
ASTExprBinaryOp *unop = alloc_node(P, sizeof(*unop));
|
||||||
unop->nodeKind = AST_EXPR_UNARY_OP;
|
unop->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
unop->type = e->expression.type->array.of;
|
unop->type = e->expression.type->array.of;
|
||||||
unop->operator = UNOP_DEREF;
|
unop->operator = BINOP_DEREF;
|
||||||
unop->operand = (AST*) child;
|
unop->operands[0] = (AST*) child;
|
||||||
|
|
||||||
expect(P, TOKEN_SQUAREN_R);
|
expect(P, TOKEN_SQUAREN_R);
|
||||||
|
|
||||||
@@ -452,16 +452,16 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
return e;
|
return e;
|
||||||
} else if(lOP == 6) {
|
} else if(lOP == 6) {
|
||||||
if(maybe(P, TOKEN_STAR)) {
|
if(maybe(P, TOKEN_STAR)) {
|
||||||
ASTExprUnaryOp *astop = alloc_node(P, sizeof(*astop));
|
ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop));
|
||||||
astop->nodeKind = AST_EXPR_UNARY_OP;
|
astop->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
astop->operator = UNOP_DEREF;
|
astop->operator = BINOP_DEREF;
|
||||||
astop->operand = nct_parse_expression(P, lOP); /* Not +1! */
|
astop->operands[0] = nct_parse_expression(P, lOP); /* Not +1! */
|
||||||
|
|
||||||
if(type_is_segmented_pointer(astop->operand->expression.type)) {
|
if(type_is_segmented_pointer(astop->operands[0]->expression.type)) {
|
||||||
astop->type = astop->operand->expression.type->record.fieldTypes[1]->pointer.of;
|
astop->type = astop->operands[0]->expression.type->record.fieldTypes[1]->pointer.of;
|
||||||
} else {
|
} else {
|
||||||
assert(astop->operand->expression.type->type == TYPE_TYPE_POINTER);
|
assert(astop->operands[0]->expression.type->type == TYPE_TYPE_POINTER);
|
||||||
astop->type = astop->operand->expression.type->pointer.of;
|
astop->type = astop->operands[0]->expression.type->pointer.of;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (AST*) astop;
|
return (AST*) astop;
|
||||||
@@ -1236,21 +1236,6 @@ static void nct_parse_statement(Parser *P) {
|
|||||||
|
|
||||||
expect(P, TOKEN_SEMICOLON);
|
expect(P, TOKEN_SEMICOLON);
|
||||||
|
|
||||||
pushstat(P, ret);
|
|
||||||
return;
|
|
||||||
} else if(!strcmp(peek(P, 0).content, "@section")) {
|
|
||||||
ASTStmtExtSection *ret = alloc_node(P, sizeof(*ret));
|
|
||||||
ret->nodeKind = AST_STMT_EXT_SECTION;
|
|
||||||
ret->next = NULL;
|
|
||||||
|
|
||||||
get(P);
|
|
||||||
|
|
||||||
expect(P, TOKEN_PAREN_L);
|
|
||||||
ret->name = expect(P, TOKEN_STRING);
|
|
||||||
expect(P, TOKEN_PAREN_R);
|
|
||||||
|
|
||||||
expect(P, TOKEN_SEMICOLON);
|
|
||||||
|
|
||||||
pushstat(P, ret);
|
pushstat(P, ret);
|
||||||
return;
|
return;
|
||||||
} else if(!strcmp(peek(P, 0).content, "@instantiate")) {
|
} else if(!strcmp(peek(P, 0).content, "@instantiate")) {
|
||||||
@@ -1516,9 +1501,12 @@ Type *nct_parse_record_definition(Parser *P) {
|
|||||||
return tr;
|
return tr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skim_chunk(Parser *P, int isTopLevel) {
|
/*
|
||||||
/* Find all symbol names and struct types ahead of time. Searches for colons as those can only mean symbol declarations */
|
* Find all symbol names and struct types ahead of time.
|
||||||
|
* Searches for colons as they can only mean symbol declarations.
|
||||||
|
* This function abuses Nectar's grammar to work, so malformed source
|
||||||
|
* code can fuck it up. */
|
||||||
|
static void skim_tokens(Parser *P, int isTopLevel) {
|
||||||
P->skimMode++;
|
P->skimMode++;
|
||||||
{
|
{
|
||||||
intmax_t oldIdx = P->i;
|
intmax_t oldIdx = P->i;
|
||||||
@@ -1606,7 +1594,7 @@ static void skim_chunk(Parser *P, int isTopLevel) {
|
|||||||
free(path);
|
free(path);
|
||||||
|
|
||||||
Parser subp = {.tokens = nct_lex(f), .scope = scope_new(NULL), .externalify = 1};
|
Parser subp = {.tokens = nct_lex(f), .scope = scope_new(NULL), .externalify = 1};
|
||||||
skim_chunk(&subp, 1);
|
skim_tokens(&subp, 1);
|
||||||
|
|
||||||
// Copy all extern symbols from the scope into our TLC's externs array
|
// Copy all extern symbols from the scope into our TLC's externs array
|
||||||
for(size_t i = 0; i < subp.scope->count; i++) {
|
for(size_t i = 0; i < subp.scope->count; i++) {
|
||||||
@@ -1650,8 +1638,6 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t
|
|||||||
P->topLevel = &ret->chunk;
|
P->topLevel = &ret->chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
skim_chunk(P, isTopLevel);
|
|
||||||
|
|
||||||
/* Arguments */
|
/* Arguments */
|
||||||
if(ft && isTopLevel) {
|
if(ft && isTopLevel) {
|
||||||
P->topLevel->functionType = ft;
|
P->topLevel->functionType = ft;
|
||||||
@@ -1676,7 +1662,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t
|
|||||||
|
|
||||||
arch_add_hidden_variables(P->scope);
|
arch_add_hidden_variables(P->scope);
|
||||||
|
|
||||||
while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R) {
|
while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R && !(peek(P, 0).type == TOKEN_IDENTIFIER && !strcmp(peek(P, 0).content, "@section"))) {
|
||||||
nct_parse_statement(P);
|
nct_parse_statement(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1711,9 +1697,49 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t
|
|||||||
return &ret->chunk;
|
return &ret->chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTSection *nct_parse_sections(Parser *P) {
|
||||||
|
ASTSection *start = alloc_node(P, sizeof(*start));
|
||||||
|
start->nodeKind = AST_SECTION;
|
||||||
|
|
||||||
|
ASTSection *current = start;
|
||||||
|
while(1) {
|
||||||
|
current->tlc = nct_parse_chunk(P, 1, 0, P->scope, NULL);
|
||||||
|
|
||||||
|
if(peek(P, 0).type == TOKEN_EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(peek(P, 0).type == TOKEN_IDENTIFIER && !strcmp(peek(P, 0).content, "@section"))) {
|
||||||
|
stahp_token(&P->tokens[P->i - 1], "Expected @section.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTSection *next = alloc_node(P, sizeof(*next));
|
||||||
|
next->nodeKind = AST_SECTION;
|
||||||
|
|
||||||
|
get(P);
|
||||||
|
expect(P, TOKEN_PAREN_L);
|
||||||
|
|
||||||
|
next->name = expect(P, TOKEN_STRING);
|
||||||
|
|
||||||
|
expect(P, TOKEN_PAREN_R);
|
||||||
|
expect(P, TOKEN_SEMICOLON);
|
||||||
|
|
||||||
|
current->next = next;
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
AST *nct_parse(Token *tokens) {
|
AST *nct_parse(Token *tokens) {
|
||||||
|
Scope *scope = scope_new(NULL);
|
||||||
|
|
||||||
Parser P;
|
Parser P;
|
||||||
memset(&P, 0, sizeof(P));
|
memset(&P, 0, sizeof(P));
|
||||||
P.tokens = tokens;
|
P.tokens = tokens;
|
||||||
return (AST*) nct_parse_chunk(&P, 1, 0, scope_new(NULL), NULL);
|
P.scope = scope;
|
||||||
|
|
||||||
|
skim_tokens(&P, 1);
|
||||||
|
|
||||||
|
return (AST*) nct_parse_sections(&P);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,12 @@ Type *primitive_parse(const char *src) {
|
|||||||
|
|
||||||
if(!strcmp(src, "ugpr")) {
|
if(!strcmp(src, "ugpr")) {
|
||||||
return type_u(8 * arch_gpr_size());
|
return type_u(8 * arch_gpr_size());
|
||||||
|
} else if(!strcmp(src, "sgpr")) {
|
||||||
|
return type_s(8 * arch_gpr_size());
|
||||||
} else if(!strcmp(src, "umem")) {
|
} else if(!strcmp(src, "umem")) {
|
||||||
return type_u(arch_memory_width());
|
return type_u(arch_memory_width());
|
||||||
|
} else if(!strcmp(src, "smem")) {
|
||||||
|
return type_s(arch_memory_width());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypePrimitive *ret = calloc(1, sizeof(*ret));
|
TypePrimitive *ret = calloc(1, sizeof(*ret));
|
||||||
|
|||||||
@@ -133,12 +133,12 @@ static inline int is_xop(AST *e) {
|
|||||||
return XOP_NOT_MEM;
|
return XOP_NOT_MEM;
|
||||||
} else if(e->nodeKind == AST_EXPR_VAR) {
|
} else if(e->nodeKind == AST_EXPR_VAR) {
|
||||||
return e->exprVar.thing->kind == SCOPEITEM_VAR ? XOP_NOT_MEM : XOP_MEM;
|
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;
|
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) {
|
} 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;
|
return XOP_NOT_MEM;
|
||||||
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
|
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF) {
|
||||||
AST *c = e->exprUnOp.operand;
|
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) {
|
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;
|
c = c->exprCast.what;
|
||||||
|
|||||||
176
src/x86/cg.c
176
src/x86/cg.c
@@ -115,11 +115,11 @@ static const char *xj(BinaryOp op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AST *is_field_access(AST *e) {
|
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;
|
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) {
|
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;
|
e = e->exprCast.what;
|
||||||
@@ -136,6 +136,16 @@ static AST *is_field_access(AST *e) {
|
|||||||
return NULL;
|
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.
|
* Convert a XOP-able expression into an x86 operand.
|
||||||
* Result MUST be determinstic and always the same, for the same given expression.
|
* 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;
|
int pr = 0;
|
||||||
|
|
||||||
if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
|
if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_DEREF) {
|
||||||
AST *p = e->exprUnOp.operand;
|
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) {
|
if(p->nodeKind == AST_EXPR_CAST && p->exprCast.to->type == TYPE_TYPE_POINTER) {
|
||||||
p = p->exprCast.what;
|
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) {
|
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),
|
spec(sz),
|
||||||
|
segment_or_empty(seg),
|
||||||
xv_sz(p->exprBinOp.operands[0]->exprVar.thing, 0),
|
xv_sz(p->exprBinOp.operands[0]->exprVar.thing, 0),
|
||||||
xv_sz(p->exprBinOp.operands[1]->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) {
|
} 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),
|
spec(sz),
|
||||||
|
segment_or_empty(seg),
|
||||||
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
xv_sz(p->exprBinOp.operands[1]->exprVar.thing, 0));
|
xv_sz(p->exprBinOp.operands[1]->exprVar.thing, 0));
|
||||||
} else if(is_field_access(e)) {
|
} 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) {
|
if(e->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP) {
|
||||||
assert(e->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF);
|
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),
|
spec(sz),
|
||||||
|
segment_or_empty(seg),
|
||||||
e->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
e->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
e->exprBinOp.operands[1]->exprPrim.val);
|
e->exprBinOp.operands[1]->exprPrim.val);
|
||||||
} else {
|
} else {
|
||||||
@@ -182,19 +196,21 @@ static const char *xop_sz(AST *tlc, AST *e, int sz) {
|
|||||||
|
|
||||||
ScopeItem *vte = e->exprBinOp.operands[0]->exprVar.thing;
|
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),
|
spec(sz),
|
||||||
|
segment_or_empty(seg),
|
||||||
REG_CLASSES[vte->data.var.registerClass].rsN[vte->data.var.color],
|
REG_CLASSES[vte->data.var.registerClass].rsN[vte->data.var.color],
|
||||||
e->exprBinOp.operands[1]->exprPrim.val);
|
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) {
|
} 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),
|
spec(sz),
|
||||||
|
segment_or_empty(seg),
|
||||||
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
p->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
p->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val,
|
p->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val,
|
||||||
xv_sz(p->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing, 0));
|
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) {
|
} 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) {
|
} else if(p->nodeKind == AST_EXPR_STACK_POINTER) {
|
||||||
if(x86_ia16()) {
|
if(x86_ia16()) {
|
||||||
pr = snprintf(ret, XOPBUFSZ, "[bp + %li]", 0 - tlc->chunk.stackReservation);
|
pr = snprintf(ret, XOPBUFSZ, "[bp + %li]", 0 - tlc->chunk.stackReservation);
|
||||||
@@ -260,6 +276,27 @@ static int lr_empty(ScopeItem *a) {
|
|||||||
return !a->data.var.liveRangeStart;
|
return !a->data.var.liveRangeStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(AST *tlc, AST *statement, size_t resource) {
|
||||||
|
for(size_t vi = 0; vi < tlc->chunk.varCount; vi++) {
|
||||||
|
ScopeItem *si = tlc->chunk.vars[vi];
|
||||||
|
if((REG_CLASSES[si->data.var.registerClass].rs[si->data.var.color] & resource) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(ast_stmt_is_after(tlc, statement, si->data.var.liveRangeEnd) == 1 || statement == si->data.var.liveRangeEnd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(si->data.var.usedefFirst == NULL) {
|
||||||
|
// Even if the resource is in use, the variable itself isn't so we don't care
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!lr_empty(si) && (ast_stmt_is_after(tlc, statement, si->data.var.liveRangeStart) == 1
|
||||||
|
&& ast_stmt_is_after(tlc, si->data.var.liveRangeEnd, statement) == 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void cg_chunk(CGState *cg, AST *a) {
|
void cg_chunk(CGState *cg, AST *a) {
|
||||||
AST *s = a->chunk.statementFirst;
|
AST *s = a->chunk.statementFirst;
|
||||||
|
|
||||||
@@ -300,15 +337,6 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
printf("jmp .%s\n", s->stmtJump.label);
|
printf("jmp .%s\n", s->stmtJump.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_EXT_SECTION) {
|
|
||||||
|
|
||||||
Token t = s->stmtExtSection.name;
|
|
||||||
printf("section %.*s\n", (int) t.length, t.content);
|
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_EXT_ORG) {
|
|
||||||
|
|
||||||
printf("org %lu\n", s->stmtExtOrg.val);
|
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_EXT_ALIGN) {
|
} else if(s->nodeKind == AST_STMT_EXT_ALIGN) {
|
||||||
|
|
||||||
uint32_t val = s->stmtExtAlign.val;
|
uint32_t val = s->stmtExtAlign.val;
|
||||||
@@ -364,13 +392,13 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
|
|
||||||
ast_linearize(s->stmtDecl.expression->exprFunc.chunk);
|
ast_linearize(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
|
||||||
arch_normalize_pre(s->stmtDecl.expression->exprFunc.chunk);
|
|
||||||
|
|
||||||
arch_normalize(s->stmtDecl.expression->exprFunc.chunk);
|
arch_normalize(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
while(!cg_go(s->stmtDecl.expression->exprFunc.chunk)) {
|
while(!cg_attempt_sections(s->stmtDecl.expression->exprFunc.chunk)) {
|
||||||
arch_normalize(s->stmtDecl.expression->exprFunc.chunk);
|
arch_normalize(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cg_go_sections(s->stmtDecl.expression->exprFunc.chunk);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else abort();
|
} else abort();
|
||||||
@@ -390,12 +418,14 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
|
|
||||||
AST *e = s->stmtAssign.to;
|
AST *e = s->stmtAssign.to;
|
||||||
|
|
||||||
if(x86_ia16()) {
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) {
|
||||||
puts("push cx");
|
puts(x86_ia16() ? "push cx" : "push ecx");
|
||||||
puts("push dx");
|
}
|
||||||
} else {
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) {
|
||||||
puts("push ecx");
|
puts(x86_ia16() ? "push dx" : "push edx");
|
||||||
puts("push edx");
|
}
|
||||||
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) {
|
||||||
|
puts(x86_ia16() ? "push ax" : "push eax");
|
||||||
}
|
}
|
||||||
|
|
||||||
int argCount = e->exprCall.what->expression.type->pointer.of->function.argCount;
|
int argCount = e->exprCall.what->expression.type->pointer.of->function.argCount;
|
||||||
@@ -422,12 +452,14 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(x86_ia16()) {
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) {
|
||||||
puts("pop dx");
|
puts(x86_ia16() ? "pop ax" : "pop eax");
|
||||||
puts("pop cx");
|
}
|
||||||
} else {
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) {
|
||||||
puts("pop edx");
|
puts(x86_ia16() ? "pop dx" : "pop edx");
|
||||||
puts("pop ecx");
|
}
|
||||||
|
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) {
|
||||||
|
puts(x86_ia16() ? "pop cx" : "pop ecx");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
||||||
@@ -583,9 +615,9 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
if(a->chunk.stackReservation) {
|
if(a->chunk.stackReservation) {
|
||||||
for(int i = 0; i < MAX_REGS_PER_CLASS && cg->calleeSaved.reg[i]; i++) {
|
for(int i = 0; i < MAX_REGS_PER_CLASS && cg->calleeSaved.reg[i]; i++) {
|
||||||
if(x86_ia16()) {
|
if(x86_ia16()) {
|
||||||
printf("mov [bp + %li], %s\n", cg->calleeSaved.stackOffset[i] - a->chunk.stackReservation, cg->calleeSaved.reg[i]);
|
printf("mov %s, [bp + %li]\n", cg->calleeSaved.reg[i], cg->calleeSaved.stackOffset[i] - a->chunk.stackReservation);
|
||||||
} else {
|
} else {
|
||||||
printf("mov [esp + %li], %s\n", cg->calleeSaved.stackOffset[i], cg->calleeSaved.reg[i]);
|
printf("mov %s, [esp + %li]\n", cg->calleeSaved.reg[i], cg->calleeSaved.stackOffset[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,14 +639,6 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
|
|
||||||
printf("ret\n");
|
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 {
|
} else {
|
||||||
|
|
||||||
stahp_node(s, "Unknown statement %s caught by code generator.", AST_KIND_STR[s->nodeKind]);
|
stahp_node(s, "Unknown statement %s caught by code generator.", AST_KIND_STR[s->nodeKind]);
|
||||||
@@ -643,7 +667,7 @@ static bool var_collision(AST *tlc, ScopeItem *v1, ScopeItem *v2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
|
static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
|
||||||
bool ebxused = false, ediused = false, esiused = false;
|
bool ebxused = false, ediused = false, esiused = false, ebpused = false;
|
||||||
|
|
||||||
for(size_t v = 0; v < tlc->chunk.varCount; v++) {
|
for(size_t v = 0; v < tlc->chunk.varCount; v++) {
|
||||||
size_t resource = REG_CLASSES[tlc->chunk.vars[v]->data.var.registerClass].rs[tlc->chunk.vars[v]->data.var.color];
|
size_t resource = REG_CLASSES[tlc->chunk.vars[v]->data.var.registerClass].rs[tlc->chunk.vars[v]->data.var.color];
|
||||||
@@ -657,6 +681,9 @@ static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
|
|||||||
if(resource & HWR_ESI) {
|
if(resource & HWR_ESI) {
|
||||||
esiused = true;
|
esiused = true;
|
||||||
}
|
}
|
||||||
|
if(resource & HWR_EBP) {
|
||||||
|
ebpused = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nextUser = 0;
|
size_t nextUser = 0;
|
||||||
@@ -675,6 +702,11 @@ static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
|
|||||||
state->reg[nextUser] = x86_ia16() ? "di" : "edi";
|
state->reg[nextUser] = x86_ia16() ? "di" : "edi";
|
||||||
nextUser++;
|
nextUser++;
|
||||||
}
|
}
|
||||||
|
if(ebpused) {
|
||||||
|
state->stackOffset[nextUser] = nextUser * x86_max_gpr_size();
|
||||||
|
state->reg[nextUser] = x86_ia16() ? "bp" : "ebp";
|
||||||
|
nextUser++;
|
||||||
|
}
|
||||||
ast_grow_stack_frame(tlc, nextUser * x86_max_gpr_size());
|
ast_grow_stack_frame(tlc, nextUser * x86_max_gpr_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,7 +791,7 @@ nextColor:;
|
|||||||
return mustSpillRegisterClass;
|
return mustSpillRegisterClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cg_go(AST *a) {
|
int cg_tlc(AST *a) {
|
||||||
assert(a->nodeKind == AST_CHUNK);
|
assert(a->nodeKind == AST_CHUNK);
|
||||||
|
|
||||||
for(size_t e = 0; e < a->chunk.externCount; e++) {
|
for(size_t e = 0; e < a->chunk.externCount; e++) {
|
||||||
@@ -769,6 +801,23 @@ int cg_go(AST *a) {
|
|||||||
printf("extern %s\n", a->chunk.externs[e]->data.symbol.name);
|
printf("extern %s\n", a->chunk.externs[e]->data.symbol.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CalleeSavedState calleeSaved = {};
|
||||||
|
if(a->chunk.functionType) {
|
||||||
|
callee_saved(a, &calleeSaved);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGState cg;
|
||||||
|
memset(&cg, 0, sizeof(cg));
|
||||||
|
cg.tlc = a;
|
||||||
|
cg.isFunction = !!a->chunk.functionType;
|
||||||
|
cg.calleeSaved = calleeSaved;
|
||||||
|
|
||||||
|
cg_chunk(&cg, a);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cg_attempt(AST *a) {
|
||||||
ast_usedef_reset(a);
|
ast_usedef_reset(a);
|
||||||
|
|
||||||
size_t adjCount = 0;
|
size_t adjCount = 0;
|
||||||
@@ -858,19 +907,36 @@ cont:;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CalleeSavedState calleeSaved = {};
|
return 1;
|
||||||
if(a->chunk.functionType) {
|
|
||||||
callee_saved(a, &calleeSaved);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGState cg;
|
int cg_attempt_sections(AST *a) {
|
||||||
memset(&cg, 0, sizeof(cg));
|
assert(a->nodeKind == AST_SECTION);
|
||||||
cg.tlc = a;
|
|
||||||
cg.isFunction = !!a->chunk.functionType;
|
|
||||||
cg.calleeSaved = calleeSaved;
|
|
||||||
|
|
||||||
cg_chunk(&cg, a);
|
ASTSection *current = &a->section;
|
||||||
|
while(current) {
|
||||||
|
if(!cg_attempt(current->tlc)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cg_go_sections(AST *a) {
|
||||||
|
assert(a->nodeKind == AST_SECTION);
|
||||||
|
|
||||||
|
ASTSection *current = &a->section;
|
||||||
|
while(current) {
|
||||||
|
if(current->name.content) {
|
||||||
|
printf("section %s\n", current->name.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg_tlc(current->tlc);
|
||||||
|
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ static AST *varify(AST *tlc, AST *chunk, AST *stmtPrev, AST *stmt, AST *e) {
|
|||||||
assign->nodeKind = AST_STMT_ASSIGN;
|
assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
assign->what = (AST*) ev[0];
|
assign->what = (AST*) ev[0];
|
||||||
assign->to = e;
|
assign->to = e;
|
||||||
|
vte->data.var.declaration = (AST*) assign;
|
||||||
|
|
||||||
if(stmtPrev) {
|
if(stmtPrev) {
|
||||||
stmtPrev->statement.next = (AST*) assign;
|
stmtPrev->statement.next = (AST*) assign;
|
||||||
@@ -106,8 +107,6 @@ struct NormState {
|
|||||||
static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud) {
|
static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud) {
|
||||||
struct NormState *this = ud;
|
struct NormState *this = ud;
|
||||||
|
|
||||||
if(this->targetTLC != tlc) return;
|
|
||||||
|
|
||||||
AST *s = *nptr;
|
AST *s = *nptr;
|
||||||
|
|
||||||
if(s->nodeKind == AST_STMT_JUMP && s->stmtJump.condition) {
|
if(s->nodeKind == AST_STMT_JUMP && s->stmtJump.condition) {
|
||||||
@@ -297,6 +296,7 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
|
|||||||
assign2->nodeKind = AST_STMT_ASSIGN;
|
assign2->nodeKind = AST_STMT_ASSIGN;
|
||||||
assign2->what = (AST*) s->stmtAssign.what;
|
assign2->what = (AST*) s->stmtAssign.what;
|
||||||
assign2->to = (AST*) ev[0];
|
assign2->to = (AST*) ev[0];
|
||||||
|
tmp->data.var.declaration = (AST*) s;
|
||||||
|
|
||||||
s->stmtAssign.what = (AST*) ev[1];
|
s->stmtAssign.what = (AST*) ev[1];
|
||||||
|
|
||||||
@@ -305,18 +305,18 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
|
|||||||
|
|
||||||
this->effective = 1;
|
this->effective = 1;
|
||||||
|
|
||||||
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->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_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_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);
|
s->stmtAssign.to = varify(tlc, chu, stmtPrev, s, s->stmtAssign.to);
|
||||||
|
|
||||||
this->effective = 1;
|
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;
|
this->effective = 1;
|
||||||
|
|
||||||
@@ -369,10 +369,10 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
|
|||||||
|
|
||||||
this->effective = 1;
|
this->effective = 1;
|
||||||
} else if(is_xop(s->stmtAssign.to) == XOP_NOT_XOP) {
|
} 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) {
|
if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprUnOp.operator == BINOP_DEREF) {
|
||||||
s->stmtAssign.to->exprUnOp.operand = varify(tlc, chu, stmtPrev, s, s->stmtAssign.to->exprUnOp.operand);
|
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;
|
this->effective = 1;
|
||||||
} else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator == BINOP_MUL) {
|
} else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator == BINOP_MUL) {
|
||||||
@@ -475,8 +475,8 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
|
|||||||
static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||||
AST *n = *nptr;
|
AST *n = *nptr;
|
||||||
|
|
||||||
if(n == ud) {
|
if(n->nodeKind == AST_CHUNK) {
|
||||||
if(tlc->chunk.functionType) {
|
if(n->chunk.functionType) {
|
||||||
size_t argCount = n->chunk.functionType->function.argCount;
|
size_t argCount = n->chunk.functionType->function.argCount;
|
||||||
|
|
||||||
// First argCount vtes in list are the arguments
|
// First argCount vtes in list are the arguments
|
||||||
@@ -500,11 +500,11 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
|
|||||||
sum->operands[1] = (AST*) offset;
|
sum->operands[1] = (AST*) offset;
|
||||||
sum->operator = BINOP_ADD;
|
sum->operator = BINOP_ADD;
|
||||||
|
|
||||||
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
|
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
|
||||||
deref->nodeKind = AST_EXPR_UNARY_OP;
|
deref->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
deref->type = vte->type;
|
deref->type = vte->type;
|
||||||
deref->operand = (AST*) sum;
|
deref->operands[0] = (AST*) sum;
|
||||||
deref->operator = UNOP_DEREF;
|
deref->operator = BINOP_DEREF;
|
||||||
|
|
||||||
ASTExprVar *evar = calloc(1, sizeof(*evar));
|
ASTExprVar *evar = calloc(1, sizeof(*evar));
|
||||||
evar->nodeKind = AST_EXPR_VAR;
|
evar->nodeKind = AST_EXPR_VAR;
|
||||||
@@ -517,6 +517,7 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
|
|||||||
ass->what = (AST*) evar;
|
ass->what = (AST*) evar;
|
||||||
ass->to = ast_cast_expr((AST*) deref, vte->type); // Must cast because of "convention correctness"
|
ass->to = ast_cast_expr((AST*) deref, vte->type); // Must cast because of "convention correctness"
|
||||||
ass->next = n->chunk.statementFirst;
|
ass->next = n->chunk.statementFirst;
|
||||||
|
vte->data.var.declaration = (AST*) ass;
|
||||||
|
|
||||||
if(n->chunk.statementFirst) {
|
if(n->chunk.statementFirst) {
|
||||||
n->chunk.statementFirst = ass;
|
n->chunk.statementFirst = ass;
|
||||||
@@ -530,8 +531,6 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void decompose_symbol_record_field_access(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
static void decompose_symbol_record_field_access(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||||
if(tlc != (AST*) ud) return;
|
|
||||||
|
|
||||||
AST *n = *nptr;
|
AST *n = *nptr;
|
||||||
|
|
||||||
if(n->nodeKind == AST_EXPR_DOT) {
|
if(n->nodeKind == AST_EXPR_DOT) {
|
||||||
@@ -564,11 +563,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]));
|
AST *cast = ast_cast_expr((AST*) sum, type_pointer_wrap(n->exprDot.a->expression.type->record.fieldTypes[f]));
|
||||||
|
|
||||||
ASTExprUnaryOp *deref = calloc(1, sizeof(*deref));
|
ASTExprBinaryOp *deref = calloc(1, sizeof(*deref));
|
||||||
deref->nodeKind = AST_EXPR_UNARY_OP;
|
deref->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
deref->type = cast->expression.type->pointer.of;
|
deref->type = cast->expression.type->pointer.of;
|
||||||
deref->operator = UNOP_DEREF;
|
deref->operator = BINOP_DEREF;
|
||||||
deref->operand = cast;
|
deref->operands[0] = cast;
|
||||||
|
|
||||||
*nptr = (AST*) deref;
|
*nptr = (AST*) deref;
|
||||||
}
|
}
|
||||||
@@ -590,8 +589,6 @@ struct DenoopState {
|
|||||||
static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||||
struct DenoopState *state = ud;
|
struct DenoopState *state = ud;
|
||||||
|
|
||||||
if(state->targetTLC != tlc) return;
|
|
||||||
|
|
||||||
AST *n = *nptr;
|
AST *n = *nptr;
|
||||||
|
|
||||||
bool *success = &state->success;
|
bool *success = &state->success;
|
||||||
@@ -605,13 +602,13 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
|
|||||||
prim->val = ntc_get_int_default("null", 0);
|
prim->val = ntc_get_int_default("null", 0);
|
||||||
|
|
||||||
*nptr = (AST*) prim;
|
*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`
|
// Turn `&*a` into `a`
|
||||||
|
|
||||||
// Artificially change type of casted expression to keep types valid for subsequent passes
|
// 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;
|
*success = true;
|
||||||
} else if(is_double_field_access(n)) {
|
} else if(is_double_field_access(n)) {
|
||||||
@@ -752,10 +749,6 @@ void ast_denoop(AST *tlc, AST **node) {
|
|||||||
* TODO: convert records to proper form also.
|
* TODO: convert records to proper form also.
|
||||||
*/
|
*/
|
||||||
static void convention_correctness_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
static void convention_correctness_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||||
if(tlc != ud) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AST *n = *nptr;
|
AST *n = *nptr;
|
||||||
|
|
||||||
if(n->nodeKind == AST_EXPR_CALL) {
|
if(n->nodeKind == AST_EXPR_CALL) {
|
||||||
@@ -775,10 +768,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) {
|
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, convention_correctness_visitor, NULL);
|
||||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, pre_norm_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_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;) {
|
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) {
|
if(ast_is_scopeitem_referenced(tlc, tlc->chunk.vars[t]) || tlc->chunk.vars[t]->type->type == TYPE_TYPE_RECORD) {
|
||||||
|
|||||||
Reference in New Issue
Block a user