/** * 翻译break 语句 * A break statement terminates the execution of associated * switch or loop. * * break is translated into: * goto switch or loop's nextBB * nextBB: * ... */ static void TranslateBreakStatement (AstStatement stmt) { AstBreakStatement brkStmt = AsBreak(stmt); if (brkStmt->target->kind == NK_SwitchStatement) { /* switch 在跳转 */ GenerateJump (AsSwitch(brkStmt->target)->nextBB); } else { /* loop 跳转 */ GenerateJump (AsLoop(brkStmt->target)->nextBB); } StartBBlock (CreateBBlock ()); }
/* 翻译switch 语句 * 创建case default 基本块 */ static void TranslateSwitchStatement (AstStatement stmt) { AstSwitchStatement swtchStmt = AsSwitch(stmt); AstCaseStatement p, q; SwitchBucket bucket, b; SwitchBucket *bucketArray; int i, val; Symbol sym; /* 翻译switch 的表达式 */ sym = TranslateExpression (swtchStmt->expr); bucket = b = NULL; p = swtchStmt->cases; /* 创建基本块, 并给case 语句排序 */ while ( p ) { q = p; p = p->nextCase; /* 给case 创建基本块 */ q->respBB = CreateBBlock (); /* case 的表达式 */ val = q->expr->val.i[0]; if (bucket && (bucket->ncase + 1) * 2 > (val - bucket->minVal)) { bucket->ncase++; bucket->maxVal = val; *bucket->tail = q; bucket->tail = &(q->nextCase); swtchStmt->nbucket -= MergeSwitchBucket (&bucket); } else { CALLOC(b); b->cases = q; b->ncase = 1; /* 初始化最小大值 */ b->minVal = b->maxVal = val; b->tail = &(q->nextCase); b->prev = bucket; bucket = b; swtchStmt->nbucket++; } } swtchStmt->buckets = bucket; bucketArray = HeapAllocate (CurrentHeap, swtchStmt->nbucket * sizeof (SwitchBucket)); for (i = swtchStmt->nbucket - 1; i >= 0; i--) { bucketArray[i] = bucket; *bucket->tail = NULL; bucket = bucket->prev; } /* default 语句 */ swtchStmt->defBB = CreateBBlock(); if (swtchStmt->defStmt) { swtchStmt->defStmt->respBB = swtchStmt->defBB; swtchStmt->nextBB = CreateBBlock(); } else { swtchStmt->nextBB = swtchStmt->defBB; } TranslateSwitchBuckets (bucketArray, 0, swtchStmt->nbucket - 1, sym, NULL, swtchStmt->defBB); TranslateStatement (swtchStmt->stmt); StartBBlock (swtchStmt->nextBB); }
static void DumpStatement(AstStatement stmt, int pos) { switch (stmt->kind) { case NK_ExpressionStatement: DumpExpression(AsExpr(stmt)->expr, pos); break; case NK_LabelStatement: fprintf(ASTFile, "(label %s:\n", AsLabel(stmt)->id); LeftAlign(ASTFile, pos + 2); DumpStatement(AsLabel(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-label)"); break; case NK_CaseStatement: fprintf(ASTFile, "(case "); DumpExpression(AsCase(stmt)->expr, pos + 7); LeftAlign(ASTFile, pos + 2); DumpStatement(AsCase(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-case)"); break; case NK_DefaultStatement: fprintf(ASTFile, "(default "); DumpStatement(AsDef(stmt)->stmt, pos + 10); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-default)"); break; case NK_IfStatement: fprintf(ASTFile, "(if "); DumpExpression(AsIf(stmt)->expr, pos + 5); LeftAlign(ASTFile, pos + 2); fprintf(ASTFile, "(then "); LeftAlign(ASTFile, pos + 4); DumpStatement(AsIf(stmt)->thenStmt, pos + 4); LeftAlign(ASTFile, pos + 2); fprintf(ASTFile, "end-then)"); if (AsIf(stmt)->elseStmt != NULL) { LeftAlign(ASTFile, pos + 2); fprintf(ASTFile, "(else "); LeftAlign(ASTFile, pos + 4); DumpStatement(AsIf(stmt)->elseStmt, pos + 4); LeftAlign(ASTFile, pos + 2); fprintf(ASTFile, "end-else)"); } LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-if)"); break; case NK_SwitchStatement: fprintf(ASTFile, "(switch "); DumpExpression(AsSwitch(stmt)->expr, pos + 9); LeftAlign(ASTFile, pos + 2); DumpStatement(AsSwitch(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-switch)"); break; case NK_WhileStatement: fprintf(ASTFile, "(while "); DumpExpression(AsLoop(stmt)->expr, pos + 8); LeftAlign(ASTFile, pos + 2); DumpStatement(AsLoop(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-while)"); break; case NK_DoStatement: fprintf(ASTFile, "(do "); DumpExpression(AsLoop(stmt)->expr, pos + 5); LeftAlign(ASTFile, pos + 2); DumpStatement(AsLoop(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, ")"); break; case NK_ForStatement: fprintf(ASTFile, "(for "); DumpExpression(AsFor(stmt)->initExpr, pos + 6); LeftAlign(ASTFile, pos + 6); DumpExpression(AsFor(stmt)->expr, pos + 6); LeftAlign(ASTFile, pos + 6); DumpExpression(AsFor(stmt)->incrExpr, pos + 6); LeftAlign(ASTFile, pos + 2); DumpStatement(AsFor(stmt)->stmt, pos + 2); LeftAlign(ASTFile, pos); fprintf(ASTFile, "end-for)"); break; case NK_GotoStatement: fprintf(ASTFile, "(goto %s)", AsGoto(stmt)->id); break; case NK_ContinueStatement: fprintf(ASTFile, "(continue)"); break; case NK_BreakStatement: fprintf(ASTFile, "(break)"); break; case NK_ReturnStatement: fprintf(ASTFile, "(ret "); DumpExpression(AsRet(stmt)->expr, pos + 5); fprintf(ASTFile, ")"); break; case NK_CompoundStatement: { AstNode p = ((AstCompoundStatement)stmt)->stmts; fprintf(ASTFile, "{"); while (p != NULL) { LeftAlign(ASTFile, pos + 2); DumpStatement((AstStatement)p, pos + 2); if (p->next != NULL) fprintf(ASTFile, "\n"); p = p->next; } LeftAlign(ASTFile, pos); fprintf(ASTFile, "}"); break; } default: assert(0); } }