|
|
|
|
@@ -34,6 +34,9 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
|
|
|
|
|
} else if(n->nodeKind == AST_STMT_IF) {
|
|
|
|
|
generic_visitor(&n->stmtIf.expression, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
|
|
|
|
generic_visitor(&n->stmtIf.then, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
|
|
|
|
if(n->stmtIf.elss) {
|
|
|
|
|
generic_visitor(&n->stmtIf.elss, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
|
|
|
|
}
|
|
|
|
|
} else if(n->nodeKind == AST_STMT_LOOP) {
|
|
|
|
|
generic_visitor(&n->stmtLoop.body, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
|
|
|
|
|
} else if(n->nodeKind == AST_STMT_BREAK) {
|
|
|
|
|
@@ -143,6 +146,13 @@ int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2) {
|
|
|
|
|
if(i == 1 || (i == 0 && s1 != NULL)) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(s->stmtIf.elss) {
|
|
|
|
|
i = ast_stmt_is_after(s->stmtIf.elss, s1, s2);
|
|
|
|
|
if(i == 1 || (i == 0 && s1 != NULL)) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = s->statement.next;
|
|
|
|
|
@@ -656,7 +666,14 @@ static char *ast_dumps(AST *tlc, AST *s) {
|
|
|
|
|
} else if(s->nodeKind == AST_STMT_IF) {
|
|
|
|
|
char *cond = ast_dumpe(tlc, s->stmtIf.expression);
|
|
|
|
|
char *inner = ast_dumpc(tlc, s->stmtIf.then);
|
|
|
|
|
char *c = malp("if(%s) {\n%s}", cond, inner);
|
|
|
|
|
char *elss = s->stmtIf.elss ? ast_dumpc(tlc, s->stmtIf.elss) : NULL;
|
|
|
|
|
char *c;
|
|
|
|
|
if(elss) {
|
|
|
|
|
c = malp("if(%s) {\n%s} else {\n%s}", cond, inner, elss);
|
|
|
|
|
free(elss);
|
|
|
|
|
} else {
|
|
|
|
|
c = malp("if(%s) {\n%s}", cond, inner);
|
|
|
|
|
}
|
|
|
|
|
free(cond);
|
|
|
|
|
free(inner);
|
|
|
|
|
return c;
|
|
|
|
|
@@ -1098,6 +1115,21 @@ void ast_segmented_dereference(AST *tlc) {
|
|
|
|
|
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, ast_segmented_dereference_visitor, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ast_patch_in_chunk(AST *chunkOuter, AST *stmtBefore, AST *chunkInner, AST *stmtAfter) {
|
|
|
|
|
if(chunkInner->chunk.statementFirst) {
|
|
|
|
|
stmtBefore->statement.next = chunkInner->chunk.statementFirst;
|
|
|
|
|
|
|
|
|
|
for(AST *z = chunkInner->chunk.statementFirst; z; z = z->statement.next) {
|
|
|
|
|
if(!z->statement.next) {
|
|
|
|
|
z->statement.next = stmtAfter;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
stmtBefore->statement.next = stmtAfter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define LOOPSTACKSIZE 64
|
|
|
|
|
struct LinearizeState {
|
|
|
|
|
size_t currentDepth;
|
|
|
|
|
@@ -1113,38 +1145,69 @@ static void ast_linearize_visitor_pre(AST **aptr, AST *stmt, AST *stmtPrev, AST
|
|
|
|
|
AST *a = *aptr;
|
|
|
|
|
|
|
|
|
|
if(a->nodeKind == AST_STMT_IF) {
|
|
|
|
|
ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond));
|
|
|
|
|
notcond->nodeKind = AST_EXPR_UNARY_OP;
|
|
|
|
|
notcond->operator = UNOP_NOT;
|
|
|
|
|
notcond->operand = a->stmtIf.expression;
|
|
|
|
|
notcond->type = a->stmtIf.expression->expression.type;
|
|
|
|
|
if(a->stmtIf.elss == NULL) {
|
|
|
|
|
ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond));
|
|
|
|
|
notcond->nodeKind = AST_EXPR_UNARY_OP;
|
|
|
|
|
notcond->operator = UNOP_NOT;
|
|
|
|
|
notcond->operand = a->stmtIf.expression;
|
|
|
|
|
notcond->type = a->stmtIf.expression->expression.type;
|
|
|
|
|
|
|
|
|
|
ASTStmtJump *jump = calloc(1, sizeof(ASTStmtJump));
|
|
|
|
|
jump->nodeKind = AST_STMT_JUMP;
|
|
|
|
|
jump->condition = (AST*) notcond;
|
|
|
|
|
jump->label = malp("$Lin%lu", nextLabelIdx++);
|
|
|
|
|
ASTStmtJump *jump = calloc(1, sizeof(ASTStmtJump));
|
|
|
|
|
jump->nodeKind = AST_STMT_JUMP;
|
|
|
|
|
jump->condition = (AST*) notcond;
|
|
|
|
|
jump->label = malp("$Lin%lu", nextLabelIdx++);
|
|
|
|
|
|
|
|
|
|
ASTStmtLabel *label = calloc(1, sizeof(ASTStmtLabel));
|
|
|
|
|
label->nodeKind = AST_STMT_LABEL;
|
|
|
|
|
label->name = strdup(jump->label);
|
|
|
|
|
ASTStmtLabel *label = calloc(1, sizeof(ASTStmtLabel));
|
|
|
|
|
label->nodeKind = AST_STMT_LABEL;
|
|
|
|
|
label->name = strdup(jump->label);
|
|
|
|
|
|
|
|
|
|
if(stmtPrev) {
|
|
|
|
|
stmtPrev->statement.next = (AST*) jump;
|
|
|
|
|
} else {
|
|
|
|
|
chunk->chunk.statementFirst = (AST*) jump;
|
|
|
|
|
}
|
|
|
|
|
if(a->stmtIf.then->chunk.statementFirst) {
|
|
|
|
|
jump->next = a->stmtIf.then->chunk.statementFirst;
|
|
|
|
|
for(AST *z = a->stmtIf.then->chunk.statementFirst; z; z = z->statement.next) {
|
|
|
|
|
if(!z->statement.next) {
|
|
|
|
|
z->statement.next = (AST*) label;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(stmtPrev) {
|
|
|
|
|
stmtPrev->statement.next = (AST*) jump;
|
|
|
|
|
} else {
|
|
|
|
|
chunk->chunk.statementFirst = (AST*) jump;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_patch_in_chunk(chunk, (AST*) jump, a->stmtIf.then, (AST*) label);
|
|
|
|
|
|
|
|
|
|
label->next = a->statement.next;
|
|
|
|
|
} else {
|
|
|
|
|
jump->next = (AST*) label;
|
|
|
|
|
ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond));
|
|
|
|
|
notcond->nodeKind = AST_EXPR_UNARY_OP;
|
|
|
|
|
notcond->operator = UNOP_NOT;
|
|
|
|
|
notcond->operand = a->stmtIf.expression;
|
|
|
|
|
notcond->type = a->stmtIf.expression->expression.type;
|
|
|
|
|
|
|
|
|
|
ASTStmtJump *jump2Else = calloc(1, sizeof(ASTStmtJump));
|
|
|
|
|
jump2Else->nodeKind = AST_STMT_JUMP;
|
|
|
|
|
jump2Else->condition = (AST*) notcond;
|
|
|
|
|
jump2Else->label = malp("$Lin%lu", nextLabelIdx++);
|
|
|
|
|
|
|
|
|
|
ASTStmtJump *jump2End = calloc(1, sizeof(ASTStmtJump));
|
|
|
|
|
jump2End->nodeKind = AST_STMT_JUMP;
|
|
|
|
|
jump2End->label = malp("$Lin%lu", nextLabelIdx++);
|
|
|
|
|
|
|
|
|
|
ASTStmtLabel *labelElse = calloc(1, sizeof(ASTStmtLabel));
|
|
|
|
|
labelElse->nodeKind = AST_STMT_LABEL;
|
|
|
|
|
labelElse->name = strdup(jump2Else->label);
|
|
|
|
|
|
|
|
|
|
ASTStmtLabel *labelEnd = calloc(1, sizeof(ASTStmtLabel));
|
|
|
|
|
labelEnd->nodeKind = AST_STMT_LABEL;
|
|
|
|
|
labelEnd->name = strdup(jump2End->label);
|
|
|
|
|
|
|
|
|
|
if(stmtPrev) {
|
|
|
|
|
stmtPrev->statement.next = (AST*) jump2Else;
|
|
|
|
|
} else {
|
|
|
|
|
chunk->chunk.statementFirst = (AST*) jump2Else;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_patch_in_chunk(chunk, (AST*) jump2Else, a->stmtIf.then, (AST*) jump2End);
|
|
|
|
|
|
|
|
|
|
jump2End->next = (AST*) labelElse;
|
|
|
|
|
|
|
|
|
|
ast_patch_in_chunk(chunk, (AST*) labelElse, a->stmtIf.elss, (AST*) labelEnd);
|
|
|
|
|
|
|
|
|
|
labelEnd->next = a->statement.next;
|
|
|
|
|
}
|
|
|
|
|
label->next = a->statement.next;
|
|
|
|
|
} else if(a->nodeKind == AST_STMT_LOOP) {
|
|
|
|
|
size_t startIdx = nextLabelIdx++;
|
|
|
|
|
size_t endIdx = nextLabelIdx++;
|
|
|
|
|
@@ -1167,17 +1230,9 @@ static void ast_linearize_visitor_pre(AST **aptr, AST *stmt, AST *stmtPrev, AST
|
|
|
|
|
} else {
|
|
|
|
|
chunk->chunk.statementFirst = (AST*) startLabel;
|
|
|
|
|
}
|
|
|
|
|
if(a->stmtLoop.body->chunk.statementFirst) {
|
|
|
|
|
startLabel->next = a->stmtLoop.body->chunk.statementFirst;
|
|
|
|
|
for(AST *z = a->stmtLoop.body->chunk.statementFirst; z; z = z->statement.next) {
|
|
|
|
|
if(!z->statement.next) {
|
|
|
|
|
z->statement.next = (AST*) jump;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
startLabel->next = (AST*) jump;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_patch_in_chunk(chunk, (AST*) startLabel, a->stmtLoop.body, (AST*) jump);
|
|
|
|
|
|
|
|
|
|
jump->next = (AST*) endLabel;
|
|
|
|
|
endLabel->next = a->statement.next;
|
|
|
|
|
|
|
|
|
|
|