static void DoStatement (void) /* Handle the 'do' statement */ { /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned ContinueLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); /* Add the loop to the loop stack */ AddLoop (BreakLabel, ContinueLabel); /* Define the loop label */ g_defcodelabel (LoopLabel); /* Parse the loop body */ Statement (0); /* Output the label for a continue */ g_defcodelabel (ContinueLabel); /* Parse the end condition */ Consume (TOK_WHILE, "`while' expected"); TestInParens (LoopLabel, 1); ConsumeSemi (); /* Define the break label */ g_defcodelabel (BreakLabel); /* Remove the loop from the loop stack */ DelLoop (); }
static void WhileStatement (void) /* Handle the 'while' statement */ { int PendingToken; CodeMark CondCodeStart; /* Start of condition evaluation code */ CodeMark CondCodeEnd; /* End of condition evaluation code */ CodeMark Here; /* "Here" location of code */ /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned CondLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); /* Add the loop to the loop stack. In case of a while loop, the condition ** label is used for continue statements. */ AddLoop (BreakLabel, CondLabel); /* We will move the code that evaluates the while condition to the end of ** the loop, so generate a jump here. */ g_jump (CondLabel); /* Remember the current position */ GetCodePos (&CondCodeStart); /* Emit the code position label */ g_defcodelabel (CondLabel); /* Test the loop condition */ TestInParens (LoopLabel, 1); /* Remember the end of the condition evaluation code */ GetCodePos (&CondCodeEnd); /* Define the head label */ g_defcodelabel (LoopLabel); /* Loop body */ Statement (&PendingToken); /* Move the test code here */ GetCodePos (&Here); MoveCode (&CondCodeStart, &CondCodeEnd, &Here); /* Exit label */ g_defcodelabel (BreakLabel); /* Eat remaining tokens that were delayed because of line info ** correctness */ SkipPending (PendingToken); /* Remove the loop from the loop stack */ DelLoop (); }
static int IfStatement (void) /* Handle an 'if' statement */ { unsigned Label1; unsigned TestResult; int GotBreak; /* Skip the if */ NextToken (); /* Generate a jump label and parse the condition */ Label1 = GetLocalLabel (); TestResult = TestInParens (Label1, 0); /* Parse the if body */ GotBreak = Statement (0); /* Else clause present? */ if (CurTok.Tok != TOK_ELSE) { g_defcodelabel (Label1); /* Since there's no else clause, we're not sure, if the a break ** statement is really executed. */ return 0; } else { /* Generate a jump around the else branch */ unsigned Label2 = GetLocalLabel (); g_jump (Label2); /* Skip the else */ NextToken (); /* If the if expression was always true, the code in the else branch ** is never executed. Output a warning if this is the case. */ if (TestResult == TESTEXPR_TRUE) { Warning ("Unreachable code"); } /* Define the target for the first test */ g_defcodelabel (Label1); /* Total break only if both branches had a break. */ GotBreak &= Statement (0); /* Generate the label for the else clause */ g_defcodelabel (Label2); /* Done */ return GotBreak; } }
void DefaultLabel (void) /* Handle a default label */ { /* Default case */ NextToken (); /* Now check if we're inside a switch statement */ if (Switch != 0) { /* Check if we do already have a default branch */ if (Switch->DefaultLabel == 0) { /* Generate and emit the default label */ Switch->DefaultLabel = GetLocalLabel (); g_defcodelabel (Switch->DefaultLabel); } else { /* We had the default label already */ Error ("Multiple default labels in one switch"); } } else { /* case keyword outside a switch statement */ Error ("`default' label not within a switch statement"); } /* Skip the colon */ ConsumeColon (); }
CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E) /* If the code entry E does already have a label, return it. Otherwise * create a new label, attach it to E and return it. */ { CodeLabel* L; if (CE_HasLabel (E)) { /* Get the label from this entry */ L = CE_GetLabel (E, 0); } else { /* Get a new name */ const char* Name = LocalLabelName (GetLocalLabel ()); /* Generate the hash over the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; /* Create a new label */ L = CS_NewCodeLabel (S, Name, Hash); /* Attach this label to the code entry */ CE_AttachLabel (E, L); } /* Return the label */ return L; }
SymEntry* AddLabelSym (const char* Name, unsigned Flags) /* Add a goto label to the label table */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); if (Entry) { if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { /* Trying to define the label more than once */ Error ("Label `%s' is defined more than once", Name); } Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_LABEL | Flags); /* Set a new label number */ Entry->V.Label = GetLocalLabel (); /* Generate the assembler name of the label */ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label)); /* Add the entry to the label table */ AddSymEntry (LabelTab, Entry); } /* Return the entry */ return Entry; }
static void WhileStatement (void) /* Handle the 'while' statement */ { int PendingToken; /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); /* Add the loop to the loop stack. In case of a while loop, the loop head * label is used for continue statements. */ AddLoop (BreakLabel, LoopLabel); /* Define the head label */ g_defcodelabel (LoopLabel); /* Test the loop condition */ TestInParens (BreakLabel, 0); /* Loop body */ Statement (&PendingToken); /* Jump back to loop top */ g_jump (LoopLabel); /* Exit label */ g_defcodelabel (BreakLabel); /* Eat remaining tokens that were delayed because of line info * correctness */ SkipPending (PendingToken); /* Remove the loop from the loop stack */ DelLoop (); }
static Literal* NewLiteral (const void* Buf, unsigned Len) /* Create a new literal and return it */ { /* Allocate memory */ Literal* L = xmalloc (sizeof (*L)); /* Initialize the fields */ L->Label = GetLocalLabel (); L->RefCount = 0; L->Output = 0; SB_Init (&L->Data); SB_AppendBuf (&L->Data, Buf, Len); /* Return the new literal */ return L; }
static Function* NewFunction (struct SymEntry* Sym) /* Create a new function activation structure and return it */ { /* Allocate a new structure */ Function* F = (Function*) xmalloc (sizeof (Function)); /* Initialize the fields */ F->FuncEntry = Sym; F->ReturnType = GetFuncReturn (Sym->Type); F->Desc = GetFuncDesc (Sym->Type); F->Reserved = 0; F->RetLab = GetLocalLabel (); F->TopLevelSP = 0; F->RegOffs = RegisterSpace; F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE; /* Return the new structure */ return F; }
void SwitchStatement (void) /* Handle a switch statement for chars with a cmp cascade for the selector */ { ExprDesc SwitchExpr; /* Switch statement expression */ CodeMark CaseCodeStart; /* Start of code marker */ CodeMark SwitchCodeStart;/* Start of switch code */ CodeMark SwitchCodeEnd; /* End of switch code */ unsigned ExitLabel; /* Exit label */ unsigned SwitchCodeLabel;/* Label for the switch code */ int HaveBreak = 0; /* True if the last statement had a break */ int RCurlyBrace; /* True if last token is right curly brace */ SwitchCtrl* OldSwitch; /* Pointer to old switch control data */ SwitchCtrl SwitchData; /* New switch data */ /* Eat the "switch" token */ NextToken (); /* Read the switch expression and load it into the primary. It must have * integer type. */ ConsumeLParen (); Expression0 (&SwitchExpr); if (!IsClassInt (SwitchExpr.Type)) { Error ("Switch quantity is not an integer"); /* To avoid any compiler errors, make the expression a valid int */ ED_MakeConstAbsInt (&SwitchExpr, 1); } ConsumeRParen (); /* Add a jump to the switch code. This jump is usually unnecessary, * because the switch code will moved up just behind the switch * expression. However, in rare cases, there's a label at the end of * the switch expression. This label will not get moved, so the code * jumps around the switch code, and after moving the switch code, * things look really weird. If we add a jump here, we will never have * a label attached to the current code position, and the jump itself * will get removed by the optimizer if it is unnecessary. */ SwitchCodeLabel = GetLocalLabel (); g_jump (SwitchCodeLabel); /* Remember the current code position. We will move the switch code * to this position later. */ GetCodePos (&CaseCodeStart); /* Setup the control structure, save the old and activate the new one */ SwitchData.Nodes = NewCollection (); SwitchData.ExprType = UnqualifiedType (SwitchExpr.Type[0].C); SwitchData.Depth = SizeOf (SwitchExpr.Type); SwitchData.DefaultLabel = 0; OldSwitch = Switch; Switch = &SwitchData; /* Get the exit label for the switch statement */ ExitLabel = GetLocalLabel (); /* Create a loop so we may use break. */ AddLoop (ExitLabel, 0); /* Make sure a curly brace follows */ if (CurTok.Tok != TOK_LCURLY) { Error ("`{' expected"); } /* Parse the following statement, which will actually be a compound * statement because of the curly brace at the current input position */ HaveBreak = Statement (&RCurlyBrace); /* Check if we had any labels */ if (CollCount (SwitchData.Nodes) == 0 && SwitchData.DefaultLabel == 0) { Warning ("No case labels"); } /* If the last statement did not have a break, we may have an open * label (maybe from an if or similar). Emitting code and then moving * this code to the top will also move the label to the top which is * wrong. So if the last statement did not have a break (which would * carry the label), add a jump to the exit. If it is useless, the * optimizer will remove it later. */ if (!HaveBreak) { g_jump (ExitLabel); } /* Remember the current position */ GetCodePos (&SwitchCodeStart); /* Output the switch code label */ g_defcodelabel (SwitchCodeLabel); /* Generate code */ if (SwitchData.DefaultLabel == 0) { /* No default label, use switch exit */ SwitchData.DefaultLabel = ExitLabel; } g_switch (SwitchData.Nodes, SwitchData.DefaultLabel, SwitchData.Depth); /* Move the code to the front */ GetCodePos (&SwitchCodeEnd); MoveCode (&SwitchCodeStart, &SwitchCodeEnd, &CaseCodeStart); /* Define the exit label */ g_defcodelabel (ExitLabel); /* Exit the loop */ DelLoop (); /* Switch back to the enclosing switch statement if any */ Switch = OldSwitch; /* Free the case value tree */ FreeCaseNodeColl (SwitchData.Nodes); /* If the case statement was (correctly) terminated by a closing curly * brace, skip it now. */ if (RCurlyBrace) { NextToken (); } }
static void ForStatement (void) /* Handle a 'for' statement */ { ExprDesc lval1; ExprDesc lval3; int HaveIncExpr; CodeMark IncExprStart; CodeMark IncExprEnd; int PendingToken; /* Get several local labels needed later */ unsigned TestLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned IncLabel = GetLocalLabel (); unsigned BodyLabel = GetLocalLabel (); /* Skip the FOR token */ NextToken (); /* Add the loop to the loop stack. A continue jumps to the start of the ** the increment condition. */ AddLoop (BreakLabel, IncLabel); /* Skip the opening paren */ ConsumeLParen (); /* Parse the initializer expression */ if (CurTok.Tok != TOK_SEMI) { Expression0 (&lval1); } ConsumeSemi (); /* Label for the test expressions */ g_defcodelabel (TestLabel); /* Parse the test expression */ if (CurTok.Tok != TOK_SEMI) { Test (BodyLabel, 1); g_jump (BreakLabel); } else { g_jump (BodyLabel); } ConsumeSemi (); /* Remember the start of the increment expression */ GetCodePos (&IncExprStart); /* Label for the increment expression */ g_defcodelabel (IncLabel); /* Parse the increment expression */ HaveIncExpr = (CurTok.Tok != TOK_RPAREN); if (HaveIncExpr) { Expression0 (&lval3); } /* Jump to the test */ g_jump (TestLabel); /* Remember the end of the increment expression */ GetCodePos (&IncExprEnd); /* Skip the closing paren */ ConsumeRParen (); /* Loop body */ g_defcodelabel (BodyLabel); Statement (&PendingToken); /* If we had an increment expression, move the code to the bottom of ** the loop. In this case we don't need to jump there at the end of ** the loop body. */ if (HaveIncExpr) { CodeMark Here; GetCodePos (&Here); MoveCode (&IncExprStart, &IncExprEnd, &Here); } else { /* Jump back to the increment expression */ g_jump (IncLabel); } /* Skip a pending token if we have one */ SkipPending (PendingToken); /* Declare the break label */ g_defcodelabel (BreakLabel); /* Remove the loop from the loop stack */ DelLoop (); }
void InitLiteralPool (void) /* Initialize the literal pool */ { /* Get the pool label */ LiteralPoolLabel = GetLocalLabel (); }