#define AUX_MEMALLOC CMemAlloc #define AUX_STRALLOC strsave #define AUX_MEMFREE CMemFree #elif defined( BY_FORTRAN_FRONT_END ) #define AUX_MEMALLOC FMemAlloc #define AUX_STRALLOC FMemAlloc #define AUX_MEMFREE FMemFree #else #error "Unknown front end" #endif #if _INTEL_CPU static hw_reg_set StackParms[] = { HW_D( HW_EMPTY ) }; #if _CPU == 386 static hw_reg_set metaWareParms[] = { HW_D( HW_EMPTY ) }; static hw_reg_set OptlinkParms[] = { HW_D_4( HW_EAX, HW_ECX, HW_EDX, HW_FLTS ), HW_D( HW_EMPTY ) }; static hw_reg_set FastcallParms[] = { HW_D( HW_ECX ), HW_D( HW_EDX ), HW_D( HW_EMPTY ) }; #else
#include "fnovload.h" #include "cgswitch.h" #include "initdefs.h" #include "cginlibs.h" #include "cginimps.h" #include "asmstmt.h" #include "pcheader.h" #include "cgfront.h" #define IS_REGSET(t) (t == T_LEFT_BRACKET || t == T_LEFT_BRACE) static byte_seq *AuxCodeDup( byte_seq *code ); static int GetByteSeq( void ); static hw_reg_set asmRegsSaved = HW_D( HW_FULL ); #define WCPP_ASM // enable assembler #define ASM_BLOCK (64) #define ROUND_ASM_BLOCK(x) ((x+ASM_BLOCK-1) & ~(ASM_BLOCK-1)) static void pragmaInit( // INITIALIZATION FOR PRAGMAS INITFINI* defn ) // - definition { defn = defn; PragInit(); PragmaAuxInfoInit( CompFlags.use_stdcall_at_number );
} else { if( ins->operands[1]->n.size & 1 ) { AddByte( M_CMPSB ); } else { AddByte( M_CMPSW ); if( _IsntTargetModel( USE_32 ) ) AddByte( M_OPND_SIZE ); } } } } static hw_reg_set IndexTab[] = { #define INDICES 8 #define BP_INDEX 5 HW_D( HW_EAX ), HW_D( HW_ECX ), HW_D( HW_EDX ), HW_D( HW_EBX ), HW_D( HW_SP ), HW_D( HW_BP ), HW_D( HW_ESI ), HW_D( HW_EDI ) }; static byte Displacement( signed_32 val, hw_reg_set regs ) /************************************************************/ { if( val == 0 && !HW_COvlap( regs, HW_BP ) ) return( D0 ); if( val <= 127 && val >= -128 ) { AddByte( val & 0xff );
"", // 26 "", // 27 "", // 28 "", // 29 "", // 30 "", // 31 }; /* bitmap for which of the above are Standard */ #define VAR_PARM_FUNCS_ANSI \ ((1<<8) | (1<<9) | (1<<12) | (1<<13) | (1<<14) | (1<<17)) #ifdef __SEH__ #if _CPU == 386 hw_reg_set TryParms[] = { HW_D( HW_EAX ), HW_D( HW_EMPTY ) }; #else hw_reg_set TryParms[] = { HW_D( HW_EMPTY ) }; #endif #endif #if _CPU == 386 extern const alt_inline_funcs FlatAlternates[]; static struct STRUCT_byte_seq( 1 ) FinallyCode = { 1, FALSE, { 0xc3 } /* ret */
* Description: Pragmas specific to x86 targets. * ****************************************************************************/ #include "cvars.h" #include "cgswitch.h" #include "pragdefn.h" #include "pdefn2.h" #include "asmstmt.h" extern struct aux_info *GetLangInfo( type_modifiers flags ); extern TREEPTR CurFuncNode; static hw_reg_set AsmRegsSaved = HW_D( HW_FULL ); static int AsmFuncNum; static struct aux_info AuxInfo; #if _CPU == 386 static hw_reg_set STOSBParms[] = { HW_D( HW_EAX ), HW_D( HW_EDX ), HW_D( HW_ECX ), HW_D( HW_EMPTY ) }; #endif static struct { unsigned f_near : 1; unsigned f_routine_pops : 1; unsigned f_caller_return : 1; unsigned f_8087_returns : 1;
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 ); }