static int EndTry( void ) { int parent_scope; TREEPTR expr; TREEPTR func; TREEPTR tree; TYPEPTR typ; int expr_type; DropBreakLabel(); /* _leave jumps to this label */ parent_scope = BlockStack->parent_index; tree = LeafNode( OPR_TRY ); tree->op.st.try_index = BlockStack->try_index; tree->op.st.parent_scope = parent_scope; AddStmt( tree ); if( (CurToken == T__EXCEPT) || (CurToken == T___EXCEPT) ) { NextToken(); BlockStack->block_type = T__EXCEPT; BlockStack->break_label = NextLabel(); Jump( BlockStack->break_label ); DeadCode = 0; tree = LeafNode( OPR_EXCEPT ); tree->op.st.try_sym_handle = DummyTrySymbol(); tree->op.st.parent_scope = parent_scope; AddStmt( tree ); CompFlags.exception_filter_expr = 1; expr = RValue( BracketExpr() ); CompFlags.exception_filter_expr = 0; CompFlags.exception_handler = 1; typ = TypeOf( expr ); expr_type = DataTypeOf( typ ); if( expr_type != TYPE_VOID ) { if( expr_type > TYPE_ULONG ) { CErr1( ERR_EXPR_MUST_BE_INTEGRAL ); } } func = VarLeaf( SymGetPtr( SymExcept ), SymExcept ); func->op.opr = OPR_FUNCNAME; expr = ExprNode( NULL, OPR_PARM, expr ); expr->expr_type = typ; expr->op.result_type = typ; tree = ExprNode( func, OPR_CALL, expr ); tree->expr_type = GetType( TYPE_VOID ); AddStmt( tree ); return( 1 ); } else if( (CurToken == T__FINALLY) || (CurToken == T___FINALLY) ) { CompFlags.in_finally_block = 1; NextToken(); BlockStack->block_type = T__FINALLY; DeadCode = 0; tree = LeafNode( OPR_FINALLY ); tree->op.st.try_sym_handle = DummyTrySymbol(); tree->op.st.parent_scope = parent_scope; AddStmt( tree ); return( 1 ); } return( 0 ); }
static void AddCaseLabel( unsigned long value ) { CASEPTR ce, prev_ce, new_ce; unsigned long old_value, converted_value; TREEPTR tree; char buffer[12]; prev_ce = NULL; #if 0 leaf.u.ulong_konst = value; leaf.data_type = SwitchStack->case_type; SetLeafType( &leaf, 1 ); // converted_value = value & SwitchStack->case_mask; converted_value = leaf.u.ulong_konst; #else converted_value = value; #endif old_value = converted_value + 1; /* make old_value different */ for( ce = SwitchStack->case_list; ce; ce = ce->next_case ) { old_value = ce->value; if( old_value >= converted_value ) break; prev_ce = ce; } if( converted_value == old_value ) { /* duplicate case value found */ sprintf( buffer, SwitchStack->case_format, value ); CErr2p( ERR_DUPLICATE_CASE_VALUE, buffer ); } else { new_ce = (CASEPTR)CMemAlloc( sizeof( CASEDEFN ) ); new_ce->value = converted_value; if( prev_ce == NULL ) { new_ce->next_case = SwitchStack->case_list; SwitchStack->case_list = new_ce; } else { prev_ce->next_case = new_ce; new_ce->next_case = ce; } /* Check if the previous statement was a 'case'. If so, reuse the label, as generating * too many labels seriously slows down code generation. */ if( prev_ce && LastStmt->op.opr == OPR_STMT && LastStmt->right->op.opr == OPR_CASE ) { new_ce->label = SwitchStack->last_case_label; new_ce->gen_label = FALSE; } else { new_ce->label = NextLabel(); new_ce->gen_label = TRUE; } SwitchStack->number_of_cases++; if( converted_value < SwitchStack->low_value ) { SwitchStack->low_value = converted_value; } if( converted_value > SwitchStack->high_value ) { SwitchStack->high_value = converted_value; } SwitchStack->last_case_label = new_ce->label; tree = LeafNode( OPR_CASE ); tree->op.case_info = new_ce; AddStmt( tree ); } }
static void EndForStmt( void ) { DropContinueLabel(); if( BlockStack->inc_var ) { AddStmt( BlockStack->inc_var ); } Jump( BlockStack->top_label ); }
void VarDeclEquals( SYMPTR sym, SYM_HANDLE sym_handle ) { TYPEPTR typ; if( SymLevel == 0 || sym->stg_class == SC_STATIC ) { if( sym->flags & SYM_INITIALIZED ) { CErrSymName( ERR_VAR_ALREADY_INITIALIZED, sym, sym_handle ); } sym->flags |= SYM_INITIALIZED; CompFlags.initializing_data = 1; StaticInit( sym, sym_handle ); CompFlags.initializing_data = 0; } else { SymReplace( sym, sym_handle ); /* 31-aug-88 */ SrcLoc = TokenLoc; typ = sym->sym_type; SKIP_TYPEDEFS( typ ); /* 07-jun-89 check for { before checking for array,struct or union */ if( CurToken != T_LEFT_BRACE && typ->decl_type != TYPE_ARRAY ) { /* 27-jun-89 */ AddStmt( AsgnOp( VarLeaf( sym, sym_handle ), T_ASSIGN_LAST, CommaExpr() ) ); } else if( typ->decl_type == TYPE_ARRAY ) { if( CurToken == T_LEFT_BRACE && CompFlags.auto_agg_inits ) { InitArrayVar( sym, sym_handle, typ ); } else { AggregateVarDeclEquals( sym, sym_handle ); } } else if( typ->decl_type == TYPE_STRUCT || typ->decl_type == TYPE_UNION ) { if( CurToken == T_LEFT_BRACE && CompFlags.auto_agg_inits && SimpleStruct( typ ) ) { NextToken(); //T_LEFT_BRACE InitStructVar( 0, sym, sym_handle, typ ); NextToken(); //T_RIGHT_BRACE } else { AggregateVarDeclEquals( sym, sym_handle ); } } else { NextToken(); AddStmt( AsgnOp( VarLeaf( sym, sym_handle ), T_ASSIGN_LAST, CommaExpr() ) ); MustRecog( T_RIGHT_BRACE ); } } }
local void AssignAggregate( TREEPTR lvalue, TREEPTR rvalue, TYPEPTR typ ) { TREEPTR tree; tree = ExprNode( lvalue, OPR_EQUALS, rvalue ); tree->right->op.opr = OPR_PUSHSYM; tree->expr_type = typ; tree->op.result_type = typ; AddStmt( tree ); }
static void DropLabel( LABEL_INDEX label ) { TREEPTR tree; CompFlags.label_dropped = 1; DeadCode = 0; tree = LeafNode( OPR_LABEL ); tree->op.label_index = label; AddStmt( tree ); }
static void Jump( LABEL_INDEX label ) { TREEPTR tree; if( ! DeadCode ) { tree = LeafNode( OPR_JUMP ); tree->op.label_index = label; AddStmt( tree ); DeadCode = 1; } }
static void UnWindTry( int try_scope ) { #ifdef __SEH__ TREEPTR tree; tree = LeafNode( OPR_UNWIND ); tree->op.st.try_index = try_scope; AddStmt( tree ); #else try_scope = try_scope; #endif }
static void ChkStmtExpr( void ) { TREEPTR tree; tree = Expr(); if( CompFlags.meaningless_stmt == 1 ) { ChkUseful(); } AddStmt( tree ); if( CompFlags.pending_dead_code ) { DeadCode = 1; } }
static void SwitchStmt( void ) { SWITCHPTR sw; TREEPTR tree; TYPEPTR typ; int switch_type; StartNewBlock(); NextToken(); sw = (SWITCHPTR)CMemAlloc( sizeof( SWITCHDEFN ) ); sw->prev_switch = SwitchStack; sw->low_value = ~0l; sw->high_value = 0; sw->case_format = "%ld"; /* assume signed cases */ SwitchStack = sw; switch_type = TYPE_INT; /* assume int */ tree = RValue( BracketExpr() ); typ = TypeOf( tree ); if( typ->decl_type == TYPE_ENUM ) typ = typ->object; if( typ->decl_type == TYPE_UFIELD ) { if( typ->u.f.field_width == (TARGET_INT * 8) ) { sw->case_format = "%lu"; switch_type = TYPE_UINT; } } switch( typ->decl_type ) { case TYPE_USHORT: case TYPE_UINT: sw->case_format = "%lu"; switch_type = TYPE_UINT; case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: case TYPE_INT: case TYPE_FIELD: case TYPE_UFIELD: break; case TYPE_ULONG: sw->case_format = "%lu"; switch_type = TYPE_ULONG; break; case TYPE_LONG: switch_type = TYPE_LONG; break; default: CErr1( ERR_INVALID_TYPE_FOR_SWITCH ); } tree = ExprNode( 0, OPR_SWITCH, tree ); tree->op.switch_info = sw; AddStmt( tree ); }
static void JumpCond( TREEPTR expr, LABEL_INDEX label, opr_code jump_opcode, opr_code jump_opposite ) { TREEPTR tree; tree = BoolExpr( expr ); if( tree->op.opr == OPR_NOT ) { tree->op.opr = jump_opposite; } else { tree = ExprNode( 0, jump_opcode, tree ); } tree->op.label_index = label; AddStmt( tree ); }
static void ForStmt( void ) { bool parsed_semi_colon = FALSE; NextToken(); MustRecog( T_LEFT_PAREN ); if( CompFlags.c99_extensions ) { PushBlock(); // 'for' opens new scope } if( CurToken != T_SEMI_COLON ) { if( CompFlags.c99_extensions ) { TREEPTR tree; tree = LeafNode( OPR_NEWBLOCK ); AddStmt( tree ); BlockStack->gen_endblock = TRUE; if( !LoopDecl( &BlockStack->sym_list ) ) { ChkStmtExpr(); // no declarator, try init_expr } else { parsed_semi_colon = TRUE; // LoopDecl ate it up } tree->op.sym_handle = BlockStack->sym_list; } else { ChkStmtExpr(); // init_expr } } if( !parsed_semi_colon ) { MustRecog( T_SEMI_COLON ); } NewLoop(); BlockStack->block_type = T_FOR; if( CurToken != T_SEMI_COLON ) { BlockStack->break_label = NextLabel(); if( !JumpFalse( Expr(), BlockStack->break_label ) ) { BlockStack->break_label = 0; /* 09-sep-92 */ } } MustRecog( T_SEMI_COLON ); BlockStack->inc_var = NULL; if( CurToken != T_RIGHT_PAREN ) { BlockStack->inc_var = Expr(); // save this if( CompFlags.meaningless_stmt == 1 ) { ChkUseful(); } } MustRecog( T_RIGHT_PAREN ); }
static void PopBlock( void ) { BLOCKPTR block; TREEPTR tree; if( BlockStack->gen_endblock ) { tree = LeafNode( OPR_ENDBLOCK ); tree->op.sym_handle = BlockStack->sym_list; AddStmt( tree ); } if( BlockStack->sym_list != 0 ) { AddSymList( BlockStack->sym_list ); } block = BlockStack; LoopStack = block->prev_loop; BlockStack = block->prev_block; CMemFree( block ); }
static void FixupC99MainReturn( SYM_HANDLE func_result, struct return_info *info ) { TREEPTR tree; TYPEPTR main_type; /* In C99 mode, return statement need not be explicit for main()... */ main_type = CurFunc->sym_type->object; SKIP_TYPEDEFS( main_type ); /* ... as long as return type is compatible with int */ if( main_type->decl_type == TYPE_INT ) { tree = IntLeaf( 0 ); /* zero is the default return value */ tree = ExprNode( 0, OPR_RETURN, tree ); tree->expr_type = main_type; tree->op.sym_handle = func_result; AddStmt( tree ); info->with_expr = TRUE; } }
static void TryStmt( void ) { TREEPTR tree; MarkTryVolatile( CurFunc->u.func.parms ); MarkTryVolatile( CurFunc->u.func.locals ); CurFuncNode->op.func.flags |= FUNC_USES_SEH; CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE; CurToken = T__TRY; StartNewBlock(); NextToken(); BlockStack->parent_index = TryScope; ++TryCount; BlockStack->try_index = TryCount; TryScope = TryCount; tree = LeafNode( OPR_TRY ); tree->op.st.try_index = 0; tree->op.st.parent_scope = TryCount; AddStmt( tree ); }
void AsmSysMakeInlineAsmFunc( bool too_many_bytes ) /*************************************************/ { int code_length; SYM_HANDLE sym_handle; TREEPTR tree; bool uses_auto; char name[8]; /* unused parameters */ (void)too_many_bytes; code_length = AsmCodeAddress; if( code_length != 0 ) { sprintf( name, "F.%d", AsmFuncNum ); ++AsmFuncNum; CreateAux( name ); CurrInfo = (aux_info *)CMemAlloc( sizeof( aux_info ) ); *CurrInfo = WatcallInfo; CurrInfo->use = 1; CurrInfo->save = AsmRegsSaved; // indicate no registers saved uses_auto = InsertFixups( AsmCodeBuffer, code_length, &CurrInfo->code ); if( uses_auto ) { /* We want to force the calling routine to set up a [E]BP frame for the use of this pragma. This is done by saying the pragma modifies the [E]SP register. A kludge, but it works. */ HW_CTurnOff( CurrInfo->save, HW_SP ); } CurrEntry->info = CurrInfo; CurrEntry->next = AuxList; AuxList = CurrEntry; CurrEntry = NULL; sym_handle = MakeFunction( name, FuncNode( GetType( TYPE_VOID ), FLAG_NONE, NULL ) ); tree = LeafNode( OPR_FUNCNAME ); tree->op.u2.sym_handle = sym_handle; tree = ExprNode( tree, OPR_CALL, NULL ); tree->u.expr_type = GetType( TYPE_VOID ); AddStmt( tree ); } }
static void ReturnStmt( SYM_HANDLE func_result, struct return_info *info ) { TREEPTR tree; BLOCKPTR block; enum return_with with; NextToken(); if( CurToken != T_SEMI_COLON ) { TYPEPTR func_type; func_type = CurFunc->sym_type->object; SKIP_TYPEDEFS( func_type ); tree = RValue( Expr() ); ChkRetType( tree ); tree = BoolConv( func_type, tree ); tree = FixupAss( tree, func_type ); tree = ExprNode( 0, OPR_RETURN, tree ); tree->expr_type = func_type; tree->op.sym_handle = func_result; AddStmt( tree ); with = RETURN_WITH_EXPR; info->with_expr = TRUE; } else { with = RETURN_WITH_NO_EXPR; } if( info->with == RETURN_WITH_NONE ) { info->with = with; } if( info->with != with ) { CErr1( ERR_INCONSISTENT_USE_OF_RETURN ); } block = BlockStack; /* 16-apr-94 */ while( block != NULL ) { if( (block->block_type == T__TRY) || (block->block_type == T___TRY) ) break; block = block->prev_block; } if( block != NULL ) { UnWindTry( -1 ); } }
static void LeftBrace( void ) { TREEPTR tree; /* <storage> <type> function( <parms> ) { <- this is SymLevel == 1 (weird code is for SymLevel > 1 ) */ // DeclList might generate some quads to do some initializers // if that happens, we want them output after the OPR_NEWBLOCK node StartNewBlock(); NextToken(); ++SymLevel; tree = LeafNode( OPR_NEWBLOCK ); AddStmt( tree ); BlockStack->sym_list = 0; BlockStack->gen_endblock = TRUE; DeclList( &BlockStack->sym_list ); tree->op.sym_handle = BlockStack->sym_list; }
local void InitStructVar( unsigned base, SYMPTR sym, SYM_HANDLE sym_handle, TYPEPTR typ) { TYPEPTR typ2; TREEPTR opnd; TREEPTR value; FIELDPTR field; TOKEN token; for( field = typ->u.tag->u.field_list; field; ) { token = CurToken; if( token == T_LEFT_BRACE ) NextToken(); //allow {}, and extra {expr}..} typ2 = field->field_type; SKIP_TYPEDEFS( typ2 ); if( CurToken == T_RIGHT_BRACE ) { value = IntLeaf( 0 ); } else { value = CommaExpr(); } opnd = VarLeaf( sym, sym_handle ); if( typ2->decl_type == TYPE_UNION ) { FIELDPTR ufield; ufield = typ2->u.tag->u.field_list; typ2 = ufield->field_type; SKIP_TYPEDEFS( typ2 ); } opnd = ExprNode( opnd, OPR_DOT, UIntLeaf( base + field->offset ) ); opnd->expr_type = typ2; opnd->op.result_type = typ2; AddStmt( AsgnOp( opnd, T_ASSIGN_LAST, value ) ); if( token == T_LEFT_BRACE ) MustRecog( T_RIGHT_BRACE ); if( CurToken == T_EOF ) break; field = field->next_field; if( field == NULL ) break; if( CurToken != T_RIGHT_BRACE ) { MustRecog( T_COMMA ); } } }
void GenFunctionNode( SYM_HANDLE sym_handle ) { TREEPTR tree; SYMPTR sym; tree = LeafNode( OPR_FUNCTION ); sym = SymGetPtr( sym_handle ); tree->op.func.sym_handle = sym_handle; tree->op.func.flags = FUNC_NONE; if( ( Toggles & TOGGLE_INLINE ) | ( sym->attrib & FLAG_INLINE ) ) { if( !sym->naked ) { if( strcmp( sym->name, "main" ) != 0 ) { tree->op.func.flags |= FUNC_OK_TO_INLINE; } } } tree->op.flags = OpFlags( sym->attrib ); tree->expr_type = sym->sym_type->object; // function return type AddStmt( tree ); // Evil, evil globals! But we need this for later lookups in cgen.c sym->u.func.start_of_func = LastStmt; CurFuncNode = tree; NodeCount = 0; }
local void InitArrayVar( SYMPTR sym, SYM_HANDLE sym_handle, TYPEPTR typ ) { unsigned i; unsigned n; TYPEPTR typ2; SYM_HANDLE sym2_handle; SYM_ENTRY sym2; TREEPTR opnd; TREEPTR value; TOKEN token; typ2 = typ->object; SKIP_TYPEDEFS( typ2 ); switch( typ2->decl_type ) { case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: case TYPE_USHORT: case TYPE_INT: case TYPE_UINT: case TYPE_LONG: case TYPE_ULONG: case TYPE_LONG64: case TYPE_ULONG64: case TYPE_FLOAT: case TYPE_DOUBLE: case TYPE_POINTER: case TYPE_LONG_DOUBLE: case TYPE_FIMAGINARY: case TYPE_DIMAGINARY: case TYPE_LDIMAGINARY: case TYPE_BOOL: NextToken(); // skip over T_LEFT_BRACE if( CharArray( typ->object ) ) { sym2_handle = MakeNewSym( &sym2, 'X', typ, SC_STATIC ); sym2.flags |= SYM_INITIALIZED; if( sym2.u.var.segment == 0 ) { /* 01-dec-91 */ SetFarHuge( &sym2, 0 ); SetSegment( &sym2 ); SetSegAlign( &sym2 ); /* 02-feb-92 */ } SymReplace( &sym2, sym2_handle ); GenStaticDataQuad( sym2_handle ); InitCharArray( typ ); AssignAggregate( VarLeaf( sym, sym_handle ), VarLeaf( &sym2, sym2_handle ), typ ); } else if( WCharArray( typ->object ) ) { sym2_handle = MakeNewSym( &sym2, 'X', typ, SC_STATIC ); sym2.flags |= SYM_INITIALIZED; if( sym2.u.var.segment == 0 ) { /* 01-dec-91 */ SetFarHuge( &sym2, 0 ); SetSegment( &sym2 ); SetSegAlign( &sym2 ); /* 02-feb-92 */ } SymReplace( &sym2, sym2_handle ); GenStaticDataQuad( sym2_handle ); InitWCharArray( typ ); AssignAggregate( VarLeaf( sym, sym_handle ), VarLeaf( &sym2, sym2_handle ), typ ); } else { n = typ->u.array->dimension; i = 0; for( ;; ) { // accept some C++ { {1},.. } token = CurToken; if( token == T_LEFT_BRACE ) NextToken(); opnd = VarLeaf( sym, sym_handle ); value = CommaExpr(); opnd = ExprNode( opnd, OPR_INDEX, IntLeaf( i ) ); opnd->expr_type = typ2; opnd->op.result_type = typ2; AddStmt( AsgnOp( opnd, T_ASSIGN_LAST, value ) ); if( token == T_LEFT_BRACE ) MustRecog( T_RIGHT_BRACE ); ++i; if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE )break; MustRecog( T_COMMA ); if( CurToken == T_RIGHT_BRACE )break; if( i == n ) { CErr1( ERR_TOO_MANY_INITS ); } } if( typ->u.array->unspecified_dim ) { typ->u.array->dimension = i; } else { while( i < n ) { value = IntLeaf( 0 ); opnd = VarLeaf( sym, sym_handle ); opnd = ExprNode( opnd, OPR_INDEX, IntLeaf( i ) ); opnd->expr_type = typ2; opnd->op.result_type = typ2; AddStmt( AsgnOp( opnd, T_ASSIGN_LAST, value ) ); ++i; } } } MustRecog( T_RIGHT_BRACE ); break; case TYPE_FCOMPLEX: case TYPE_DCOMPLEX: case TYPE_LDCOMPLEX: case TYPE_STRUCT: case TYPE_UNION: if( SimpleStruct( typ2 ) ) { unsigned base; unsigned size; NextToken(); // skip over T_LEFT_BRACE n = typ->u.array->dimension; i = 0; base = 0; size = SizeOfArg( typ2 ); for( ;; ) { token = CurToken; if( token == T_LEFT_BRACE ) { NextToken(); } InitStructVar( base, sym, sym_handle, typ2 ); if( token == T_LEFT_BRACE ) { MustRecog( T_RIGHT_BRACE ); } ++i; if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE ) break; MustRecog( T_COMMA ); if( CurToken == T_RIGHT_BRACE ) break; if( i == n ) { CErr1( ERR_TOO_MANY_INITS ); } base += size; } if( typ->u.array->unspecified_dim ) { typ->u.array->dimension = i; } else { while( i < n ) { // mop up base += size; InitStructVar( base, sym, sym_handle, typ2 ); ++i; } } NextToken(); // skip over T_RIGHT_BRACE break; } default: AggregateVarDeclEquals( sym, sym_handle ); break; } }
static void EndOfStmt( void ) { do { switch( BlockStack->block_type ) { case T_LEFT_BRACE: EndBlock(); break; case T_IF: if( CurToken == T_ELSE ) { ElseStmt(); return; } DropBreakLabel(); break; case T_ELSE: DropBreakLabel(); break; case T_WHILE: DropContinueLabel(); Jump( BlockStack->top_label ); --LoopDepth; DropBreakLabel(); break; case T_FOR: EndForStmt(); --LoopDepth; DropBreakLabel(); if( CompFlags.c99_extensions ) { EndBlock(); /* Terminate the scope introduced by 'for' */ PopBlock(); } break; case T_DO: DropContinueLabel(); MustRecog( T_WHILE ); SrcLoc = TokenLoc; JumpTrue( BracketExpr(), BlockStack->top_label ); MustRecog( T_SEMI_COLON ); SrcLoc = TokenLoc; --LoopDepth; DropBreakLabel(); break; case T_SWITCH: EndSwitch(); DropBreakLabel(); break; #ifdef __SEH__ case T__TRY: case T___TRY: if( EndTry() ) return; break; case T__EXCEPT: case T___EXCEPT: DropBreakLabel(); TryScope = BlockStack->parent_index; CompFlags.exception_handler = 0; break; case T__FINALLY: case T___FINALLY: AddStmt( LeafNode( OPR_END_FINALLY ) ); CompFlags.in_finally_block = 0; TryScope = BlockStack->parent_index; break; #endif } PopBlock(); if( BlockStack == NULL ) break; } while( BlockStack->block_type != T_LEFT_BRACE ); }
static void AddParms( void ) { PARMPTR parm; PARMPTR prev_parm; SYM_HANDLE sym_handle; SYM_HANDLE prev_sym_handle; SYM_HANDLE new_sym_handle; TYPEPTR typ = NULL; int parm_count; id_hash_idx h; parm_list *parmlist; SYM_ENTRY new_sym; CurFunc->u.func.locals = SYM_NULL; CurFunc->u.func.parms = SYM_NULL; parmlist = NULL; prev_sym_handle = SYM_NULL; parm_count = 0; prev_parm = NULL; for( parm = ParmList; parm != NULL; parm = parm->next_parm ) { new_sym_handle = SYM_NULL; parm->sym.flags |= SYM_DEFINED | SYM_ASSIGNED; parm->sym.attribs.is_parm = true; h = parm->sym.info.hash; if( parm->sym.name[0] == '\0' ) { /* no name ==> ... */ parm->sym.sym_type = GetType( TYPE_DOT_DOT_DOT ); parm->sym.attribs.stg_class = SC_AUTO; } else if( parm->sym.sym_type == NULL ) { parm->sym.sym_type = TypeDefault(); parm->sym.attribs.stg_class = SC_AUTO; } else { /* go through ParmList again, looking for FLOAT parms change the name to ".P" and duplicate the symbol with type float and generate an assignment statement. */ typ = parm->sym.sym_type; SKIP_TYPEDEFS( typ ); switch( typ->decl_type ) { case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: if( CompFlags.strict_ANSI ) { parm->sym.sym_type = GetType( TYPE_INT ); } break; case TYPE_USHORT: if( CompFlags.strict_ANSI ) { #if TARGET_SHORT == TARGET_INT parm->sym.sym_type = GetType( TYPE_UINT ); #else parm->sym.sym_type = GetType( TYPE_INT ); #endif } break; case TYPE_FLOAT: memcpy( &new_sym, &parm->sym, sizeof( SYM_ENTRY ) ); new_sym.handle = CurFunc->u.func.locals; new_sym_handle = SymAdd( h, &new_sym ); CurFunc->u.func.locals = new_sym_handle; SymReplace( &new_sym, new_sym_handle ); parm->sym.name = ".P"; parm->sym.flags |= SYM_REFERENCED; parm->sym.sym_type = GetType( TYPE_DOUBLE ); break; default: break; } } sym_handle = SymAdd( h, &parm->sym ); if( new_sym_handle != SYM_NULL ) { TREEPTR tree; tree = ExprNode( VarLeaf( &new_sym, new_sym_handle ), OPR_EQUALS, RValue( VarLeaf( &parm->sym, sym_handle ) ) ); tree->op.u2.result_type = typ; tree->u.expr_type = typ; AddStmt( tree ); } if( prev_parm == NULL ) { CurFunc->u.func.parms = sym_handle; } else { prev_parm->sym.handle = sym_handle; SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } prev_parm = parm; prev_sym_handle = sym_handle; ++parm_count; parmlist = NewParm( parm->sym.sym_type, parmlist ); } if( prev_parm != NULL ) { prev_parm->sym.handle = SYM_NULL; SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } typ = CurFunc->sym_type; // TODO not following my scheme CurFunc->sym_type = FuncNode( typ->object, FLAG_NONE, MakeParmList( parmlist, ParmsToBeReversed( CurFunc->mods, NULL ) ) ); if( PrevProtoType != NULL ) { ChkProtoType(); } }
void Statement( void ) { LABEL_INDEX end_of_func_label; SYM_HANDLE func_result; TREEPTR tree; bool return_at_outer_level; bool skip_to_next_token; bool declaration_allowed; struct return_info return_info; SYM_ENTRY sym; #ifndef NDEBUG if( DebugFlag >= 1 ) { printf( "***** line %u, func=%s\n", TokenLoc.line, CurFunc->name ); PrintStats(); } #endif ++FuncCount; return_info.with = RETURN_WITH_NONE; /* indicate no return statements */ return_info.with_expr = FALSE; CompFlags.label_dropped = 0; CompFlags.addr_of_auto_taken = 0; /* 23-oct-91 */ end_of_func_label = 0; return_at_outer_level = FALSE; /* 28-feb-92 */ declaration_allowed = FALSE; DeadCode = 0; LoopDepth = 0; LabelIndex = 0; BlockStack = NULL; LoopStack = NULL; SwitchStack = NULL; #ifdef __SEH__ TryCount = -1; TryScope = -1; #endif StartNewBlock(); NextToken(); // skip over { ++SymLevel; tree = LeafNode( OPR_LABELCOUNT ); AddStmt( tree ); if( GrabLabels() == 0 ) { /* 29-nov-94 */ GetLocalVarDecls(); } func_result = MakeNewSym( &sym, 'R', CurFunc->sym_type->object, SC_AUTO ); sym.flags |= SYM_FUNC_RETURN_VAR; /* 25-oct-91 */ SymReplace( &sym, func_result ); for( ;; ) { CompFlags.pending_dead_code = 0; if( GrabLabels() == 0 && declaration_allowed && IsDeclarator( CurToken ) ) { GetLocalVarDecls(); } if( CompFlags.c99_extensions ) { declaration_allowed = TRUE; } skip_to_next_token = FALSE; switch( CurToken ) { case T_IF: StartNewBlock(); NextToken(); BlockStack->break_label = NextLabel(); JumpFalse( BracketExpr(), BlockStack->break_label ); /* 23-dec-88, only issue msg if ';' is on same line as 'if' */ if( CurToken == T_SEMI_COLON && SrcLoc.line == TokenLoc.line && SrcLoc.fno == TokenLoc.fno ) { SetErrLoc( &TokenLoc ); NextToken(); /* look ahead for else keyword */ if( CurToken != T_ELSE ) { /* 02-apr-91 */ ChkUseful(); /* 08-dec-88 */ } InitErrLoc(); break; } declaration_allowed = FALSE; continue; case T_WHILE: NewLoop(); NextToken(); BlockStack->break_label = NextLabel(); if( !JumpFalse( BracketExpr(), BlockStack->break_label ) ) { BlockStack->break_label = 0; /* 09-sep-92 */ } if( CurToken == T_SEMI_COLON ) { /* 08-dec-88 */ if( ! CompFlags.useful_side_effect ) { CWarn1( WARN_MEANINGLESS, ERR_MEANINGLESS ); } } declaration_allowed = FALSE; continue; case T_DO: NewLoop(); NextToken(); if( CurToken == T_RIGHT_BRACE ) { CErr1( ERR_STMT_REQUIRED_AFTER_DO ); break; } declaration_allowed = FALSE; continue; case T_FOR: ForStmt(); declaration_allowed = FALSE; continue; case T_SWITCH: SwitchStmt(); DeadCode = 1; declaration_allowed = FALSE; continue; case T_CASE: DeadCode = 0; CaseStmt(); declaration_allowed = FALSE; continue; case T_DEFAULT: DefaultStmt(); declaration_allowed = FALSE; continue; case T_BREAK: BreakStmt(); DeadCode = 1; if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; case T_CONTINUE: ContinueStmt(); DeadCode = 1; if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; #ifdef __SEH__ case T__LEAVE: case T___LEAVE: LeaveStmt(); DeadCode = 1; if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; #endif case T_RETURN: ReturnStmt( func_result, &return_info ); if( BlockStack->prev_block == NULL ) { /* 28-feb-92 */ return_at_outer_level = TRUE; } MustRecog( T_SEMI_COLON ); if( SymLevel != 1 || CurToken != T_RIGHT_BRACE || BlockStack->block_type != T_LEFT_BRACE ) { if( end_of_func_label == 0 ) { end_of_func_label = NextLabel(); } Jump( end_of_func_label ); } if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; case T_GOTO: GotoStmt(); if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; case T_SEMI_COLON: NextToken(); if( BlockStack->block_type != T_LEFT_BRACE ) { if( CurToken == T_ELSE ) { declaration_allowed = FALSE; } break; } continue; case T_LEFT_BRACE: LeftBrace(); continue; case T_RIGHT_BRACE: if( BlockStack->block_type != T_LEFT_BRACE ) { CErr1( ERR_MISPLACED_RIGHT_BRACE ); } if( BlockStack->prev_block == NULL ) { skip_to_next_token = TRUE; } else { NextToken(); } break; case T_EXTERN: case T_STATIC: case T_AUTO: case T_REGISTER: case T_VOID: case T_CHAR: case T_SHORT: case T_INT: case T_LONG: case T_FLOAT: case T_DOUBLE: case T_SIGNED: case T_UNSIGNED: if( CompFlags.c99_extensions ) CErr1( ERR_UNEXPECTED_DECLARATION ); else CErr1( ERR_MISSING_RIGHT_BRACE ); break; case T_EOF: CErr1( ERR_MISSING_RIGHT_BRACE ); break; #ifdef __SEH__ case T__TRY: case T___TRY: TryStmt(); continue; #endif case T___ASM: AsmStmt(); continue; default: if( DeadCode == 1 ) { DeadMsg(); } StmtExpr(); if( BlockStack->block_type != T_LEFT_BRACE ) break; continue; } EndOfStmt(); if( BlockStack == NULL ) break; if( skip_to_next_token ) { NextToken(); } } /* C99 has special semantics for return value of main() */ if( CompFlags.c99_extensions && !strcmp( CurFunc->name, "main" ) ) { if( !return_at_outer_level ) { FixupC99MainReturn( func_result, &return_info ); return_at_outer_level = TRUE; } } if( !return_info.with_expr ) { /* no return values present */ if( !DeadCode && !CurFunc->naked ) { ChkRetValue(); } } else if( ! return_at_outer_level ) { /* 28-feb-92 */ if( ! DeadCode && !CurFunc->naked ) { CWarn( WARN_MISSING_RETURN_VALUE, ERR_MISSING_RETURN_VALUE, CurFunc->name ); } } if( end_of_func_label != 0 ) { DropLabel( end_of_func_label ); } DeadCode = 0; tree->op.label_count = LabelIndex; tree = LeafNode( OPR_FUNCEND ); if( !return_info.with_expr ) { tree->expr_type = NULL; tree->op.sym_handle = 0; } else { tree->op.sym_handle = func_result; SetFuncReturnNode( tree ); } AddStmt( tree ); AddSymList( CurFunc->u.func.locals ); SrcLoc = TokenLoc; FreeLabels(); if( skip_to_next_token ) { NextToken(); } if( CompFlags.generate_prototypes ) { if( DefFile == NULL ) { OpenDefFile(); } if( DefFile != NULL && CurFunc->stg_class == SC_NULL ) { /* function exported */ DumpFuncDefn(); } } if( Toggles & TOGGLE_INLINE ) { if( Inline_Threshold < NodeCount ) { CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE; } } if( VarParm( CurFunc ) ) { CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE; } NodeCount = 0; if( CompFlags.addr_of_auto_taken ) { /* 23-oct-91 */ CurFunc->flags &= ~ SYM_OK_TO_RECURSE; } }