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 ); }
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 ); }
void AddStmt( TREEPTR stmt ) { WalkExprTree( stmt, ChkStringLeaf, NoOp, NoOp, DoConstFold ); stmt = ExprNode( 0, OPR_STMT, stmt ); stmt->op.src_loc = SrcLoc; stmt->op.unroll_count = UnrollCount; if( FirstStmt == NULL ) FirstStmt = stmt; if( LastStmt != NULL ) { LastStmt->left = stmt; } LastStmt = stmt; }
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 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 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 ); } }
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 ); } }
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 ); } } }
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 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(); } }