/* // Return name pattern manipulator string */ static const char *GetNamePattern( SYM_HANDLE sym_handle ) { char *pattern; SYM_ENTRY sym; 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.mods, 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 ); }
static fe_attr FESymAttr( SYMPTR sym ) /************************************/ { fe_attr attr; attr = 0; switch( sym->attribs.stg_class ) { case SC_FORWARD: case SC_EXTERN: attr = FE_GLOBAL | FE_IMPORT | FE_STATIC; break; case SC_NONE: attr = FE_GLOBAL | FE_STATIC; break; case SC_STATIC: attr = FE_STATIC | FE_VISIBLE; if( sym->level != 0 ) { attr |= FE_INTERNAL; } break; } if( sym->flags & SYM_FUNCTION ) { attr |= FE_PROC | FE_STATIC; if( VarFunc( sym ) ) attr |= FE_VARARGS; if( CompFlags.unique_functions ) { if( (attr & FE_GLOBAL) || (sym->flags & SYM_ADDR_TAKEN) ) { attr |= FE_UNIQUE; } } } if( sym->flags & SYM_USED_IN_PRAGMA ) { attr |= FE_MEMORY | FE_ADDR_TAKEN | FE_VOLATILE; } if( sym->flags & SYM_TRY_VOLATILE ) { attr |= FE_MEMORY | FE_VOLATILE; } if( sym->mods & FLAG_VOLATILE ) { attr |= FE_MEMORY | FE_VOLATILE; } else if( sym->mods & FLAG_CONST ) { attr |= FE_CONSTANT; } switch( sym->attribs.declspec ) { case DECLSPEC_DLLIMPORT: if( (attr & FE_IMPORT) || CompFlags.rent ) { attr |= FE_DLLIMPORT; } break; case DECLSPEC_DLLEXPORT: if( sym->attribs.stg_class == SC_NONE ) { attr |= FE_DLLEXPORT; } break; case DECLSPEC_THREAD: attr |= FE_THREAD_DATA; break; } if( sym->attribs.naked ) { attr |= FE_NAKED; } if( sym->attribs.rent ) { //Override on function or r/w data attr |= FE_THREAD_DATA; } return( attr ); }
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 ); }
/* // This section is NOT 8086 and 386 , i.e., // _AXP // _PPC // _MIPS // // pass auxiliary information to back end */ CGPOINTER FEAuxInfo( CGPOINTER req_handle, int request ) { aux_info *inf; auto SYM_ENTRY sym; static hw_reg_set save_set; switch( request ) { case SOURCE_LANGUAGE: return( (CGPOINTER)"C" ); case OBJECT_FILE_NAME: return( (CGPOINTER)ObjFileName() ); case REVISION_NUMBER: return( (CGPOINTER)(pointer_int)II_REVISION ); case AUX_LOOKUP: return( req_handle ); case SOURCE_NAME: if( SrcFName == ModuleName ) { return( (CGPOINTER)FNameFullPath( FNames ) ); } else { return( (CGPOINTER)ModuleName ); } case CALL_CLASS: { static call_class cclass; cclass = GetCallClass( req_handle ); return( (CGPOINTER)&cclass ); } case NEXT_LIBRARY: case LIBRARY_NAME: return( NextLibrary( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT: case IMPORT_NAME: return( NextImport( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT_S: case IMPORT_NAME_S: return( NextImportS( (int)(pointer_int)req_handle, request ) ); case NEXT_ALIAS: case ALIAS_NAME: case ALIAS_SYMBOL: case ALIAS_SUBST_NAME: case ALIAS_SUBST_SYMBOL: return( NextAlias( (int)(pointer_int)req_handle, request ) ); case FREE_SEGMENT: return( NULL ); case TEMP_LOC_NAME: return( (CGPOINTER)(pointer_int)TEMP_LOC_QUIT ); case TEMP_LOC_TELL: return( NULL ); case NEXT_DEPENDENCY: if( CompFlags.emit_dependencies ) return( (CGPOINTER)NextDependency( (FNAMEPTR)req_handle ) ); return( NULL ); case DEPENDENCY_TIMESTAMP: return( (CGPOINTER)getFileDepTimeStamp( (FNAMEPTR)req_handle ) ); case DEPENDENCY_NAME: return( (CGPOINTER)FNameFullPath( (FNAMEPTR)req_handle ) ); default: break; } inf = FindInfo( &sym, req_handle ); switch( request ) { case SAVE_REGS: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } else { sym.mods = 0; } save_set = inf->save; return( (CGPOINTER)&save_set ); case RETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->returns ); case CALL_BYTES: return( (CGPOINTER)inf->code ); case PARM_REGS: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); if( inf->code == NULL && VarFunc( &sym ) ) { return( (CGPOINTER)DefaultVarParms ); } } return( (CGPOINTER)inf->parms ); default: break; } return( NULL ); }
/* // This section is for // 8086 // 386 // // pass auxiliary information to back end */ CGPOINTER FEAuxInfo( CGPOINTER req_handle, int request ) { aux_info *inf; auto SYM_ENTRY sym; static hw_reg_set save_set; switch( request ) { case SOURCE_LANGUAGE: return( (CGPOINTER)"C" ); case STACK_SIZE_8087: return( (CGPOINTER)(pointer_int)Stack87 ); case CODE_GROUP: return( (CGPOINTER)GenCodeGroup ); case DATA_GROUP: return( (CGPOINTER)DataSegName ); case OBJECT_FILE_NAME: return( (CGPOINTER)ObjFileName() ); case REVISION_NUMBER: return( (CGPOINTER)(pointer_int)II_REVISION ); case AUX_LOOKUP: return( req_handle ); case PROEPI_DATA_SIZE: return( (CGPOINTER)(pointer_int)ProEpiDataSize ); case DBG_PREDEF_SYM: return( (CGPOINTER)SymDFAbbr ); case P5_CHIP_BUG_SYM: return( (CGPOINTER)SymChipBug ); case CODE_LABEL_ALIGNMENT: { static unsigned char Alignment[] = { 2, 1, 1 }; if( OptSize == 0 ) Alignment[1] = TARGET_INT; return( (CGPOINTER)Alignment ); } case CLASS_NAME: return( (CGPOINTER)SegClassName( (segment_id)(pointer_int)req_handle ) ); case USED_8087: CompFlags.pgm_used_8087 = 1; return( NULL ); #if _CPU == 386 case P5_PROF_DATA: return( (CGPOINTER)FunctionProfileBlock ); case P5_PROF_SEG: return( (CGPOINTER)(pointer_int)FunctionProfileSegment ); #endif case SOURCE_NAME: if( SrcFName == ModuleName ) { return( (CGPOINTER)FNameFullPath( FNames ) ); } else { return( (CGPOINTER)ModuleName ); } case CALL_CLASS: { static call_class cclass; cclass = GetCallClass( req_handle ); return( (CGPOINTER)&cclass ); } case FREE_SEGMENT: return( NULL ); case NEXT_LIBRARY: case LIBRARY_NAME: return( NextLibrary( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT: case IMPORT_NAME: return( NextImport( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT_S: case IMPORT_NAME_S: return( NextImportS( (int)(pointer_int)req_handle, request ) ); case NEXT_ALIAS: case ALIAS_NAME: case ALIAS_SYMBOL: case ALIAS_SUBST_NAME: case ALIAS_SUBST_SYMBOL: return( NextAlias( (int)(pointer_int)req_handle, request ) ); case TEMP_LOC_NAME: return( (CGPOINTER)(pointer_int)TEMP_LOC_QUIT ); case TEMP_LOC_TELL: return( NULL ); case NEXT_DEPENDENCY: if( CompFlags.emit_dependencies ) return( (CGPOINTER)NextDependency( (FNAMEPTR)req_handle ) ); return( NULL ); case DEPENDENCY_TIMESTAMP: return( (CGPOINTER)getFileDepTimeStamp( (FNAMEPTR)req_handle ) ); case DEPENDENCY_NAME: return( (CGPOINTER)FNameFullPath( (FNAMEPTR)req_handle ) ); case PEGGED_REGISTER: return( (CGPOINTER)SegPeggedReg( (segment_id)(pointer_int)req_handle ) ); default: break; } inf = FindInfo( &sym, req_handle ); switch( request ) { case SAVE_REGS: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } else { sym.mods = 0; } save_set = inf->save; if( sym.mods & FLAG_SAVEREGS ) { HW_CTurnOn( save_set, HW_SEGS ); } #ifdef __SEH__ if( (SYM_HANDLE)req_handle == SymTryInit ) { HW_CTurnOff( save_set, HW_SP ); } #endif return( (CGPOINTER)&save_set ); case RETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->returns ); case CALL_BYTES: return( (CGPOINTER)inf->code ); case PARM_REGS: #ifdef __SEH__ if(( (SYM_HANDLE)req_handle == SymTryInit ) || ( (SYM_HANDLE)req_handle == SymTryFini ) || ( (SYM_HANDLE)req_handle == SymTryUnwind ) || ( (SYM_HANDLE)req_handle == SymExcept )) { return( (CGPOINTER)TryParms ); } #endif if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); if( inf->code == NULL && VarFunc( &sym ) ) { return( (CGPOINTER)DefaultVarParms ); } } return( (CGPOINTER)inf->parms ); case STRETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->streturn ); default: break; } return( NULL ); }
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 ); }
/* // pass auxiliary information to back end */ VOIDPTR FEAuxInfo( CGSYM_HANDLE cgsym_handle, int request ) { SYM_HANDLE sym_handle = cgsym_handle; struct aux_info *inf; auto SYM_ENTRY sym; static hw_reg_set save_set; switch( request ) { case SOURCE_LANGUAGE: return( "C" ); case OBJECT_FILE_NAME: return( (VOIDPTR)ObjFileName( OBJ_EXT ) ); case REVISION_NUMBER: return( (VOIDPTR)II_REVISION ); case AUX_LOOKUP: return( (VOIDPTR)sym_handle ); case SOURCE_NAME: if( SrcFName == ModuleName ) { return( FNameFullPath( FNames ) ); } else { return( ModuleName ); } case CALL_CLASS: GetCallClass( sym_handle ); return( &CallClass ); case NEXT_LIBRARY: case LIBRARY_NAME: return( NextLibrary( (int)sym_handle, request ) ); case NEXT_IMPORT: case IMPORT_NAME: return( NextImport( (int)sym_handle, request ) ); case NEXT_IMPORT_S: case IMPORT_NAME_S: return( NextImportS( (int)sym_handle, request ) ); case NEXT_ALIAS: case ALIAS_NAME: case ALIAS_SYMBOL: case ALIAS_SUBST_NAME: case ALIAS_SUBST_SYMBOL: return( NextAlias( (int)sym_handle, request ) ); case FREE_SEGMENT: return( NULL ); case TEMP_LOC_NAME: return( (char *)TEMP_LOC_QUIT ); case TEMP_LOC_TELL: return( NULL ); case NEXT_DEPENDENCY: /* 03-dec-92 */ if( CompFlags.emit_dependencies ) return( NextDependency( (FNAMEPTR) cgsym_handle ) ); return( NULL ); case DEPENDENCY_TIMESTAMP: return( getFileDepTimeStamp( (FNAMEPTR)cgsym_handle ) ); case DEPENDENCY_NAME: return( FNameFullPath( (FNAMEPTR)cgsym_handle ) ); default: break; } inf = FindInfo( &sym, sym_handle ); switch( request ) { case SAVE_REGS: if( sym_handle != 0 ) { inf = LangInfo( sym.attrib, inf ); } else { sym.attrib = 0; } save_set = inf->save; return( &save_set ); case RETURN_REG: if( sym_handle != 0 ) { inf = LangInfo( sym.attrib, inf ); } return( &inf->returns ); case CALL_BYTES: return( inf->code ); case PARM_REGS: if( sym_handle != 0 ) { inf = LangInfo( sym.attrib, inf ); if( inf->code == NULL && VarFunc( &sym ) ) { return( DefaultVarParms ); } } return( inf->parms ); default: break; } return( NULL ); }
Expression* Expression_parse(const char** expr) { Expression* ret = NULL; Variable* var; Value* val; const char* equals = strchr(*expr, '='); if(equals == NULL) { /* No assignment, just a plain expression. */ return parseExpr(expr); } /* There is an assignment */ /* First, parse the right side of the assignment */ equals++; val = Value_parse(&equals, 0, 0); if(val->type == VAL_ERR) { /* A parse error occurred */ var = VarErr(Error_copy(val->err)); Value_free(val); return Expression_new(var); } if(val->type == VAL_END) { /* Empty input */ Value_free(val); var = VarErr(earlyEnd()); return Expression_new(var); } /* Now parse the left side */ char* name = nextToken(expr); if(name == NULL) { Value_free(val); var = VarErr(syntaxError("No variable to assign to.")); return Expression_new(var); } trimSpaces(expr); if(**expr == '(') { /* Defining a function */ (*expr)++; /* Array of argument names */ unsigned size = 2; char** args = fmalloc(size * sizeof(*args)); unsigned len = 0; /* Add each argument name to the array */ char* arg = nextToken(expr); if(arg == NULL && **expr != ')') { /* Invalid character */ Value_free(val); free(args); free(name); var = VarErr(badChar(**expr)); return Expression_new(var); } trimSpaces(expr); if(arg == NULL) { /* Empty parameter list means function with no args */ free(args); args = NULL; len = 0; } else { /* Loop through each argument in the list */ while(**expr == ',' || **expr == ')') { args[len++] = arg; if(**expr == ')') break; (*expr)++; /* Expand argument array if it's too small */ if(len >= size) { size *= 2; args = frealloc(args, size * sizeof(*args)); } arg = nextToken(expr); if(arg == NULL) { /* Invalid character */ Value_free(val); free(name); /* Free argument names and return */ unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } trimSpaces(expr); } } if(**expr != ')') { /* Invalid character inside argument name list */ Value_free(val); free(name); /* Free argument names and return */ unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } /* Skip closing parenthesis */ (*expr)++; trimSpaces(expr); if(**expr != '=') { Value_free(val); free(name); unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } /* Construct function and return it */ Function* func = Function_new(len, args, val); var = VarFunc(name, func); free(name); ret = Expression_new(var); } else { /* Defining a variable */ if(**expr != '=') { /* In-place manipulation */ BINTYPE bin = BinOp_nextType(expr, 0, 0); /* Still not an equals sign means invalid character */ if(**expr != '=') { Value_free(val); free(name); var = VarErr(badChar(**expr)); return Expression_new(var); } val = ValExpr(BinOp_new(bin, ValVar(name), val)); } var = VarValue(name, val); free(name); ret = Expression_new(var); } return ret; }