unsigned SizeOf (const Type* T) /* Compute size of object represented by type array. */ { switch (UnqualifiedType (T->C)) { case T_VOID: return 0; /* Assume voids have size zero */ case T_SCHAR: case T_UCHAR: return SIZEOF_CHAR; case T_SHORT: case T_USHORT: return SIZEOF_SHORT; case T_INT: case T_UINT: return SIZEOF_INT; case T_PTR: case T_FUNC: /* Maybe pointer to function */ return SIZEOF_PTR; case T_LONG: case T_ULONG: return SIZEOF_LONG; case T_LONGLONG: case T_ULONGLONG: return SIZEOF_LONGLONG; case T_ENUM: return SIZEOF_INT; case T_FLOAT: return SIZEOF_FLOAT; case T_DOUBLE: return SIZEOF_DOUBLE; case T_STRUCT: case T_UNION: return ((SymEntry*) T->A.P)->V.S.Size; case T_ARRAY: if (T->A.L == UNSPECIFIED) { /* Array with unspecified size */ return 0; } else { return T->A.L * SizeOf (T + 1); } default: Internal ("Unknown type in SizeOf: %04lX", T->C); return 0; } }
Type* GetFuncReturn (Type* T) /* Return a pointer to the return type of a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Return a pointer to the return type */ return T + 1; }
void SetFuncDesc (Type* T, FuncDesc* F) /* Set the FuncDesc pointer in a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Set the function descriptor */ T->A.P = F; }
FuncDesc* GetFuncDesc (const Type* T) /* Get the FuncDesc pointer from a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Get the function descriptor from the type attributes */ return T->A.P; }
unsigned TypeOf (const Type* T) /* Get the code generator base type of the object */ { switch (UnqualifiedType (T->C)) { case T_SCHAR: return CF_CHAR; case T_UCHAR: return CF_CHAR | CF_UNSIGNED; case T_SHORT: case T_INT: case T_ENUM: return CF_INT; case T_USHORT: case T_UINT: case T_PTR: case T_ARRAY: return CF_INT | CF_UNSIGNED; case T_LONG: return CF_LONG; case T_ULONG: return CF_LONG | CF_UNSIGNED; case T_FLOAT: case T_DOUBLE: /* These two are identical in the backend */ return CF_FLOAT; case T_FUNC: return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC; case T_STRUCT: case T_UNION: /* Address of ... */ return CF_INT | CF_UNSIGNED; default: Error ("Illegal type %04lX", T->C); return CF_INT; } }
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 (); } }