static void ChkParms( void ) { PARMPTR parm; PARMPTR prev_parm; SYM_HANDLE sym_handle; SYM_HANDLE prev_sym_handle; TYPEPTR typ; CurFunc->u.func.locals = SYM_NULL; CurFunc->u.func.parms = SYM_NULL; typ = *(CurFunc->sym_type->u.fn.parms); SKIP_TYPEDEFS( typ ); if( typ->decl_type != TYPE_VOID ) { prev_sym_handle = SYM_NULL; prev_parm = NULL; for( parm = ParmList; parm != NULL; parm = parm->next_parm ) { if( parm->sym.name == NULL ) { parm->sym.name = ".J"; parm->sym.flags |= SYM_REFERENCED; } if( parm->sym.name[0] == '\0' ) { parm->sym.name = ".I"; InvDecl(); } if( parm->sym.sym_type == NULL ) { parm->sym.sym_type = TypeDefault(); } /* make sure name not already defined in this SymLevel */ sym_handle = SymAdd( parm->sym.info.hash, &parm->sym ); 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->sym.flags |= SYM_DEFINED | SYM_ASSIGNED; parm->sym.attribs.is_parm = true; } if( prev_parm != NULL ) { #if _CPU == 370 { SYM_ENTRY var_parm; if( VarParm( CurFunc ) ) { typ = ArrayNode( GetType( TYPE_CHAR ) ); typ->u.array->dimension = 160; sym_handle = GetNewSym( &var_parm, 'V', typ, SC_AUTO ); SymReplace( &var_parm, sym_handle ); prev_parm->sym.handle = sym_handle; } } #endif SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } } }
static SYM_HANDLE GetLocalVarDecls( void ) { SYM_HANDLE symlist; SYM_HANDLE symhandle; SYM_ENTRY sym; DeclList( &symlist ); if( symlist != 0 ) { symhandle = CurFunc->u.func.locals; // symhandle will be non-zero if MakeNewSym was called while // parsing the declaration list. if( symhandle != 0 ) { // if some temporaries were created for( ;; ) { // - find end of list SymGet( &sym, symhandle ); if( sym.handle == 0 ) break; symhandle = sym.handle; } sym.handle = symlist; SymReplace( &sym, symhandle ); } else { CurFunc->u.func.locals = symlist; } } return( symlist ); }
static void PragIntrinsic( int intrinsic ) /* 09-oct-92 */ /****************************************/ { SYM_HANDLE sym_handle; SYM_ENTRY sym; if( ExpectingToken( T_LEFT_PAREN ) ) { NextToken(); while( IS_ID_OR_KEYWORD( CurToken ) ) { sym_handle = SymLook( HashValue, Buffer ); if( sym_handle != 0 ) { SymGet( &sym, sym_handle ); sym.flags &= ~ SYM_INTRINSIC; if( intrinsic ) sym.flags |= SYM_INTRINSIC; SymReplace( &sym, sym_handle ); } NextToken(); if( CurToken != T_COMMA ) break; NextToken(); } MustRecog( T_RIGHT_PAREN ); } }
static SYM_HANDLE DummyTrySymbol( void ) { SYM_ENTRY sym; SYM_HANDLE sym_handle; sym_handle = MakeNewSym( &sym, 'T', GetType( TYPE_VOID ), SC_STATIC ); SymReplace( &sym, sym_handle ); return( sym_handle ); }
static void MarkTryVolatile( SYM_HANDLE sym_handle ) { SYM_ENTRY sym; for( ;; ) { if( sym_handle == 0 ) break; SymGet( &sym, sym_handle ); sym.flags |= SYM_TRY_VOLATILE; //force into memory SymReplace( &sym, sym_handle ); sym_handle = sym.handle; } }
static void FuncDefn( SYMPTR sym ) { SYM_NAMEPTR sym_name; size_t sym_len; TYPEPTR typ; /* duplicate name in near space */ sym_name = SymName( sym, CurFuncHandle ); sym_len = strlen( sym_name ) + 1; sym->name = CMemAlloc( sym_len ); memcpy( sym->name, sym_name, sym_len ); if( sym->flags & SYM_DEFINED ) { CErr2p( ERR_SYM_ALREADY_DEFINED, sym->name ); } typ = sym->sym_type->object; /* get return type */ SKIP_TYPEDEFS( typ ); if( typ->decl_type != TYPE_VOID ) { if( TypeSize( typ ) == 0 ) { CErr2p( ERR_INCOMPLETE_TYPE, sym_name ); } } sym->flags |= SYM_DEFINED /* | SYM_REFERENCED */; if( (GenSwitches & NO_OPTIMIZATION) == 0 ) { sym->flags |= SYM_OK_TO_RECURSE; } if( sym->attribs.stg_class == SC_EXTERN || sym->attribs.stg_class == SC_FORWARD ) { sym->attribs.stg_class = SC_NONE; /* indicate exported function */ } CompFlags.external_defn_found = 1; if( Toggles & TOGGLE_CHECK_STACK ) sym->flags |= SYM_CHECK_STACK; if( !CompFlags.zu_switch_used ) { if( (sym->mods & FLAG_INTERRUPT) == FLAG_INTERRUPT ) { /* interrupt function */ TargetSwitches |= FLOATING_SS; /* force -zu switch on */ } else { TargetSwitches &= ~FLOATING_SS; /* turn it back off */ } } if( CMPLIT( CurFunc->name, "main" ) == 0 || CMPLIT( CurFunc->name, "wmain" ) == 0 ) { sym->mods &= ~MASK_LANGUAGES; // Turn off any language flags sym->mods |= LANG_WATCALL; // Turn on __watcall calling convention for main } SymReplace( sym, CurFuncHandle ); }
local void FuncDefn( SYMPTR sym ) { SYM_NAMEPTR sym_name; int sym_len; TYPEPTR typ; /* duplicate name in near space */ sym_name = SymName( sym, CurFuncHandle ); sym_len = far_strlen_plus1( sym_name ); sym->name = CMemAlloc( sym_len ); far_memcpy( sym->name, sym_name, sym_len ); if( sym->flags & SYM_DEFINED ) { CErr2p( ERR_SYM_ALREADY_DEFINED, sym->name ); /* 03-aug-88 */ } typ = sym->sym_type->object; /* get return type */ SKIP_TYPEDEFS( typ ); if( typ->decl_type != TYPE_VOID ) { /* 26-mar-91 */ if( TypeSize( typ ) == 0 ) { CErr( ERR_INCOMPLETE_TYPE, sym_name ); } } sym->flags |= /*SYM_REFERENCED | 18-jan-89 */ SYM_DEFINED; if( !(GenSwitches & NO_OPTIMIZATION) ) { sym->flags |= SYM_OK_TO_RECURSE; /* 25-sep-91 */ } if( sym->stg_class == SC_EXTERN || sym->stg_class == SC_FORWARD ) { sym->stg_class = SC_NULL; /* indicate exported function */ } CompFlags.external_defn_found = 1; if( Toggles & TOGGLE_CHECK_STACK ) sym->flags |= SYM_CHECK_STACK; if( !CompFlags.zu_switch_used ) { if( (sym->attrib & FLAG_INTERRUPT) == FLAG_INTERRUPT ) { /* interrupt function */ TargetSwitches |= FLOATING_SS; /* force -zu switch on */ } else { TargetSwitches &= ~FLOATING_SS; /* turn it back off */ } } if( strcmp( CurFunc->name, "main" ) == 0 || strcmp( CurFunc->name, "wmain" ) == 0 ) { sym->attrib &= ~FLAG_LANGUAGES; // Turn off any language flags sym->attrib |= LANG_WATCALL; // Turn on __watcall calling convention for main } SymReplace( sym, CurFuncHandle ); }
local void AggregateVarDeclEquals( SYMPTR sym, SYM_HANDLE sym_handle ) { SYM_HANDLE sym2_handle; SYM_ENTRY sym2; sym2_handle = MakeNewSym( &sym2, 'X', sym->sym_type, SC_STATIC ); sym2.flags |= SYM_INITIALIZED; CompFlags.initializing_data = 1; StaticInit( &sym2, sym2_handle ); CompFlags.initializing_data = 0; SymReplace( &sym2, sym2_handle ); /* StaticInit will change sym2.sym_type if it is an incomplete array type */ sym->sym_type = sym2.sym_type; AssignAggregate( VarLeaf( sym, sym_handle ), VarLeaf( &sym2, sym2_handle ), sym->sym_type ); }
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 PragAllocText( void ) /* 26-oct-91 */ /******************************/ { struct textsegment *seg; SYM_HANDLE sym_handle; auto SYM_ENTRY sym; if( ExpectingToken( T_LEFT_PAREN ) ) { NextToken(); /* current token can be an T_ID or a T_STRING */ seg = LkSegName( Buffer, "" ); NextToken(); for( ; ; ) { MustRecog( T_COMMA ); /* current token can be an T_ID or a T_STRING */ sym_handle = Sym0Look( CalcHash( Buffer, strlen( Buffer ) ), Buffer ); if( sym_handle == 0 ) { /* error */ } else { SymGet( &sym, sym_handle ); if( sym.flags & SYM_FUNCTION ) { sym.seginfo = seg; SymReplace( &sym, sym_handle ); } else { /* error, must be function */ } } NextToken(); if( CurToken == T_RIGHT_PAREN ) break; if( CurToken == T_EOF ) break; if( CurToken == T_NULL ) { break; } } #if _CPU == 8086 || _CPU == 386 CompFlags.multiple_code_segments = 1; #endif MustRecog( T_RIGHT_PAREN ); } }
void EmitSegLabels( void ) /* 15-mar-92 */ { int seg; struct user_seg *useg; BACK_HANDLE bck; SYM_ENTRY sym; seg = FIRST_USER_SEGMENT; for( useg = UserSegments; useg; useg = useg->next ) { if( useg->sym_handle != 0 ) { SymGet( &sym, useg->sym_handle ); bck = BENewBack( useg->sym_handle ); sym.info.backinfo = bck; SymReplace( &sym, useg->sym_handle ); BESetSeg( seg ); DGLabel( bck ); } ++seg; } }
enum sym_state AsmQueryExternal( char *name ) /*******************************************/ { SYM_HANDLE sym_handle; SYM_ENTRY sym; sym_handle = SymLook( CalcHash( name, strlen( name ) ), name ); if( sym_handle == 0 ) return( SYM_UNDEFINED ); SymGet( &sym, sym_handle ); if( !(sym.flags & SYM_REFERENCED) ) { sym.flags |= SYM_REFERENCED; SymReplace( &sym, sym_handle ); } switch( sym.stg_class ) { case SC_AUTO: case SC_REGISTER: return( SYM_STACK ); } return( SYM_EXTERNAL ); }
void ParsePgm( void ) { SYM_HANDLE dummysym; CompFlags.external_defn_found = 0; CompFlags.initializing_data = 0; dummysym = SYM_NULL; GlobalSym = SYM_NULL; do { if( DeclList( &dummysym ) ) { /* if this is a function defn */ FuncDefn( CurFunc ); SrcLoc = CurFunc->src_loc; GenFunctionNode( CurFuncHandle ); SymLevel = 1; ParmDeclList(); SymLevel = 0; if( CurToken == T_LEFT_BRACE ) { BeginFunc(); Statement(); CMemFree( CurFunc->name ); CurFunc->name = NULL; SymReplace( CurFunc, CurFuncHandle ); CurFunc = NULL; CurFuncNode = NULL; CurFuncHandle = SYM_NULL; } else { MustRecog( T_LEFT_BRACE ); } } } while( CurToken != T_EOF ); if( CompFlags.external_defn_found == 0 ) { if( !CompFlags.extensions_enabled ) { CErr1( ERR_NO_EXTERNAL_DEFNS_FOUND ); } } }
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; } }
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 int InsertFixups( unsigned char *buff, unsigned i, byte_seq **code ) /*************************************************************************/ { /* additional slop in buffer to simplify the code */ unsigned char temp[MAXIMUM_BYTESEQ + 1 + 2 * sizeof( long )]; struct asmfixup *fix; struct asmfixup *head; struct asmfixup *chk; struct asmfixup *next; struct asmfixup **owner; unsigned char *dst; unsigned char *src; unsigned char *end; byte_seq *seq; byte_seq_len perform_fixups; unsigned char cg_fix; SYM_HANDLE sym_handle; SYM_ENTRY sym; char *name; unsigned skip; int mutate_to_segment; int uses_auto; #if _CPU == 8086 int fixup_padding; #endif sym_handle = 0; uses_auto = 0; perform_fixups = 0; head = FixupHead; if( head != NULL ) { FixupHead = NULL; /* sort the fixup list in increasing fixup_loc's */ for( fix = head; fix != NULL; fix = next ) { owner = &FixupHead; for( ;; ) { chk = *owner; if( chk == NULL ) break; if( chk->fixup_loc > fix->fixup_loc ) break; owner = &chk->next; } next = fix->next; fix->next = *owner; *owner = fix; } dst = temp; src = buff; end = src + i; fix = FixupHead; owner = &FixupHead; /* insert fixup escape sequences */ while( src < end ) { if( fix != NULL && fix->fixup_loc == (src - buff) ) { name = fix->name; if( name != NULL ) { sym_handle = SymLook( CalcHash( name, strlen( name ) ), name ); if( sym_handle == 0 ) { CErr2p( ERR_UNDECLARED_SYM, name ); return( 0 ); } SymGet( &sym, sym_handle ); sym.flags |= SYM_REFERENCED | SYM_ADDR_TAKEN; switch( sym.stg_class ) { case SC_REGISTER: case SC_AUTO: sym.flags |= SYM_USED_IN_PRAGMA; CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE; uses_auto = 1; break; } SymReplace( &sym, sym_handle ); } /* insert fixup information */ skip = 0; *dst++ = FLOATING_FIXUP_BYTE; mutate_to_segment = 0; #if _CPU == 8086 fixup_padding = 0; #endif switch( fix->fixup_type ) { case FIX_FPPATCH: *dst++ = fix->offset; break; case FIX_SEG: if( name == NULL ) { // special case for floating point fixup if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) { // inline assembler FWAIT instruction 0x90, 0x9b *dst++ = FIX_FPP_WAIT; } else if( src[0] == 0x9b && (src[1] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as second byte *dst++ = FIX_FPP_NORMAL; } else if( src[0] == 0x9b && (src[2] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as third byte // second byte should be segment override prefix switch( src[1] ) { case PREFIX_ES: *dst++ = FIX_FPP_ES; break; case PREFIX_CS: *dst++ = FIX_FPP_CS; break; case PREFIX_SS: *dst++ = FIX_FPP_SS; break; case PREFIX_DS: *dst++ = FIX_FPP_DS; break; case PREFIX_GS: *dst++ = FIX_FPP_GS; break; case PREFIX_FS: *dst++ = FIX_FPP_FS; break; default: --dst; break; // skip FP patch } } else { // skip FP patch --dst; } } else { skip = 2; cg_fix = FIX_SYM_SEGMENT; } break; case FIX_RELOFF16: skip = 2; cg_fix = FIX_SYM_RELOFF; break; case FIX_RELOFF32: skip = 4; cg_fix = FIX_SYM_RELOFF; #if _CPU == 8086 fixup_padding = 1; #endif break; case FIX_PTR16: mutate_to_segment = 1; /* fall through */ case FIX_OFF16: skip = 2; cg_fix = FIX_SYM_OFFSET; break; case FIX_PTR32: mutate_to_segment = 1; /* fall through */ case FIX_OFF32: skip = 4; cg_fix = FIX_SYM_OFFSET; #if _CPU == 8086 fixup_padding = 1; #endif break; default: CErr2p( ERR_UNREACHABLE_SYM, name ); break; } if( skip != 0 ) { *dst++ = cg_fix; *((CGSYM_HANDLE *)dst) = sym_handle; dst += sizeof( CGSYM_HANDLE ); *((unsigned long *)dst) = fix->offset; dst += sizeof( long ); src += skip; } #if _CPU == 8086 if( fixup_padding ) { // add offset fixup padding to 32-bit // cg create only 16-bit offset fixup *dst++ = 0; *dst++ = 0; // } #endif if( mutate_to_segment ) { /* Since the CG escape sequences don't allow for FAR pointer fixups, we have to split them into two. This is done by doing the offset fixup first, then mutating the fixup structure to look like a segment fixup one near pointer size later. */ fix->fixup_type = FIX_SEG; fix->fixup_loc += skip; fix->offset = 0; } else { head = fix; fix = fix->next; if( head->external ) { *owner = fix; if( head->name != NULL ) { CMemFree( head->name ); } CMemFree( head ); } else { owner = &head->next; } } } else { if( *src == FLOATING_FIXUP_BYTE ) { *dst++ = FLOATING_FIXUP_BYTE; } *dst++ = *src++; } if( dst > &temp[MAXIMUM_BYTESEQ] ) { CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA ); return( 0 ); } } buff = temp; i = dst - temp; perform_fixups = DO_FLOATING_FIXUPS; } seq = (byte_seq *)CMemAlloc( sizeof( byte_seq ) + i ); seq->length = i | perform_fixups; memcpy( &seq->data[0], buff, i ); *code = seq; return( uses_auto ); }
void StaticInit( SYMPTR sym, SYM_HANDLE sym_handle ) { TYPEPTR typ; TYPEPTR struct_typ; TYPEPTR last_array; GenStaticDataQuad( sym_handle ); CompFlags.non_zero_data = 0; struct_typ = NULL; last_array = NULL; typ = sym->sym_type; /* Follow chain of typedefs/structs/arrays */ for( ;; ) { SKIP_TYPEDEFS( typ ); if( typ->decl_type == TYPE_ARRAY ) { /* Remember innermost array type */ last_array = typ; typ = typ->object; } else if( typ->decl_type == TYPE_STRUCT ) { FIELDPTR field; /* Remember outermost structure type */ if( struct_typ == NULL ) { /* last_array cannot to be outside this struct! */ last_array = NULL; struct_typ = typ; } /* Determine the type of the last field in the struct */ field = typ->u.tag->u.field_list; if( field == NULL ) break; /* 10-sep-92 */ while( field->next_field != NULL ) field = field->next_field; typ = field->field_type; } else { break; } } typ = last_array; /* If innermost array had unspecified dimension, create new types whose * dimensions will be determined by number of initializers */ if( (typ != NULL) && typ->u.array->unspecified_dim ) { if( struct_typ == NULL ) { /* Array was not inside struct */ sym->sym_type = ArrayNode( typ->object ); /* 18-oct-88 */ sym->sym_type->u.array->unspecified_dim = TRUE; } else { typ = sym->sym_type; /* Create new structure type */ sym->sym_type = TypeNode( TYPE_STRUCT, ArrayNode( last_array->object ) ); sym->sym_type->u.tag = struct_typ->u.tag; struct_typ = sym->sym_type; /* Create new array types as necessary */ for( ;; ) { SKIP_TYPEDEFS( typ ); if( typ->decl_type != TYPE_ARRAY ) break; sym->sym_type = ArrayNode( sym->sym_type ); sym->sym_type->u.array->unspecified_dim = TRUE; typ = typ->object; } typ = last_array; } } else { struct_typ = NULL; } SymReplace( sym, sym_handle ); /* 31-aug-88 */ InitSymData( sym->sym_type, sym->sym_type, 0 ); SymGet( sym, sym_handle ); /* 31-aug-88 */ if( struct_typ != NULL ) { /* 17-mar-92 */ /* Structure contains an unspecified length array as last field */ struct_typ->object->u.array->dimension = typ->u.array->dimension; typ->u.array->unspecified_dim = TRUE; typ->u.array->dimension = 0; /* Reset back to 0 */ } if( sym->u.var.segment == 0 ) { /* 01-dec-91 */ SetFarHuge( sym, 0 ); SetSegment( sym ); SetSegAlign( sym ); /* 02-feb-92 */ } }