static aux_info *InfoLookup( SYMPTR sym ) { char *name; aux_info *inf; aux_entry *ent; name = sym->name; inf = &DefaultInfo; /* assume default */ if( name == NULL ) return( inf ); ent = AuxLookup( name ); if( ent != NULL ) inf = ent->info; if( ( ent == NULL ) || (sym->flags & SYM_INTRINSIC) ) { if( sym->flags & SYM_DEFINED ) return( inf ); if( (sym->flags & SYM_INTRINSIC) == 0 ) { if( memcmp( name, "_inline_", 8 ) != 0 ) return( inf ); name += 8; } #if ( _CPU == 8086 ) || ( _CPU == 386 ) { const inline_funcs *ifunc; ifunc = IF_Lookup( name ); if( ifunc == NULL ) return( inf ); #if ( _CPU == 8086 ) if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_SI ) || HW_CEqual( ifunc->returns, HW_ES_DI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 4 ) { #else if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_ESI ) || HW_CEqual( ifunc->returns, HW_ES_EDI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 6 ) { #endif return( inf ); } } inf = &InlineInfo; inf->cclass = (WatcallInfo.cclass & FAR_CALL) | MODIFY_EXACT; if( (sym->flags & SYM_INTRINSIC) && ( ent != NULL ) ) inf->cclass |= ent->info->cclass; inf->code = ifunc->code; inf->parms = ifunc->parms; inf->returns = ifunc->returns; #if ( _CPU == 8086 ) if( !HW_CEqual( inf->returns, HW_AX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #else if( !HW_CEqual( inf->returns, HW_EAX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #endif inf->cclass |= SPECIAL_RETURN; } HW_CAsgn( inf->streturn, HW_EMPTY ); inf->save = ifunc->save; inf->objname = WatcallInfo.objname; inf->use = 1; } #endif } return( inf ); } aux_info *FindInfo( SYMPTR sym, SYM_HANDLE sym_handle ) { SYM_ENTRY sym_typedef; aux_entry *ent; TYPEPTR typ; aux_info *inf; inf = &DefaultInfo; /* assume default */ if( sym_handle == SYM_NULL ) return( inf ); SymGet( sym, sym_handle ); #if _CPU == 386 if( (sym_handle == SymSTOSB) || (sym_handle == SymSTOSD) ) { return( &STOSBInfo ); } else if( sym_handle == SymFinally ) { InlineInfo = WatcallInfo; InlineInfo.code = (byte_seq *)&FinallyCode; return( &InlineInfo ); } else if( sym_handle == SymTryFini ) { InlineInfo = WatcallInfo; InlineInfo.parms = TryFiniParms; InlineInfo.code = (byte_seq *)&TryFiniCode; return( &InlineInfo ); } #endif if( (sym->flags & SYM_TEMP) == 0 ) { /* not an indirect func call*/ inf = InfoLookup( sym ); } if( inf == &DefaultInfo ) { typ = sym->sym_type; SKIP_DUMMY_TYPEDEFS( typ ); if( typ->decl_type == TYPE_TYPEDEF ) { SymGet( &sym_typedef, typ->u.typedefn ); if( sym_typedef.name != NULL ) { ent = AuxLookup( sym_typedef.name ); if( ent != NULL ) { inf = ent->info; } } } } #if _CPU == 386 if( (inf->flags & AUX_FLAG_FAR16) || (sym->mods & FLAG_FAR16) ) { if( (sym->mods & MASK_LANGUAGES) == LANG_PASCAL || (inf->cclass & REVERSE_PARMS) ) { return( &Far16PascalInfo ); } else { return( &Far16CdeclInfo ); } } #endif return( inf ); } bool FunctionAborts( SYMPTR sym, SYM_HANDLE sym_handle ) { aux_entry *ent; if( sym_handle != SYM_NULL ) { SymGet( sym, sym_handle ); ent = AuxLookup( SymName( sym, sym_handle ) ); if( ent != NULL ) { if( ent->info->cclass & SUICIDAL ) { return( TRUE ); } } } return( FALSE ); } call_class GetCallClass( SYM_HANDLE sym_handle ) { aux_info *inf; SYM_ENTRY sym; call_class cclass; cclass = DefaultInfo.cclass; if( sym_handle != SYM_NULL ) { inf = FindInfo( &sym, sym_handle ); if( sym.flags & SYM_FUNCTION ) { if( inf != &DefaultInfo ) { cclass = inf->cclass; } else { cclass = GetLangInfo( sym.mods )->cclass; #if _CPU == 8086 if( TargSys == TS_WINDOWS ) { if( sym.mods & (LANG_CDECL | LANG_PASCAL) ) { cclass |= FAT_WINDOWS_PROLOG; } } #endif } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( CompFlags.emit_names ) { cclass |= EMIT_FUNCTION_NAME; } if( sym.mods & FLAG_FAR ) { cclass |= FAR_CALL; if( sym.mods & FLAG_NEAR ) { cclass |= INTERRUPT; } } else if( sym.mods & FLAG_NEAR ) { cclass &= ~ FAR_CALL; } #endif #ifdef DLL_EXPORT if( sym.mods & FLAG_EXPORT ) { cclass |= DLL_EXPORT; } #endif #ifdef LOAD_DS_ON_ENTRY if( sym.mods & FLAG_LOADDS ) { #if 0 if( TargSys == TS_WINDOWS ) { cclass |= FAT_WINDOWS_PROLOG; } else { cclass |= LOAD_DS_ON_ENTRY; } #else cclass |= LOAD_DS_ON_ENTRY; #endif } #endif #ifdef MAKE_CALL_INLINE if( IsInLineFunc( sym_handle ) ) { cclass |= MAKE_CALL_INLINE; } #endif if( VarFunc( &sym ) ) { cclass |= CALLER_POPS | HAS_VARARGS; } } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( sym.flags & SYM_FUNC_NEEDS_THUNK ) { cclass |= THUNK_PROLOG; } #endif } #ifdef REVERSE cclass &= ~ REVERSE_PARMS; #endif #ifdef PROLOG_HOOKS if( CompFlags.ep_switch_used != 0 ) { cclass |= PROLOG_HOOKS; } #endif #ifdef EPILOG_HOOKS if( CompFlags.ee_switch_used != 0 ) { cclass |= EPILOG_HOOKS; } #endif #ifdef GROW_STACK if( CompFlags.sg_switch_used ) { cclass |= GROW_STACK; } #endif #ifdef TOUCH_STACK if( CompFlags.st_switch_used ) { cclass |= TOUCH_STACK; } #endif return( cclass ); }
struct aux_info *InfoLookup( SYMPTR sym ) { char *name; struct aux_info *inf; struct aux_entry *ent; name = sym->name; inf = &DefaultInfo; /* assume default */ if( name == NULL ) return( inf ); /* 01-jun-90 */ ent = AuxLookup( name ); if( ent != NULL ) inf = ent->info; if( ( ent == NULL ) || (sym->flags & SYM_INTRINSIC) ) { if( sym->flags & SYM_DEFINED ) return( inf ); if( !(sym->flags & SYM_INTRINSIC) ) { if( memcmp( name, "_inline_", 8 ) != 0 ) return( inf ); name += 8; } #if ( _CPU == 8086 ) || ( _CPU == 386 ) { struct inline_funcs *ifunc; ifunc = IF_Lookup( name ); if( ifunc == NULL ) return( inf ); #if ( _CPU == 8086 ) if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_SI ) || HW_CEqual( ifunc->returns, HW_ES_DI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 4 ) { #else if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_ESI ) || HW_CEqual( ifunc->returns, HW_ES_EDI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 6 ) { #endif return( inf ); } } inf = &InlineInfo; inf->cclass = (WatcallInfo.cclass & FAR) | MODIFY_EXACT; if( (sym->flags & SYM_INTRINSIC) && ( ent != NULL ) ) inf->cclass |= ent->info->cclass; inf->code = ifunc->code; inf->parms = ifunc->parms; inf->returns = ifunc->returns; #if ( _CPU == 8086 ) if( !HW_CEqual( inf->returns, HW_AX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #else if( !HW_CEqual( inf->returns, HW_EAX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #endif inf->cclass |= SPECIAL_RETURN; } HW_CAsgn( inf->streturn, HW_EMPTY ); inf->save = ifunc->save; inf->objname = WatcallInfo.objname; /* 26-jan-93 */ inf->use = 1; } #endif } return( inf ); } struct aux_info *FindInfo( SYM_ENTRY *sym, SYM_HANDLE sym_handle ) { SYM_ENTRY sym_typedef; struct aux_entry *ent; TYPEPTR typ; struct aux_info *inf; inf = &DefaultInfo; /* assume default */ if( sym_handle == 0 ) return( inf ); SymGet( sym, sym_handle ); #if _CPU == 386 if( (sym_handle == SymSTOSB) || (sym_handle == SymSTOSD) ) { return( &STOSBInfo ); } else if( sym_handle == SymFinally ) { static byte_seq FinallyCode = { 1, { 0xc3 } }; /* ret */ InlineInfo = WatcallInfo; InlineInfo.code = &FinallyCode; return( &InlineInfo ); } else if( sym_handle == SymTryFini ) { static hw_reg_set TryFiniParms[] = { HW_D( HW_EAX ), HW_D( HW_EMPTY ) }; static byte_seq TryFiniCode = { 6, { 0x64, 0xA3, 0, 0, 0, 0 } }; /* mov fs:[0],eax */ InlineInfo = WatcallInfo; InlineInfo.parms = TryFiniParms; InlineInfo.code = &TryFiniCode; return( &InlineInfo ); } #endif if( !(sym->flags & SYM_TEMP) ) { /* not an indirect func call*/ inf = InfoLookup( sym ); } if( inf == &DefaultInfo ) { typ = SkipDummyTypedef( sym->sym_type ); if( typ->decl_type == TYPE_TYPEDEF ) { SymGet( &sym_typedef, typ->u.typedefn ); if( sym_typedef.name != NULL ) { ent = AuxLookup( sym_typedef.name ); if( ent != NULL ) { inf = ent->info; } } } } #if _CPU == 386 if( ( inf->flags & AUX_FLAG_FAR16 ) || ( sym->attrib & FLAG_FAR16 ) ) { if( ( (sym->attrib & FLAG_LANGUAGES) == LANG_PASCAL ) || ( inf->cclass & REVERSE_PARMS ) ) { return( &Far16PascalInfo ); } else { return( &Far16CdeclInfo ); } } #endif return( inf ); } int FunctionAborts( SYM_ENTRY *sym, SYM_HANDLE sym_handle ) /* 09-apr-93 */ { struct aux_entry *ent; if( sym_handle != 0 ) { /* 19-apr-93 */ SymGet( sym, sym_handle ); ent = AuxLookup( SymName( sym, sym_handle ) ); if( ent != NULL ) { if( ent->info->cclass & SUICIDAL ) { return( 1 ); } } } return( 0 ); } void GetCallClass( SYM_HANDLE sym_handle ) { struct aux_info *inf; SYM_ENTRY sym; CallClass = DefaultInfo.cclass; if( sym_handle != 0 ) { inf = FindInfo( &sym, sym_handle ); if( sym.flags & SYM_FUNCTION ) { if( inf != &DefaultInfo ) { CallClass = inf->cclass; } else { CallClass = GetLangInfo( sym.attrib )->cclass; #if _CPU == 8086 if( TargSys == TS_WINDOWS ) { if( sym.attrib & (LANG_CDECL | LANG_PASCAL) ) { CallClass |= FAT_WINDOWS_PROLOG; } } #endif } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( CompFlags.emit_names ) { CallClass |= EMIT_FUNCTION_NAME; } if( sym.attrib & FLAG_FAR ) { CallClass |= FAR; if( sym.attrib & FLAG_NEAR ) { CallClass |= INTERRUPT; } } else if( sym.attrib & FLAG_NEAR ) { CallClass &= ~ FAR; } #endif #ifdef DLL_EXPORT if( sym.attrib & FLAG_EXPORT ) { /* 12-mar-90 */ CallClass |= DLL_EXPORT; } #endif #ifdef LOAD_DS_ON_ENTRY if( sym.attrib & FLAG_LOADDS ) { /* 26-apr-90 */ #if 0 /* John - 11-mar-93 */ /* 21-feb-93 */ if( TargSys == TS_WINDOWS ) { CallClass |= FAT_WINDOWS_PROLOG; } else { CallClass |= LOAD_DS_ON_ENTRY; } #else CallClass |= LOAD_DS_ON_ENTRY; #endif } #endif #ifdef MAKE_CALL_INLINE if( IsInLineFunc( sym_handle ) ) { CallClass |= MAKE_CALL_INLINE; } #endif if( VarFunc( &sym ) ) { CallClass |= CALLER_POPS | HAS_VARARGS; } } } #ifdef REVERSE CallClass &= ~ REVERSE_PARMS; /* 28-may-89 */ #endif #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( sym_handle != 0 && sym.flags & SYM_FUNC_NEEDS_THUNK ) { CallClass |= THUNK_PROLOG; } #endif #ifdef PROLOG_HOOKS if( CompFlags.ep_switch_used != 0 ) { CallClass |= PROLOG_HOOKS; } #endif #ifdef EPILOG_HOOKS if( CompFlags.ee_switch_used != 0 ) { CallClass |= EPILOG_HOOKS; } #endif #ifdef GROW_STACK if( CompFlags.sg_switch_used ) { CallClass |= GROW_STACK; } #endif #ifdef TOUCH_STACK if( CompFlags.st_switch_used ) { CallClass |= TOUCH_STACK; } #endif } static time_t *getFileDepTimeStamp( FNAMEPTR flist ) { static time_t stamp; #if ( ( _CPU == 8086 ) || ( _CPU == 386 ) ) && ( COMP_CFG_COFF == 0 ) stamp = _timet2dos( flist->mtime ); #else stamp = flist->mtime; #endif return( &stamp ); } /* // NextLibrary // Called (indirectly) from the code generator to inject automagically defined symbols. // Inputs: // index (n-1) // Usually called from a loop until we return 0/NULL to show no more libraries // request // NEXT_LIBRARY // examines the current flags to see if any libraries should be // automagically referenced and returns the relevant index if so. // LIBRARY_NAME // returns the requested name. // */ static VOIDPTR NextLibrary( int index, aux_class request ) { struct library_list *liblist; char *name = NULL; int i; i = 0; if( request == NEXT_LIBRARY ) ++index; for( liblist = HeadLibs; liblist; liblist = liblist->next ) { name = &liblist->prio; ++i; if( i == index ) { break; } } if( liblist == NULL ) { switch( index - i ) { case 1: /* return 1 for CLIB */ name = CLIB_Name; if( CompFlags.emit_library_any ) break; if( CompFlags.emit_library_with_main ) { if( CompFlags.has_main ) break; if( CompFlags.has_winmain ) break; if( CompFlags.bd_switch_used ) break; if( CompFlags.has_libmain ) break; if( CompFlags.bm_switch_used ) break; /* JBS */ ++index; } else { name = NULL; index = 0; // indicate all done } break; /* // MATHLIB is always referenced as a default library because // the linker wont include anything without a 'real' referenced // symbol */ case 2: /* return 2 for MATHLIB */ name = MATHLIB_Name; break; case 3: /* return 3 for EMULIB */ name = EmuLib_Name; if( EmuLib_Name != NULL ) break; // fall through case 4: /* used to be PCODE */ name = NULL; index = 0; // indicate all done break; default: break; } } /* // return library name, or */ if( request == LIBRARY_NAME ) return( name ); /* // library index */ return( (char *)index ); } // NextAlias // Called (indirectly) from the code generator to go through the list of // linker aliases. // Inputs: // index (n-1) // Called from a loop until we return 0/NULL to show no more aliases // request // NEXT_ALIAS // returns the index of next alias in the list, or zero if none. // ALIAS_NAME // returns the alias name, or NULL if alias refers to a symbol. // ALIAS_SYMBOL // returns the alias symbol, or NULL if alias refers to a name. // ALIAS_SUBSTITUTE // returns the name to be substituted for the alias. // // Note: One of ALIAS_NAME and ALIAS_SYMBOL will always be 0/NULL and the other // will be valid, depending on which form of the pragma was used. static VOIDPTR NextAlias( int index, aux_class request ) { struct alias_list *aliaslist; SYM_HANDLE alias_sym = NULL; SYM_HANDLE subst_sym = NULL; const char *alias_name = NULL; const char *subst_name = NULL; int i; if( request == NEXT_ALIAS ) ++index; for( i = 1, aliaslist = AliasHead; aliaslist; aliaslist = aliaslist->next, ++i ) { alias_name = aliaslist->name; alias_sym = aliaslist->a_sym; subst_name = aliaslist->subst; subst_sym = aliaslist->s_sym; if( i == index ) { break; } } if( aliaslist == NULL ) index = 0; /* no (more) aliases */ if( request == ALIAS_NAME ) { return( (VOIDPTR)alias_name ); } else if( request == ALIAS_SYMBOL ) { return( (VOIDPTR)alias_sym ); } else if( request == ALIAS_SUBST_NAME ) { return( (VOIDPTR)subst_name ); } else if( request == ALIAS_SUBST_SYMBOL ) { return( (VOIDPTR)subst_sym ); } else { // this had better be a NEXT_ALIAS request return( (VOIDPTR)index ); } } /* Return the size of function parameters or -1 if size could * not be determined (symbol isn't a function or is variadic) */ static int GetParmsSize( CGSYM_HANDLE sym_handle ) { int total_parm_size = 0; int parm_size; TYPEPTR fn_typ; TYPEPTR *parm; TYPEPTR typ; SYM_ENTRY sym; SymGet( &sym, sym_handle ); fn_typ = sym.sym_type; SKIP_TYPEDEFS( fn_typ ); if( fn_typ->decl_type == TYPE_FUNCTION ) { parm = fn_typ->u.fn.parms; if( parm != NULL ) { for( ; (typ = *parm); ++parm ) { if( typ->decl_type == TYPE_DOT_DOT_DOT ) { total_parm_size = -1; break; } SKIP_TYPEDEFS( typ ); if( typ->decl_type == TYPE_VOID ) break; parm_size = TypeSize( typ ); parm_size = (parm_size + sizeof( target_int ) - 1) & -sizeof( target_int ); total_parm_size += parm_size; } } } else { total_parm_size = -1; } return( total_parm_size ); } /* // Return name pattern manipulator string */ static char *GetNamePattern( CGSYM_HANDLE sym_handle ) { char *pattern; SYM_ENTRY sym; struct aux_info *inf; inf = FindInfo( &sym, sym_handle ); #ifdef __SEH__ if(( sym_handle == SymTryInit ) || ( sym_handle == SymTryFini ) || ( sym_handle == SymTryUnwind ) || ( sym_handle == SymExcept )) { pattern = "*"; } else { #endif inf = LangInfo( sym.attrib, inf ); if( sym.flags & SYM_FUNCTION ) { pattern = inf->objname; #if ( _CPU == 386 ) || ( _CPU == 8086 ) if( VarFunc( &sym ) ) { if( inf == &DefaultInfo ) inf = DftCallConv; if( inf == &StdcallInfo ) { pattern = CdeclInfo.objname; } else if( inf == &FastcallInfo ) { pattern = CdeclInfo.objname; } } #endif if( pattern == NULL ) { pattern = TS_CODE_MANGLE; } } else { pattern = VarNamePattern( inf ); if( pattern == NULL ) { pattern = TS_DATA_MANGLE; } } #ifdef __SEH__ } // close that else #endif return( pattern ); }