<s> static int access_check ( const char * name , int mode ) { if ( mode == X_OK ) { struct stat st ; if ( stat ( name , & st ) < 0 || S_ISDIR ( st . st_mode ) ) return - 1 ; } return access ( name , mode ) ; } </s>

Check whether NAME can be accessed in MODE . This is like access , except that it never considers directories to be executable .


<s> static char * find_target_compiler ( const char * name ) { bool found = false ; char * * paths = NULL ; unsigned n_paths , i ; char * target_compiler ; const char * collect_gcc = getenv ( "COLLECT_GCC" ) ; const char * gcc_path = dirname ( ASTRDUP ( collect_gcc ) ) ; const char * gcc_exec = basename ( ASTRDUP ( collect_gcc ) ) ; if ( strcmp ( gcc_exec , collect_gcc ) == 0 ) { target_compiler = XDUPVEC ( char , name , strlen ( name ) + 1 ) ; found = true ; goto out ; } target_compiler = concat ( gcc_path , "/" , name , NULL ) ; if ( access_check ( target_compiler , X_OK ) == 0 ) { found = true ; goto out ; } n_paths = parse_env_var ( getenv ( "COMPILER_PATH" ) , & paths ) ; for ( i = 0 ; i < n_paths ; i ++ ) { size_t len = strlen ( paths [ i ] ) + 1 + strlen ( name ) + 1 ; target_compiler = XRESIZEVEC ( char , target_compiler , len ) ; sprintf ( target_compiler , "%s/%s" , paths [ i ] , name ) ; if ( access_check ( target_compiler , X_OK ) == 0 ) { found = true ; break ; } } out : free_array_of_ptrs ( ( void * * ) paths , n_paths ) ; return found ? target_compiler : NULL ; } </s>

Find target compiler using a path from COLLECT_GCC or COMPILER_PATH .


<s> static void free_array_of_ptrs ( void * * ptr , unsigned n ) { unsigned i ; if ( ! ptr ) return ; for ( i = 0 ; i < n ; i ++ ) { if ( ! ptr [ i ] ) break ; free ( ptr [ i ] ) ; } free ( ptr ) ; return ; } </s>

Auxiliary function that frees elements of PTR and PTR itself . N is number of elements to be freed . If PTR is NULL , nothing is freed . If an element is NULL , subsequent elements are not freed .


"extern const void *const __OFFLOAD_TABLE__;\n"

"extern const void *const __offload_image_intelmic_start;\n"

"extern const void *const __offload_image_intelmic_end;\n\n"

"static const void *const __offload_target_data[] = {\n"

"  &__offload_image_intelmic_start, &__offload_image_intelmic_end\n"

"void GOMP_offload_register (const void *, int, const void *);\n"

"void GOMP_offload_unregister (const void *, int, const void *);\n\n"

"  GOMP_offload_register (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"

"  GOMP_offload_unregister (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"

Generates object file with the host side descriptor .


"extern const void *const __offload_funcs_end[];\n"

"extern const void *const __offload_vars_end[];\n\n"

"const void *const __offload_func_table[0]\n"

"__attribute__ ((__used__, visibility (\"hidden\"),\n"

"section (\".gnu.offload_funcs\"))) = { };\n\n"

"const void *const __offload_var_table[0]\n"

"section (\".gnu.offload_vars\"))) = { };\n\n"

"const void *const __OFFLOAD_TARGET_TABLE__[]\n"

"__attribute__ ((__used__, visibility (\"hidden\"))) = {\n"

"  &__offload_func_table, &__offload_funcs_end,\n"

"  &__offload_var_table, &__offload_vars_end\n"

"void target_register_lib (const void *);\n\n"

"  target_register_lib (__OFFLOAD_TARGET_TABLE__);\n"

Generates object file with the descriptor for the target library .


"const void *const __offload_funcs_end[0]\n"

"const void *const __offload_vars_end[0]\n"

"section (\".gnu.offload_vars\"))) = { };\n"

Generates object file with __offload_ * _end symbols for the target library .


<s>
void
maybe_unlink
(
const
char
*
file
)
{
if
(
!
save_temps
)
{
if
(
unlink_if_ordinary
(
file
)
&&
errno
!=
ENOENT
)
fatal_error
(
input_location
,
"deleting file %s: %m"
,
file
)
;
}
else
if
(
verbose
)
fprintf
(
stderr
,
"[Leaving %s]\n"
,
file
)
;
}
</s>

Unlink a temporary file unless requested otherwise .

i386
"deleting file %s: %m"
"[Leaving %s]\n"


<s> static unsigned parse_env_var ( const char * str , char * * * pvalues ) { const char * curval , * nextval ; char * * values ; unsigned num = 1 , i ; curval = strchr ( str , ':' ) ; while ( curval ) { num ++ ; curval = strchr ( curval + 1 , ':' ) ; } values = ( char * * ) xmalloc ( num * sizeof ( char * ) ) ; curval = str ; nextval = strchr ( curval , ':' ) ; if ( nextval == NULL ) nextval = strchr ( curval , '\0' ) ; for ( i = 0 ; i < num ; i ++ ) { int l = nextval - curval ; values [ i ] = ( char * ) xmalloc ( l + 1 ) ; memcpy ( values [ i ] , curval , l ) ; values [ i ] [ l ] = 0 ; curval = nextval + 1 ; nextval = strchr ( curval , ':' ) ; if ( nextval == NULL ) nextval = strchr ( curval , '\0' ) ; } * pvalues = values ; return num ; } </s>

Parse STR , saving found tokens into PVALUES and return their number . Tokens are assumed to be delimited by ' : ' .


<s> void tool_cleanup ( bool from_signal ATTRIBUTE_UNUSED ) { for ( int i = 0 ; i < num_temps ; i ++ ) maybe_unlink ( temp_files [ i ] ) ; } </s>


<s> static void xputenv ( const char * string ) { if ( verbose ) fprintf ( stderr , "%s\n" , string ) ; putenv ( CONST_CAST ( char * , string ) ) ; } </s>

Add or change the value of an environment variable , outputting the change to standard error if in verbose mode .


<s> static tree gen_regparm_prefix ( tree decl , unsigned nregs ) { unsigned total = 0 ; const char * asmname = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; char * newsym ; tree formal_type = TYPE_ARG_TYPES ( TREE_TYPE ( decl ) ) ; if ( formal_type != NULL_TREE ) { if ( TREE_VALUE ( tree_last ( formal_type ) ) != void_type_node ) return NULL_TREE ; while ( TREE_VALUE ( formal_type ) != void_type_node && COMPLETE_TYPE_P ( TREE_VALUE ( formal_type ) ) ) { unsigned parm_size = TREE_INT_CST_LOW ( TYPE_SIZE ( TREE_VALUE ( formal_type ) ) ) ; parm_size = ( ( parm_size + PARM_BOUNDARY - 1 ) / PARM_BOUNDARY * PARM_BOUNDARY ) ; total += parm_size ; formal_type = TREE_CHAIN ( formal_type ) ; } } if ( nregs > total / BITS_PER_WORD ) nregs = total / BITS_PER_WORD ; gcc_assert ( nregs <= 9 ) ; newsym = alloca ( 3 + strlen ( asmname ) + 1 ) ; return get_identifier_with_length ( newsym , sprintf ( newsym , "_%u@%s" , nregs , asmname ) ) ; } </s>

Return string which is the former assembler name modified with an _n @ prefix where n represents the number of arguments passed in registers


<s> static tree gen_stdcall_or_fastcall_decoration ( tree decl , char prefix ) { unsigned total = 0 ; const char * asmname = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; char * newsym ; tree formal_type = TYPE_ARG_TYPES ( TREE_TYPE ( decl ) ) ; if ( formal_type != NULL_TREE ) { if ( TREE_VALUE ( tree_last ( formal_type ) ) != void_type_node ) return NULL_TREE ; while ( TREE_VALUE ( formal_type ) != void_type_node && COMPLETE_TYPE_P ( TREE_VALUE ( formal_type ) ) ) { unsigned parm_size = TREE_INT_CST_LOW ( TYPE_SIZE ( TREE_VALUE ( formal_type ) ) ) ; parm_size = ( ( parm_size + PARM_BOUNDARY - 1 ) / PARM_BOUNDARY * PARM_BOUNDARY ) ; total += parm_size ; formal_type = TREE_CHAIN ( formal_type ) ; } } newsym = alloca ( 1 + strlen ( asmname ) + 1 + 10 + 1 ) ; return get_identifier_with_length ( newsym , sprintf ( newsym , "%c%s@%u" , prefix , asmname , total / BITS_PER_UNIT ) ) ; } </s>

Return string which is the former assembler name modified with an underscore prefix and a suffix consisting of an atsign ( @ ) followed by the number of bytes of arguments


<s> const char * i386_nlm_strip_name_encoding ( const char * str ) { const char * name = default_strip_name_encoding ( str ) ; if ( * str != '*' && ( * name == '_' || * name == '@' ) ) { const char * p = strchr ( name + 1 , '@' ) ; if ( p ) { ++ name ; if ( ISDIGIT ( p [ 1 ] ) ) name = ggc_alloc_string ( name , p - name ) ; else { gcc_assert ( ISDIGIT ( * name ) ) ; name ++ ; gcc_assert ( name == p ) ; } } } return name ; } </s>

Strip the stdcall/fastcall/regparm pre-/suffix .


<s> static void winnt_d_os_builtins ( void ) { d_add_builtin_version ( "Windows" ) ; d_add_builtin_version ( "MinGW" ) ; if ( TARGET_64BIT && ix86_abi == MS_ABI ) d_add_builtin_version ( "Win64" ) ; else if ( ! TARGET_64BIT ) d_add_builtin_version ( "Win32" ) ; d_add_builtin_version ( "CRuntime_Microsoft" ) ; } </s>

Implement TARGET_D_OS_VERSIONS for Windows targets .


<s> static tree winnt_d_handle_target_object_format ( void ) { const char * objfmt = "coff" ; return build_string_literal ( strlen ( objfmt ) + 1 , objfmt ) ; } </s>

Handle a call to ` __traits ( getTargetInfo , `` objectFormat '' ) ' .


<s> static void winnt_d_os_builtins ( void ) { d_add_builtin_version ( "Windows" ) ; EXTRA_TARGET_D_OS_VERSIONS ( ) ; } </s>


<s> static void winnt_d_register_target_info ( void ) { const struct d_target_info_spec handlers [ ] = { { "objectFormat" , winnt_d_handle_target_object_format } , { NULL , NULL } , } ; d_add_target_info_handlers ( handlers ) ; } </s>

Implement TARGET_D_REGISTER_OS_TARGET_INFO for Windows targets .


<s> void i386_pe_seh_unwind_emit ( FILE * asm_out_file , rtx_insn * insn ) { rtx note , pat ; bool handled_one = false ; struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; seh = cfun -> machine -> seh ; if ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_SWITCH_TEXT_SECTIONS ) { rtx_insn * prev = prev_active_insn ( insn ) ; if ( prev && ! insn_nothrow_p ( prev ) ) fputs ( "\tnop\n" , asm_out_file ) ; fputs ( "\t.seh_endproc\n" , asm_out_file ) ; seh -> in_cold_section = true ; return ; } if ( NOTE_P ( insn ) || ! RTX_FRAME_RELATED_P ( insn ) ) return ; if ( seh -> after_prologue ) return ; for ( note = REG_NOTES ( insn ) ; note ; note = XEXP ( note , 1 ) ) { switch ( REG_NOTE_KIND ( note ) ) { case REG_FRAME_RELATED_EXPR : pat = XEXP ( note , 0 ) ; goto found ; case REG_CFA_DEF_CFA : case REG_CFA_EXPRESSION : gcc_unreachable ( ) ; break ; case REG_CFA_REGISTER : gcc_unreachable ( ) ; case REG_CFA_ADJUST_CFA : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) { pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == PARALLEL ) pat = XVECEXP ( pat , 0 , 0 ) ; } seh_cfa_adjust_cfa ( asm_out_file , seh , pat ) ; handled_one = true ; break ; case REG_CFA_OFFSET : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) pat = single_set ( insn ) ; seh_cfa_offset ( asm_out_file , seh , pat ) ; handled_one = true ; break ; default : break ; } } if ( handled_one ) return ; pat = PATTERN ( insn ) ; found : seh_frame_related_expr ( asm_out_file , seh , pat ) ; } </s>

This function looks at a single insn and emits any SEH directives required for unwind of this insn .


<s> static tree associated_type ( tree decl ) { return ( DECL_CONTEXT ( decl ) && TYPE_P ( DECL_CONTEXT ( decl ) ) ) ? DECL_CONTEXT ( decl ) : NULL_TREE ; } </s>

Return the type that we should use to determine if DECL is imported or exported .


<s> static tree gen_stdcall_or_fastcall_suffix ( tree decl , bool fastcall ) { int total = 0 ; const char * asmname = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; char * newsym ; char * p ; tree formal_type ; if ( * asmname == '*' || strchr ( asmname , '@' ) ) return DECL_ASSEMBLER_NAME ( decl ) ; formal_type = TYPE_ARG_TYPES ( TREE_TYPE ( decl ) ) ; if ( formal_type != NULL_TREE ) { if ( TREE_VALUE ( tree_last ( formal_type ) ) != void_type_node ) return DECL_ASSEMBLER_NAME ( decl ) ; while ( TREE_VALUE ( formal_type ) != void_type_node && COMPLETE_TYPE_P ( TREE_VALUE ( formal_type ) ) ) { int parm_size = TREE_INT_CST_LOW ( TYPE_SIZE ( TREE_VALUE ( formal_type ) ) ) ; parm_size = ( ( parm_size + PARM_BOUNDARY - 1 ) / PARM_BOUNDARY * PARM_BOUNDARY ) ; total += parm_size ; formal_type = TREE_CHAIN ( formal_type ) ; \ } } newsym = alloca ( 1 + strlen ( asmname ) + 1 + 8 + 1 ) ; p = newsym ; if ( fastcall ) * p ++ = FASTCALL_PREFIX ; sprintf ( p , "%s@%d" , asmname , total / BITS_PER_UNIT ) ; return get_identifier ( newsym ) ; } </s>

Return string which is the former assembler name modified with a suffix consisting of an atsign ( @ ) followed by the number of bytes of arguments . If FASTCALL is true , also add the FASTCALL_PREFIX .


<s> void i386_pe_declare_function_type ( FILE * file , const char * name , int public ) { fprintf ( file , "\t.def\t" ) ; assemble_name ( file , name ) ; fprintf ( file , ";\t.scl\t%d;\t.type\t%d;\t.endef\n" , public ? ( int ) C_EXT : ( int ) C_STAT , ( int ) DT_FCN << N_BTSHFT ) ; } </s>

Mark a function appropriately . This should only be called for functions for which we are not emitting COFF debugging information . FILE is the assembler output file , NAME is the name of the function , and PUBLIC is nonzero if the function is globally visible .


<s> int i386_pe_dllexport_name_p ( const char * symbol ) { return ( strncmp ( DLL_EXPORT_PREFIX , symbol , strlen ( DLL_EXPORT_PREFIX ) ) == 0 ) ; } </s>

Return nonzero if SYMBOL is marked as being dllexport 'd .


<s> static bool i386_pe_dllexport_p ( tree decl ) { if ( TREE_CODE ( decl ) != VAR_DECL && TREE_CODE ( decl ) != FUNCTION_DECL ) return false ; if ( lookup_attribute ( "dllexport" , DECL_ATTRIBUTES ( decl ) ) ) return true ; if ( associated_type ( decl ) && lookup_attribute ( "dllexport" , TYPE_ATTRIBUTES ( associated_type ( decl ) ) ) ) return i386_pe_type_dllexport_p ( decl ) ; return false ; } </s>

Return true if DECL is a dllexport 'd object .


<s> int i386_pe_dllimport_name_p ( const char * symbol ) { return ( strncmp ( DLL_IMPORT_PREFIX , symbol , strlen ( DLL_IMPORT_PREFIX ) ) == 0 ) ; } </s>

Return nonzero if SYMBOL is marked as being dllimport 'd .


<s> static bool i386_pe_dllimport_p ( tree decl ) { if ( TREE_CODE ( decl ) != VAR_DECL && TREE_CODE ( decl ) != FUNCTION_DECL ) return false ; if ( lookup_attribute ( "dllimport" , DECL_ATTRIBUTES ( decl ) ) ) return true ; if ( associated_type ( decl ) && lookup_attribute ( "dllimport" , TYPE_ATTRIBUTES ( associated_type ( decl ) ) ) ) return i386_pe_type_dllimport_p ( decl ) ; return false ; } </s>

Return non-zero if DECL is a dllimport 'd object .


<s> void i386_pe_encode_section_info ( tree decl , rtx rtl , int first ) { default_encode_section_info ( decl , rtl , first ) ; if ( first && TREE_CODE ( decl ) == FUNCTION_DECL ) { tree type_attributes = TYPE_ATTRIBUTES ( TREE_TYPE ( decl ) ) ; tree newid = NULL_TREE ; if ( lookup_attribute ( "stdcall" , type_attributes ) ) newid = gen_stdcall_or_fastcall_suffix ( decl , false ) ; else if ( lookup_attribute ( "fastcall" , type_attributes ) ) newid = gen_stdcall_or_fastcall_suffix ( decl , true ) ; if ( newid != NULL_TREE ) { rtx rtlname = XEXP ( rtl , 0 ) ; if ( GET_CODE ( rtlname ) == MEM ) rtlname = XEXP ( rtlname , 0 ) ; XSTR ( rtlname , 0 ) = IDENTIFIER_POINTER ( newid ) ; change_decl_assembler_name ( decl , newid ) ; } } if ( i386_pe_dllexport_p ( decl ) ) i386_pe_mark_dllexport ( decl ) ; else if ( i386_pe_dllimport_p ( decl ) ) i386_pe_mark_dllimport ( decl ) ; else gcc_assert ( ! ( ( TREE_CODE ( decl ) == FUNCTION_DECL || TREE_CODE ( decl ) == VAR_DECL ) && rtl != NULL_RTX && GET_CODE ( rtl ) == MEM && GET_CODE ( XEXP ( rtl , 0 ) ) == MEM && GET_CODE ( XEXP ( XEXP ( rtl , 0 ) , 0 ) ) == SYMBOL_REF && i386_pe_dllimport_name_p ( XSTR ( XEXP ( XEXP ( rtl , 0 ) , 0 ) , 0 ) ) ) ) ; } </s>

Cover function to implement ENCODE_SECTION_INFO .


<s>
void
i386_pe_file_end
(
void
)
{
struct
extern_list
*
p
;
ix86_file_end
(
)
;
for
(
p
=
extern_head
;
p
!=
;
p
=
p
->
next
)
{
tree
decl
;
decl
=
p
->
decl
;
if
(
!
TREE_ASM_WRITTEN
(
decl
)
&&
TREE_SYMBOL_REFERENCED
(
DECL_ASSEMBLER_NAME
(
decl
)
)
)
{
TREE_ASM_WRITTEN
(
decl
)
=
1
;
i386_pe_declare_function_type
(
asm_out_file
,
p
->
name
,
TREE_PUBLIC
(
decl
)
)
;
}
}
if
(
export_head
)
{
struct
export_list
*
q
;
drectve_section
(
)
;
for
(
q
=
export_head
;
q
!=
;
q
=
q
->
next
)
{
fprintf
(
asm_out_file
,
"\t.ascii \" -export:%s%s\"\n"
,
i386_pe_strip_name_encoding
(
q
->
name
)
,
(
q
->
is_data
)
",data"
:
""
)
;
}
}
}
</s>

This is called at the end of assembly . For each external function which has not been defined , we output a declaration now . We also output the .drectve section .


"inconsistent dll linkage for %q+D, dllexport assumed"

Mark a DECL as being dllexport 'd . Note that we override the previous setting ( e.g . : dllimport ) .


"%qs declared as both exported to and imported from a DLL"


<s> void i386_pe_record_exported_symbol ( const char * name , int is_data ) { struct export_list * p ; p = ( struct export_list * ) ggc_alloc ( sizeof * p ) ; p -> next = export_head ; p -> name = name ; p -> is_data = is_data ; export_head = p ; } </s>

Assemble an export symbol entry . We need to keep a list of these , so that we can output the export list at the end of the assembly . We used to output these export symbols in each function , but that causes problems with GNU ld when the sections are linkonce .


<s> void i386_pe_record_external_function ( tree decl , const char * name ) { struct extern_list * p ; p = ( struct extern_list * ) ggc_alloc ( sizeof * p ) ; p -> next = extern_head ; p -> decl = decl ; p -> name = name ; extern_head = p ; } </s>

Assemble an external function reference . We need to keep a list of these , so that we can output the function types at the end of the assembly . We ca n't output the types now , because we might see a definition of the function later on and emit debugging information for it then .


<s> const char * i386_pe_strip_name_encoding ( const char * str ) { if ( strncmp ( str , DLL_IMPORT_PREFIX , strlen ( DLL_IMPORT_PREFIX ) ) == 0 ) str += strlen ( DLL_IMPORT_PREFIX ) ; else if ( strncmp ( str , DLL_EXPORT_PREFIX , strlen ( DLL_EXPORT_PREFIX ) ) == 0 ) str += strlen ( DLL_EXPORT_PREFIX ) ; if ( * str == '*' ) str += 1 ; return str ; } </s>

Strip only the leading encoding , leaving the stdcall suffix and fastcall prefix if it exists .


<s> const char * i386_pe_strip_name_encoding_full ( const char * str ) { const char * p ; const char * name = i386_pe_strip_name_encoding ( str ) ; if ( * name == '@' ) name ++ ; p = strchr ( name , '@' ) ; if ( p ) return ggc_alloc_string ( name , p - name ) ; return name ; } </s>

Also strip the fastcall prefix and stdcall suffix .


<s> void i386_pe_unique_section ( tree decl , int reloc ) { int len ; const char * name , * prefix ; char * string ; name = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; name = i386_pe_strip_name_encoding_full ( name ) ; if ( TREE_CODE ( decl ) == FUNCTION_DECL ) prefix = ".text$" ; else if ( decl_readonly_section ( decl , reloc ) ) prefix = ".rdata$" ; else prefix = ".data$" ; len = strlen ( name ) + strlen ( prefix ) ; string = alloca ( len + 1 ) ; sprintf ( string , "%s%s" , prefix , name ) ; DECL_SECTION_NAME ( decl ) = build_string ( len , string ) ; } </s>


<s> bool i386_pe_valid_dllimport_attribute_p ( tree decl ) { if ( TARGET_NOP_FUN_DLLIMPORT && TREE_CODE ( decl ) == FUNCTION_DECL ) return false ; return true ; } </s>

Handle the -mno-fun-dllimport target switch .


"%qs attribute applies only to initialized variables"

Handle a `` selectany '' attribute ; arguments as in struct attribute_spec.handler .


"%qs attribute only applies to variables"

Handle a `` shared '' attribute ; arguments as in struct attribute_spec.handler .


<s> inline bool wrapped_symbol_hasher :: equal ( const value_type * x , const compare_type * y ) { return ! strcmp ( x , y ) ; } </s>


<s> inline hashval_t wrapped_symbol_hasher :: hash ( const value_type * v ) { return htab_hash_string ( v ) ; } </s>

Hash function for builtin functions with up to 3 arguments and a return type .


<s> static const char * i386_find_on_wrapper_list ( const char * target ) { static char first_time = 1 ; static hash_table < wrapped_symbol_hasher > * wrappers ; if ( first_time ) { static char wrapper_list_buffer [ ] = CXX_WRAP_SPEC_LIST ; char * bufptr ; wrappers = new hash_table < wrapped_symbol_hasher > ( 8 ) ; for ( bufptr = wrapper_list_buffer ; * bufptr ; ++ bufptr ) { char * found = NULL ; if ( ISSPACE ( * bufptr ) ) continue ; if ( * bufptr == '_' ) found = bufptr ; while ( * bufptr && ! ISSPACE ( * bufptr ) ) ++ bufptr ; if ( * bufptr ) * bufptr = 0 ; if ( found ) * wrappers -> find_slot ( found , INSERT ) = found ; } first_time = 0 ; } return wrappers -> find ( target ) ; } </s>

Search for a function named TARGET in the list of library wrappers we are using , returning a pointer to it if found or NULL if not . This function might be called on quite a few symbols , and we only have the list of names of wrapped functions available to us as a spec string , so first time round we lazily initialise a hash table to make things quicker .


<s>
void
i386_pe_asm_output_aligned_decl_common
(
FILE
*
stream
,
tree
decl
,
const
char
*
name
,
HOST_WIDE_INT
size
,
HOST_WIDE_INT
align
)
{
HOST_WIDE_INT
rounded
;
rounded
=
size
size
:
1
;
rounded
+=
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
1
;
rounded
=
(
rounded
/
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
*
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
)
;
i386_pe_maybe_record_exported_symbol
(
decl
,
name
,
1
)
;
fprintf
(
stream
,
"\t.comm\t"
)
;
assemble_name
(
stream
,
name
)
;
if
(
use_pe_aligned_common
)
fprintf
(
stream
,
", "
HOST_WIDE_INT_PRINT_DEC
", %d\n"
,
size
size
:
(
HOST_WIDE_INT
)
1
,
exact_log2
(
align
)
exact_log2
(
CHAR_BIT
)
)
;
else
fprintf
(
stream
,
", "
HOST_WIDE_INT_PRINT_DEC
"\t"
ASM_COMMENT_START
" "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
rounded
,
size
)
;
}
</s>

Beware , DECL may be NULL if compile_file ( ) is emitting the LTO marker .


"%q+D:'selectany' attribute applies only to "


<s> void i386_pe_seh_end_prologue ( FILE * f ) { struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; if ( cfun -> is_thunk ) return ; seh = cfun -> machine -> seh ; XDELETE ( seh ) ; cfun -> machine -> seh = NULL ; fputs ( "\t.seh_endprologue\n" , f ) ; } </s>

Emit an assembler directive for the end of the prologue .


<s> static void i386_pe_seh_fini ( FILE * f ) { if ( ! TARGET_SEH ) return ; if ( cfun -> is_thunk ) return ; fputs ( "\t.seh_endproc\n" , f ) ; } </s>

Emit an assembler directive for the end of the function .


<s> void i386_pe_seh_unwind_emit ( FILE * asm_out_file , rtx_insn * insn ) { rtx note , pat ; bool handled_one = false ; struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; seh = cfun -> machine -> seh ; if ( seh == NULL ) return ; if ( NOTE_P ( insn ) || ! RTX_FRAME_RELATED_P ( insn ) ) return ; for ( note = REG_NOTES ( insn ) ; note ; note = XEXP ( note , 1 ) ) { switch ( REG_NOTE_KIND ( note ) ) { case REG_FRAME_RELATED_EXPR : pat = XEXP ( note , 0 ) ; goto found ; case REG_CFA_DEF_CFA : case REG_CFA_EXPRESSION : gcc_unreachable ( ) ; break ; case REG_CFA_REGISTER : gcc_unreachable ( ) ; case REG_CFA_ADJUST_CFA : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) { pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == PARALLEL ) pat = XVECEXP ( pat , 0 , 0 ) ; } seh_cfa_adjust_cfa ( asm_out_file , seh , pat ) ; handled_one = true ; break ; case REG_CFA_OFFSET : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) pat = single_set ( insn ) ; seh_cfa_offset ( asm_out_file , seh , pat ) ; handled_one = true ; break ; default : break ; } } if ( handled_one ) return ; pat = PATTERN ( insn ) ; found : seh_frame_related_expr ( asm_out_file , seh , pat ) ; } </s>

This function looks at a single insn and emits any SEH directives required for unwind of this insn .


"%qE attribute applies only to initialized variables"


<s> static void seh_emit_push ( FILE * f , struct seh_frame_state * seh , rtx reg ) { unsigned int regno = REGNO ( reg ) ; gcc_checking_assert ( GENERAL_REGNO_P ( regno ) ) ; seh -> sp_offset += UNITS_PER_WORD ; if ( seh -> cfa_reg == stack_pointer_rtx ) seh -> cfa_offset += UNITS_PER_WORD ; fputs ( "\t.seh_pushreg\t" , f ) ; print_reg ( reg , 0 , f ) ; fputc ( '\n' , f ) ; } </s>

Emit an assembler directive to save REG via a PUSH .


<s>
static
void
seh_emit_save
(
FILE
*
f
,
struct
seh_frame_state
*
seh
,
rtx
reg
,
HOST_WIDE_INT
cfa_offset
)
{
unsigned
int
regno
=
REGNO
(
reg
)
;
HOST_WIDE_INT
offset
;
gcc_assert
(
seh
->
sp_offset
>=
cfa_offset
)
;
offset
=
seh
->
sp_offset
cfa_offset
;
fputs
(
(
SSE_REGNO_P
(
regno
)
"\t.seh_savexmm\t"
:
GENERAL_REGNO_P
(
regno
)
"\t.seh_savereg\t"
:
(
gcc_unreachable
(
)
,
""
)
)
,
f
)
;
print_reg
(
reg
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
</s>

Emit an assembler directive to save REG at CFA - CFA_OFFSET .


<s>
void
i386_pe_seh_cold_init
(
FILE
*
f
,
const
char
*
name
)
{
struct
seh_frame_state
*
seh
;
HOST_WIDE_INT
alloc_offset
,
offset
;
if
(
!
TARGET_SEH
)
return
;
if
(
cfun
->
is_thunk
)
return
;
seh
=
cfun
->
machine
->
seh
;
fputs
(
"\t.seh_proc\t"
,
f
)
;
assemble_name
(
f
,
name
)
;
fputc
(
'\n'
,
f
)
;
if
(
crtl
->
accesses_prior_frames
)
alloc_offset
=
seh
->
cfa_offset
;
else
alloc_offset
=
seh
->
sp_offset
;
offset
=
alloc_offset
INCOMING_FRAME_SP_OFFSET
;
if
(
offset
>
0
&&
offset
<
SEH_MAX_FRAME_SIZE
)
fprintf
(
f
,
"\t.seh_stackalloc\t"
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
for
(
int
regno
=
0
;
regno
<
FIRST_PSEUDO_REGISTER
;
regno
++
)
if
(
seh
->
reg_offset
[
regno
]
>
0
)
{
fputs
(
(
SSE_REGNO_P
(
regno
)
"\t.seh_savexmm\t"
:
GENERAL_REGNO_P
(
regno
)
"\t.seh_savereg\t"
:
(
gcc_unreachable
(
)
,
""
)
)
,
f
)
;
print_reg
(
gen_rtx_REG
(
DImode
,
regno
)
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
alloc_offset
seh
->
reg_offset
[
regno
]
)
;
}
if
(
seh
->
cfa_reg
!=
stack_pointer_rtx
)
{
offset
=
alloc_offset
seh
->
cfa_offset
;
gcc_assert
(
(
offset
&
15
)
==
0
)
;
gcc_assert
(
IN_RANGE
(
offset
,
0
,
240
)
)
;
fputs
(
"\t.seh_setframe\t"
,
f
)
;
print_reg
(
seh
->
cfa_reg
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
if
(
crtl
->
accesses_prior_frames
)
{
offset
=
seh
->
sp_offset
alloc_offset
;
if
(
offset
>
0
&&
offset
<
SEH_MAX_FRAME_SIZE
)
fprintf
(
f
,
"\t.seh_stackalloc\t"
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
fputs
(
"\t.seh_endprologue\n"
,
f
)
;
}
</s>

Emit assembler directives to reconstruct the SEH state .


<s> static tree associated_type ( tree decl ) { return ( DECL_CONTEXT ( decl ) && TYPE_P ( DECL_CONTEXT ( decl ) ) ? DECL_CONTEXT ( decl ) : NULL_TREE ) ; } </s>

Return the type that we should use to determine if DECL is imported or exported .


<s> static tree gen_stdcall_or_fastcall_suffix ( tree decl , tree id , bool fastcall ) { HOST_WIDE_INT total = 0 ; const char * old_str = IDENTIFIER_POINTER ( id != NULL_TREE ? id : DECL_NAME ( decl ) ) ; char * new_str , * p ; tree type = TREE_TYPE ( DECL_ORIGIN ( decl ) ) ; tree arg ; function_args_iterator args_iter ; gcc_assert ( TREE_CODE ( decl ) == FUNCTION_DECL ) ; if ( prototype_p ( type ) ) { if ( stdarg_p ( type ) ) return NULL_TREE ; FOREACH_FUNCTION_ARGS ( type , arg , args_iter ) { HOST_WIDE_INT parm_size ; HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT ; if ( ! COMPLETE_TYPE_P ( arg ) ) break ; parm_size = int_size_in_bytes ( arg ) ; if ( parm_size < 0 ) break ; parm_size = ( ( parm_size + parm_boundary_bytes - 1 ) / parm_boundary_bytes * parm_boundary_bytes ) ; total += parm_size ; } } p = new_str = XALLOCAVEC ( char , 1 + strlen ( old_str ) + 1 + 8 + 1 ) ; if ( fastcall ) * p ++ = FASTCALL_PREFIX ; sprintf ( p , "%s@" HOST_WIDE_INT_PRINT_DEC , old_str , total ) ; return get_identifier ( new_str ) ; } </s>

Return string which is the former assembler name modified with a suffix consisting of an atsign ( @ ) followed by the number of bytes of arguments . If FASTCALL is true , also add the FASTCALL_PREFIX .


<s> static const char * i386_find_on_wrapper_list ( const char * target ) { static char first_time = 1 ; static hash_table < nofree_string_hash > * wrappers ; if ( first_time ) { static char wrapper_list_buffer [ ] = CXX_WRAP_SPEC_LIST ; char * bufptr ; wrappers = new hash_table < nofree_string_hash > ( 8 ) ; for ( bufptr = wrapper_list_buffer ; * bufptr ; ++ bufptr ) { char * found = NULL ; if ( ISSPACE ( * bufptr ) ) continue ; if ( * bufptr == '_' ) found = bufptr ; while ( * bufptr && ! ISSPACE ( * bufptr ) ) ++ bufptr ; if ( * bufptr ) * bufptr = 0 ; if ( found ) * wrappers -> find_slot ( found , INSERT ) = found ; } first_time = 0 ; } return wrappers -> find ( target ) ; } </s>


<s>
void
i386_pe_asm_output_aligned_decl_common
(
FILE
*
stream
,
tree
decl
,
const
char
*
name
,
HOST_WIDE_INT
size
,
HOST_WIDE_INT
align
)
{
HOST_WIDE_INT
rounded
;
rounded
=
size
size
:
1
;
rounded
+=
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
1
;
rounded
=
(
rounded
/
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
*
(
BIGGEST_ALIGNMENT
/
BITS_PER_UNIT
)
)
;
i386_pe_maybe_record_exported_symbol
(
decl
,
name
,
1
)
;
fprintf
(
stream
,
"\t.comm\t"
)
;
assemble_name
(
stream
,
name
)
;
if
(
use_pe_aligned_common
)
fprintf
(
stream
,
", "
HOST_WIDE_INT_PRINT_DEC
", %d\n"
,
size
size
:
HOST_WIDE_INT_1
,
exact_log2
(
align
)
exact_log2
(
CHAR_BIT
)
)
;
else
fprintf
(
stream
,
", "
HOST_WIDE_INT_PRINT_DEC
"\t"
ASM_COMMENT_START
" "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
rounded
,
size
)
;
}
</s>


<s>
void
i386_pe_assemble_visibility
(
tree
decl
,
int
)
{
if
(
!
decl
||
!
lookup_attribute
(
"visibility"
,
DECL_ATTRIBUTES
(
decl
)
)
)
return
;
if
(
!
DECL_ARTIFICIAL
(
decl
)
)
warning
(
OPT_Wattributes
,
"visibility attribute not supported "
"in this configuration; ignored"
)
;
}
</s>

Emit an assembler directive to set symbol for DECL visibility to the visibility type VIS , which must not be VISIBILITY_DEFAULT . As for PE there is no hidden support in gas , we just warn for user-specified visibility attributes .

i386
"visibility"
"visibility attribute not supported "
"in this configuration; ignored"


<s> void i386_pe_declare_function_type ( FILE * file , const char * name , int pub ) { fprintf ( file , "\t.def\t" ) ; assemble_name ( file , name ) ; fprintf ( file , ";\t.scl\t%d;\t.type\t%d;\t.endef\n" , pub ? ( int ) C_EXT : ( int ) C_STAT , ( int ) DT_FCN << N_BTSHFT ) ; } </s>

Mark a function appropriately . This should only be called for functions for which we are not emitting COFF debugging information . FILE is the assembler output file , NAME is the name of the function , and PUBLIC is nonzero if the function is globally visible .


<s> static bool i386_pe_determine_dllexport_p ( tree decl ) { if ( TREE_CODE ( decl ) != VAR_DECL && TREE_CODE ( decl ) != FUNCTION_DECL ) return false ; if ( ! TREE_PUBLIC ( decl ) ) return false ; if ( TREE_CODE ( decl ) == FUNCTION_DECL && DECL_DECLARED_INLINE_P ( decl ) && ! flag_keep_inline_dllexport ) return false ; if ( lookup_attribute ( "dllexport" , DECL_ATTRIBUTES ( decl ) ) ) return true ; return false ; } </s>

Return true if DECL should be a dllexport 'd object .


"definition of static data member %q+D of "

Return true if DECL should be a dllimport 'd object .


<s> void i386_pe_encode_section_info ( tree decl , rtx rtl , int first ) { rtx symbol ; int flags ; default_encode_section_info ( decl , rtl , first ) ; if ( ! MEM_P ( rtl ) ) return ; symbol = XEXP ( rtl , 0 ) ; gcc_assert ( GET_CODE ( symbol ) == SYMBOL_REF ) ; switch ( TREE_CODE ( decl ) ) { case FUNCTION_DECL : case VAR_DECL : break ; default : return ; } flags = ( SYMBOL_REF_FLAGS ( symbol ) & ~ ( SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT ) ) ; if ( i386_pe_determine_dllexport_p ( decl ) ) flags |= SYMBOL_FLAG_DLLEXPORT ; else if ( i386_pe_determine_dllimport_p ( decl ) ) flags |= SYMBOL_FLAG_DLLIMPORT ; SYMBOL_REF_FLAGS ( symbol ) = flags ; } </s>

Cover function to implement ENCODE_SECTION_INFO .


<s>
void
i386_pe_file_end
(
void
)
{
struct
extern_list
*
p
;
for
(
p
=
extern_head
;
p
!=
;
p
=
p
->
next
)
{
tree
decl
;
decl
=
p
->
decl
;
if
(
!
TREE_ASM_WRITTEN
(
decl
)
&&
TREE_SYMBOL_REFERENCED
(
DECL_ASSEMBLER_NAME
(
decl
)
)
)
{
const
char
*
realsym
=
i386_find_on_wrapper_list
(
p
->
name
)
;
if
(
realsym
)
i386_pe_declare_function_type
(
asm_out_file
,
concat
(
"__real_"
,
realsym
,
)
,
TREE_PUBLIC
(
decl
)
)
;
TREE_ASM_WRITTEN
(
decl
)
=
1
;
i386_pe_declare_function_type
(
asm_out_file
,
p
->
name
,
TREE_PUBLIC
(
decl
)
)
;
}
}
if
(
export_head
)
{
struct
export_list
*
q
;
drectve_section
(
)
;
for
(
q
=
export_head
;
q
!=
;
q
=
q
->
next
)
{
fprintf
(
asm_out_file
,
"\t.ascii \" -export:\\\"%s\\\"%s\"\n"
,
default_strip_name_encoding
(
q
->
name
)
,
(
q
->
is_data
",data"
:
""
)
)
;
}
}
if
(
stub_head
)
{
struct
stub_list
*
q
;
for
(
q
=
stub_head
;
q
!=
;
q
=
q
->
next
)
{
const
char
*
name
=
q
->
name
;
const
char
*
oname
;
if
(
name
[
0
]
==
'*'
)
++
name
;
oname
=
name
;
if
(
name
[
0
]
==
'.'
)
++
name
;
if
(
!
startswith
(
name
,
"refptr."
)
)
continue
;
name
+=
7
;
fprintf
(
asm_out_file
,
"\t.section\t.rdata$%s, \"dr\"\n"
"\t.globl\t%s\n"
"\t.linkonce\tdiscard\n"
,
oname
,
oname
)
;
fprintf
(
asm_out_file
,
"%s:\n\t.quad\t%s\n"
,
oname
,
name
)
;
}
}
}
</s>

This is called at the end of assembly . For each external function which has not been defined , we output a declaration now . We also output the .drectve section .


<s> tree i386_pe_mangle_assembler_name ( const char * name ) { const char * skipped = name + ( * name == '*' ? 1 : 0 ) ; const char * stripped = targetm . strip_name_encoding ( skipped ) ; if ( * name != '*' && * user_label_prefix && * stripped != FASTCALL_PREFIX ) stripped = ACONCAT ( ( user_label_prefix , stripped , NULL ) ) ; return get_identifier ( stripped ) ; } </s>

This hook behaves the same as varasm.cc/assemble_name ( ) , but generates the name into memory rather than outputting it to a file stream .


This is used as a target hook to modify the DECL_ASSEMBLER_NAME in the language-independent default hook langhooks , c : lhd_set_decl_assembler_name ( ) and in cp/mangle , c : mangle_decl ( ) .


Maybe decorate and get a new identifier for the DECL of a stdcall or fastcall function . The original identifier is supplied in ID .


<s> void i386_pe_maybe_record_exported_symbol ( tree decl , const char * name , int is_data ) { rtx symbol ; struct export_list * p ; if ( ! decl ) return ; symbol = XEXP ( DECL_RTL ( decl ) , 0 ) ; gcc_assert ( GET_CODE ( symbol ) == SYMBOL_REF ) ; if ( ! SYMBOL_REF_DLLEXPORT_P ( symbol ) ) return ; gcc_assert ( TREE_PUBLIC ( decl ) ) ; p = ggc_alloc < export_list > ( ) ; p -> next = export_head ; p -> name = name ; p -> is_data = is_data ; export_head = p ; } </s>

Assemble an export symbol entry . We need to keep a list of these , so that we can output the export list at the end of the assembly . We used to output these export symbols in each function , but that causes problems with GNU ld when the sections are linkonce . Beware , DECL may be NULL if compile_file ( ) is emitting the LTO marker .


<s> void i386_pe_record_external_function ( tree decl , const char * name ) { struct extern_list * p ; p = ggc_alloc < extern_list > ( ) ; p -> next = extern_head ; p -> decl = decl ; p -> name = name ; extern_head = p ; } </s>

Assemble an external function reference . We need to keep a list of these , so that we can output the function types at the end of the assembly . We ca n't output the types now , because we might see a definition of the function later on and emit debugging information for it then .


<s> int i386_pe_reloc_rw_mask ( void ) { return 0 ; } </s>

Local and global relocs can be placed always into readonly memory for memory for PE-COFF targets .


<s>
void
i386_pe_seh_cold_init
(
FILE
*
f
,
const
char
*
name
)
{
struct
seh_frame_state
*
seh
;
HOST_WIDE_INT
alloc_offset
,
offset
;
if
(
!
TARGET_SEH
)
return
;
if
(
cfun
->
is_thunk
)
return
;
seh
=
cfun
->
machine
->
seh
;
fputs
(
"\t.seh_proc\t"
,
f
)
;
assemble_name
(
f
,
name
)
;
fputc
(
'\n'
,
f
)
;
offset
=
seh
->
sp_offset
INCOMING_FRAME_SP_OFFSET
;
if
(
offset
<
SEH_MAX_FRAME_SIZE
&&
!
crtl
->
accesses_prior_frames
)
alloc_offset
=
seh
->
sp_offset
;
else
alloc_offset
=
MIN
(
seh
->
cfa_offset
+
240
,
seh
->
sp_offset
)
;
offset
=
alloc_offset
INCOMING_FRAME_SP_OFFSET
;
if
(
offset
>
0
)
fprintf
(
f
,
"\t.seh_stackalloc\t"
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
for
(
int
regno
=
0
;
regno
<
FIRST_PSEUDO_REGISTER
;
regno
++
)
if
(
seh
->
reg_offset
[
regno
]
>
0
&&
seh
->
reg_offset
[
regno
]
<=
alloc_offset
)
{
if
(
SSE_REGNO_P
(
regno
)
)
fputs
(
"\t.seh_savexmm\t"
,
f
)
;
else
if
(
GENERAL_REGNO_P
(
regno
)
)
fputs
(
"\t.seh_savereg\t"
,
f
)
;
else
gcc_unreachable
(
)
;
print_reg
(
gen_rtx_REG
(
DImode
,
regno
)
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
alloc_offset
seh
->
reg_offset
[
regno
]
)
;
}
if
(
seh
->
cfa_reg
!=
stack_pointer_rtx
)
{
offset
=
alloc_offset
seh
->
cfa_offset
;
gcc_assert
(
(
offset
&
15
)
==
0
)
;
gcc_assert
(
IN_RANGE
(
offset
,
0
,
240
)
)
;
fputs
(
"\t.seh_setframe\t"
,
f
)
;
print_reg
(
seh
->
cfa_reg
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
if
(
alloc_offset
!=
seh
->
sp_offset
)
{
offset
=
seh
->
sp_offset
alloc_offset
;
if
(
offset
>
0
&&
offset
<
SEH_MAX_FRAME_SIZE
)
fprintf
(
f
,
"\t.seh_stackalloc\t"
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
for
(
int
regno
=
0
;
regno
<
FIRST_PSEUDO_REGISTER
;
regno
++
)
if
(
seh
->
reg_offset
[
regno
]
>
alloc_offset
)
{
if
(
SSE_REGNO_P
(
regno
)
)
fputs
(
"\t.seh_savexmm\t"
,
f
)
;
else
if
(
GENERAL_REGNO_P
(
regno
)
)
fputs
(
"\t.seh_savereg\t"
,
f
)
;
else
gcc_unreachable
(
)
;
print_reg
(
gen_rtx_REG
(
DImode
,
regno
)
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
seh
->
sp_offset
seh
->
reg_offset
[
regno
]
)
;
}
}
fputs
(
"\t.seh_endprologue\n"
,
f
)
;
}
</s>


<s> void i386_pe_seh_end_prologue ( FILE * f ) { if ( ! TARGET_SEH ) return ; if ( cfun -> is_thunk ) return ; cfun -> machine -> seh -> after_prologue = true ; fputs ( "\t.seh_endprologue\n" , f ) ; } </s>

Emit an assembler directive for the end of the prologue .


<s> static void i386_pe_seh_fini ( FILE * f , bool cold ) { struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; if ( cfun -> is_thunk ) return ; seh = cfun -> machine -> seh ; if ( cold != seh -> in_cold_section ) return ; XDELETE ( seh ) ; cfun -> machine -> seh = NULL ; fputs ( "\t.seh_endproc\n" , f ) ; } </s>

Emit an assembler directive for the end of the function .


<s> void i386_pe_seh_init ( FILE * f ) { struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; if ( cfun -> is_thunk ) return ; gcc_assert ( ! stack_realign_drap ) ; seh = XCNEW ( struct seh_frame_state ) ; cfun -> machine -> seh = seh ; seh -> sp_offset = INCOMING_FRAME_SP_OFFSET ; seh -> cfa_offset = INCOMING_FRAME_SP_OFFSET ; seh -> cfa_reg = stack_pointer_rtx ; fputs ( "\t.seh_proc\t" , f ) ; assemble_name ( f , IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( cfun -> decl ) ) ) ; fputc ( '\n' , f ) ; } </s>

Set up data structures beginning output for SEH .


<s> void i386_pe_seh_unwind_emit ( FILE * out_file , rtx_insn * insn ) { rtx note , pat ; bool handled_one = false ; struct seh_frame_state * seh ; if ( ! TARGET_SEH ) return ; seh = cfun -> machine -> seh ; if ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_SWITCH_TEXT_SECTIONS ) { rtx_insn * prev = prev_active_insn ( insn ) ; if ( prev && ( CALL_P ( prev ) || ! insn_nothrow_p ( prev ) ) ) fputs ( "\tnop\n" , out_file ) ; fputs ( "\t.seh_endproc\n" , out_file ) ; seh -> in_cold_section = true ; return ; } if ( NOTE_P ( insn ) || ! RTX_FRAME_RELATED_P ( insn ) ) return ; if ( seh -> after_prologue ) return ; for ( note = REG_NOTES ( insn ) ; note ; note = XEXP ( note , 1 ) ) { switch ( REG_NOTE_KIND ( note ) ) { case REG_FRAME_RELATED_EXPR : pat = XEXP ( note , 0 ) ; goto found ; case REG_CFA_DEF_CFA : case REG_CFA_EXPRESSION : gcc_unreachable ( ) ; break ; case REG_CFA_REGISTER : gcc_unreachable ( ) ; case REG_CFA_ADJUST_CFA : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) { pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == PARALLEL ) pat = XVECEXP ( pat , 0 , 0 ) ; } seh_cfa_adjust_cfa ( out_file , seh , pat ) ; handled_one = true ; break ; case REG_CFA_OFFSET : pat = XEXP ( note , 0 ) ; if ( pat == NULL ) pat = single_set ( insn ) ; seh_cfa_offset ( out_file , seh , pat ) ; handled_one = true ; break ; default : break ; } } if ( handled_one ) return ; pat = PATTERN ( insn ) ; found : seh_frame_related_expr ( out_file , seh , pat ) ; } </s>

This function looks at a single insn and emits any SEH directives required for unwind of this insn .


<s> const char * i386_pe_strip_name_encoding_full ( const char * str ) { const char * p ; const char * name = default_strip_name_encoding ( str ) ; if ( * name == '@' ) name ++ ; p = strchr ( name , '@' ) ; if ( p ) return ggc_alloc_string ( name , p - name ) ; return name ; } </s>

Also strip the fastcall prefix and stdcall suffix .


<s> void i386_pe_unique_section ( tree decl , int reloc ) { int len ; const char * name , * prefix ; char * string ; if ( ! flag_writable_rel_rdata ) reloc = 0 ; name = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; name = i386_pe_strip_name_encoding_full ( name ) ; if ( TREE_CODE ( decl ) == FUNCTION_DECL ) prefix = ".text$" ; else if ( decl_readonly_section ( decl , reloc ) ) prefix = ".rdata$" ; else prefix = ".data$" ; len = strlen ( name ) + strlen ( prefix ) ; string = XALLOCAVEC ( char , len + 1 ) ; sprintf ( string , "%s%s" , prefix , name ) ; set_decl_section_name ( decl , string ) ; } </s>


<s> bool i386_pe_valid_dllimport_attribute_p ( const_tree decl ) { if ( TARGET_NOP_FUN_DLLIMPORT && TREE_CODE ( decl ) == FUNCTION_DECL ) return false ; return true ; } </s>

Handle the -mno-fun-dllimport target switch .


"%qE attribute applies only to initialized variables"

Handle a `` selectany '' attribute ; arguments as in struct attribute_spec.handler .


"%qE attribute only applies to variables"

Handle a `` shared '' attribute ; arguments as in struct attribute_spec.handler .


<s>
static
void
seh_cfa_adjust_cfa
(
FILE
*
f
,
struct
seh_frame_state
*
seh
,
rtx
pat
)
{
rtx
dest
,
src
;
HOST_WIDE_INT
reg_offset
=
0
;
unsigned
int
dest_regno
;
dest
=
SET_DEST
(
pat
)
;
src
=
SET_SRC
(
pat
)
;
if
(
GET_CODE
(
src
)
==
PLUS
)
{
reg_offset
=
INTVAL
(
XEXP
(
src
,
1
)
)
;
src
=
XEXP
(
src
,
0
)
;
}
else
if
(
GET_CODE
(
src
)
==
MINUS
)
{
reg_offset
=
INTVAL
(
XEXP
(
src
,
1
)
)
;
src
=
XEXP
(
src
,
0
)
;
}
gcc_assert
(
src
==
stack_pointer_rtx
)
;
gcc_assert
(
seh
->
cfa_reg
==
stack_pointer_rtx
)
;
dest_regno
=
REGNO
(
dest
)
;
if
(
dest_regno
==
STACK_POINTER_REGNUM
)
seh_emit_stackalloc
(
f
,
seh
,
reg_offset
)
;
else
if
(
dest_regno
==
HARD_FRAME_POINTER_REGNUM
)
{
HOST_WIDE_INT
offset
;
seh
->
cfa_reg
=
dest
;
seh
->
cfa_offset
-=
reg_offset
;
offset
=
seh
->
sp_offset
seh
->
cfa_offset
;
gcc_assert
(
(
offset
&
15
)
==
0
)
;
gcc_assert
(
IN_RANGE
(
offset
,
0
,
240
)
)
;
fputs
(
"\t.seh_setframe\t"
,
f
)
;
print_reg
(
seh
->
cfa_reg
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
else
gcc_unreachable
(
)
;
}
</s>


<s> static void seh_cfa_offset ( FILE * f , struct seh_frame_state * seh , rtx pat ) { rtx dest , src ; HOST_WIDE_INT reg_offset ; dest = SET_DEST ( pat ) ; src = SET_SRC ( pat ) ; gcc_assert ( MEM_P ( dest ) ) ; dest = XEXP ( dest , 0 ) ; if ( REG_P ( dest ) ) reg_offset = 0 ; else { gcc_assert ( GET_CODE ( dest ) == PLUS ) ; reg_offset = INTVAL ( XEXP ( dest , 1 ) ) ; dest = XEXP ( dest , 0 ) ; } gcc_assert ( dest == seh -> cfa_reg ) ; seh_emit_save ( f , seh , src , seh -> cfa_offset - reg_offset ) ; } </s>


<s> static void seh_emit_push ( FILE * f , struct seh_frame_state * seh , rtx reg ) { const unsigned int regno = REGNO ( reg ) ; gcc_checking_assert ( GENERAL_REGNO_P ( regno ) ) ; seh -> sp_offset += UNITS_PER_WORD ; seh -> reg_offset [ regno ] = seh -> sp_offset ; if ( seh -> cfa_reg == stack_pointer_rtx ) seh -> cfa_offset += UNITS_PER_WORD ; fputs ( "\t.seh_pushreg\t" , f ) ; print_reg ( reg , 0 , f ) ; fputc ( '\n' , f ) ; } </s>

Emit an assembler directive to save REG via a PUSH .


<s>
static
void
seh_emit_save
(
FILE
*
f
,
struct
seh_frame_state
*
seh
,
rtx
reg
,
HOST_WIDE_INT
cfa_offset
)
{
const
unsigned
int
regno
=
REGNO
(
reg
)
;
HOST_WIDE_INT
offset
;
seh
->
reg_offset
[
regno
]
=
cfa_offset
;
gcc_assert
(
seh
->
sp_offset
>=
cfa_offset
)
;
offset
=
seh
->
sp_offset
cfa_offset
;
fputs
(
(
SSE_REGNO_P
(
regno
)
"\t.seh_savexmm\t"
:
GENERAL_REGNO_P
(
regno
)
"\t.seh_savereg\t"
:
(
gcc_unreachable
(
)
,
""
)
)
,
f
)
;
print_reg
(
reg
,
0
,
f
)
;
fprintf
(
f
,
", "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
offset
)
;
}
</s>

Emit an assembler directive to save REG at CFA - CFA_OFFSET .


<s> static void seh_emit_stackalloc ( FILE * f , struct seh_frame_state * seh , HOST_WIDE_INT offset ) { gcc_assert ( offset < 0 ) ; offset = - offset ; if ( seh -> cfa_reg == stack_pointer_rtx ) seh -> cfa_offset += offset ; seh -> sp_offset += offset ; if ( offset < SEH_MAX_FRAME_SIZE ) fprintf ( f , "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n" , offset ) ; } </s>

Emit an assembler directive to adjust RSP by OFFSET .


<s> static void seh_frame_related_expr ( FILE * f , struct seh_frame_state * seh , rtx pat ) { rtx dest , src ; HOST_WIDE_INT addend ; if ( GET_CODE ( pat ) == PARALLEL || GET_CODE ( pat ) == SEQUENCE ) { int i , n = XVECLEN ( pat , 0 ) , pass , npass ; npass = ( GET_CODE ( pat ) == PARALLEL ? 2 : 1 ) ; for ( pass = 0 ; pass < npass ; ++ pass ) for ( i = 0 ; i < n ; ++ i ) { rtx ele = XVECEXP ( pat , 0 , i ) ; if ( GET_CODE ( ele ) != SET ) continue ; dest = SET_DEST ( ele ) ; if ( i == 0 || RTX_FRAME_RELATED_P ( ele ) ) { if ( ( MEM_P ( dest ) ^ pass ) || npass == 1 ) seh_frame_related_expr ( f , seh , ele ) ; } } return ; } dest = SET_DEST ( pat ) ; src = SET_SRC ( pat ) ; switch ( GET_CODE ( dest ) ) { case REG : switch ( GET_CODE ( src ) ) { case REG : gcc_assert ( src == stack_pointer_rtx ) ; gcc_assert ( dest == hard_frame_pointer_rtx ) ; seh_cfa_adjust_cfa ( f , seh , pat ) ; break ; case PLUS : addend = INTVAL ( XEXP ( src , 1 ) ) ; src = XEXP ( src , 0 ) ; if ( dest == hard_frame_pointer_rtx ) seh_cfa_adjust_cfa ( f , seh , pat ) ; else if ( dest == stack_pointer_rtx ) { gcc_assert ( src == stack_pointer_rtx ) ; seh_emit_stackalloc ( f , seh , addend ) ; } else gcc_unreachable ( ) ; break ; default : gcc_unreachable ( ) ; } break ; case MEM : dest = XEXP ( dest , 0 ) ; if ( GET_CODE ( dest ) == PRE_DEC ) { gcc_checking_assert ( GET_MODE ( src ) == Pmode ) ; gcc_checking_assert ( REG_P ( src ) ) ; seh_emit_push ( f , seh , src ) ; } else seh_cfa_offset ( f , seh , pat ) ; break ; default : gcc_unreachable ( ) ; } } </s>


<s> static int do_reorder_for_imul ( rtx_insn * * ready , int n_ready ) { rtx_insn * insn ; rtx set , insn1 , insn2 ; sd_iterator_def sd_it ; dep_t dep ; int index = - 1 ; int i ; if ( ! TARGET_CPU_P ( BONNELL ) ) return index ; insn = ready [ n_ready - 1 ] ; set = single_set ( insn ) ; if ( ! set ) return index ; if ( ! ( GET_CODE ( SET_SRC ( set ) ) == MULT && GET_MODE ( SET_SRC ( set ) ) == SImode ) ) return index ; for ( i = n_ready - 2 ; i >= 0 ; i -- ) { insn = ready [ i ] ; if ( ! NONDEBUG_INSN_P ( insn ) ) continue ; insn2 = PATTERN ( insn ) ; if ( GET_CODE ( insn2 ) == PARALLEL ) insn2 = XVECEXP ( insn2 , 0 , 0 ) ; if ( GET_CODE ( insn2 ) == SET && GET_CODE ( SET_SRC ( insn2 ) ) == MULT && GET_MODE ( SET_SRC ( insn2 ) ) == SImode ) continue ; FOR_EACH_DEP ( insn , SD_LIST_FORW , sd_it , dep ) { rtx con ; con = DEP_CON ( dep ) ; if ( ! NONDEBUG_INSN_P ( con ) ) continue ; insn1 = PATTERN ( con ) ; if ( GET_CODE ( insn1 ) == PARALLEL ) insn1 = XVECEXP ( insn1 , 0 , 0 ) ; if ( GET_CODE ( insn1 ) == SET && GET_CODE ( SET_SRC ( insn1 ) ) == MULT && GET_MODE ( SET_SRC ( insn1 ) ) == SImode ) { sd_iterator_def sd_it1 ; dep_t dep1 ; index = i ; FOR_EACH_DEP ( con , SD_LIST_BACK , sd_it1 , dep1 ) { rtx pro ; pro = DEP_PRO ( dep1 ) ; if ( ! NONDEBUG_INSN_P ( pro ) ) continue ; if ( pro != insn ) index = - 1 ; } if ( index >= 0 ) break ; } } if ( index >= 0 ) break ; } return index ; } </s>

Try to reorder ready list to take advantage of Atom pipelined IMUL execution . It is applied if ( 1 ) IMUL instruction is on the top of list ; ( 2 ) There exists the only producer of independent IMUL instruction in ready list . Return index of IMUL producer if it was found and -1 otherwise .


";;\tatom sched_reorder: put %d insn on top\n"

";;\tslm sched_reorder: swap %d and %d insns\n"

Perform possible reodering of ready list for Atom/Silvermont only . Return issue rate .


<s> static bool swap_top_of_ready_list ( rtx_insn * * ready , int n_ready ) { rtx_insn * top = ready [ n_ready - 1 ] ; rtx_insn * next = ready [ n_ready - 2 ] ; rtx set ; sd_iterator_def sd_it ; dep_t dep ; int clock1 = - 1 ; int clock2 = - 1 ; if ( ! TARGET_CPU_P ( SILVERMONT ) && ! TARGET_CPU_P ( INTEL ) ) return false ; if ( ! NONDEBUG_INSN_P ( top ) ) return false ; if ( ! NONJUMP_INSN_P ( top ) ) return false ; if ( ! NONDEBUG_INSN_P ( next ) ) return false ; if ( ! NONJUMP_INSN_P ( next ) ) return false ; set = single_set ( top ) ; if ( ! set ) return false ; set = single_set ( next ) ; if ( ! set ) return false ; if ( INSN_PRIORITY_KNOWN ( top ) && INSN_PRIORITY_KNOWN ( next ) ) { if ( INSN_PRIORITY ( top ) != INSN_PRIORITY ( next ) ) return false ; FOR_EACH_DEP ( top , SD_LIST_RES_BACK , sd_it , dep ) { rtx pro ; pro = DEP_PRO ( dep ) ; if ( ! NONDEBUG_INSN_P ( pro ) ) continue ; if ( INSN_TICK ( pro ) > clock1 ) clock1 = INSN_TICK ( pro ) ; } FOR_EACH_DEP ( next , SD_LIST_RES_BACK , sd_it , dep ) { rtx pro ; pro = DEP_PRO ( dep ) ; if ( ! NONDEBUG_INSN_P ( pro ) ) continue ; if ( INSN_TICK ( pro ) > clock2 ) clock2 = INSN_TICK ( pro ) ; } if ( clock1 == clock2 ) { enum attr_memory memory1 , memory2 ; memory1 = get_attr_memory ( top ) ; memory2 = get_attr_memory ( next ) ; if ( memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD ) return true ; } return ( bool ) ( clock2 < clock1 ) ; } return false ; } </s>

Try to find the best candidate on the top of ready list if two insns have the same priority - candidate is best if its dependees were scheduled earlier . Applied for Silvermont only . Return true if top 2 insns must be interchanged .


<s> static void add_insn_window ( rtx_insn * insn , dispatch_windows * window_list , int num_uops ) { int byte_len = ix86_min_insn_size ( insn ) ; int num_insn = window_list -> num_insn ; int imm_size ; sched_insn_info * window = window_list -> window ; enum dispatch_group group = get_insn_group ( insn ) ; enum insn_path path = get_insn_path ( insn ) ; int num_imm_operand ; int num_imm32_operand ; int num_imm64_operand ; if ( ! window_list -> violation && group != disp_cmp && ! fits_dispatch_window ( insn ) ) window_list -> violation = true ; imm_size = get_num_immediates ( insn , & num_imm_operand , & num_imm32_operand , & num_imm64_operand ) ; window [ num_insn ] . insn = insn ; window [ num_insn ] . byte_len = byte_len ; window [ num_insn ] . group = group ; window [ num_insn ] . path = path ; window [ num_insn ] . imm_bytes = imm_size ; window_list -> window_size += byte_len ; window_list -> num_insn = num_insn + 1 ; window_list -> num_uops = window_list -> num_uops + num_uops ; window_list -> imm_size += imm_size ; window_list -> num_imm += num_imm_operand ; window_list -> num_imm_32 += num_imm32_operand ; window_list -> num_imm_64 += num_imm64_operand ; if ( group == disp_store ) window_list -> num_stores += 1 ; else if ( group == disp_load || group == disp_prefetch ) window_list -> num_loads += 1 ; else if ( group == disp_load_store ) { window_list -> num_stores += 1 ; window_list -> num_loads += 1 ; } } </s>

Add an instruction INSN with NUM_UOPS micro-operations to the dispatch window WINDOW_LIST .


<s> static void add_to_dispatch_window ( rtx_insn * insn ) { int byte_len ; dispatch_windows * window_list ; dispatch_windows * next_list ; dispatch_windows * window0_list ; enum insn_path path ; enum dispatch_group insn_group ; bool insn_fits ; int num_insn ; int num_uops ; int window_num ; int insn_num_uops ; int sum ; if ( INSN_CODE ( insn ) < 0 ) return ; byte_len = ix86_min_insn_size ( insn ) ; window_list = dispatch_window_list ; next_list = window_list -> next ; path = get_insn_path ( insn ) ; insn_group = get_insn_group ( insn ) ; if ( next_list ) window_list = dispatch_window_list -> next ; if ( path == path_single ) insn_num_uops = 1 ; else if ( path == path_double ) insn_num_uops = 2 ; else insn_num_uops = ( int ) path ; num_insn = window_list -> num_insn ; num_uops = window_list -> num_uops ; window_num = window_list -> window_num ; insn_fits = fits_dispatch_window ( insn ) ; if ( num_insn >= MAX_INSN || num_uops + insn_num_uops > MAX_INSN || ! ( insn_fits ) ) { window_num = ~ window_num & 1 ; window_list = allocate_next_window ( window_num ) ; } if ( window_num == 0 ) { add_insn_window ( insn , window_list , insn_num_uops ) ; if ( window_list -> num_insn >= MAX_INSN && insn_group == disp_branch ) { process_end_window ( ) ; return ; } } else if ( window_num == 1 ) { window0_list = window_list -> prev ; sum = window0_list -> window_size + window_list -> window_size ; if ( sum == 32 || ( byte_len + sum ) >= 48 ) { process_end_window ( ) ; window_list = dispatch_window_list ; } add_insn_window ( insn , window_list , insn_num_uops ) ; } else gcc_unreachable ( ) ; if ( is_end_basic_block ( insn_group ) ) { process_end_window ( ) ; return ; } } </s>

Adds a scheduled instruction , INSN , to the current dispatch window . If the total bytes of instructions or the number of instructions in the window exceed allowable , it allocates a new window .


"  group = %s, path = %d, byte_len = %d\n"

"  num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n"

Print INSN dispatch information to FILE .


<s> static bool fits_dispatch_window ( rtx_insn * insn ) { dispatch_windows * window_list = dispatch_window_list ; dispatch_windows * window_list_next = dispatch_window_list -> next ; unsigned int num_restrict ; enum dispatch_group group = get_insn_group ( insn ) ; enum insn_path path = get_insn_path ( insn ) ; int sum ; if ( group == disp_jcc || group == disp_cmp ) return false ; if ( group == disp_no_group || group == disp_branch ) return true ; if ( window_list_next ) window_list = window_list_next ; if ( window_list -> window_num == 1 ) { sum = window_list -> prev -> window_size + window_list -> window_size ; if ( sum == 32 || ( ix86_min_insn_size ( insn ) + sum ) >= 48 ) return true ; } num_restrict = count_num_restricted ( insn , window_list ) ; if ( num_restrict > num_allowable_groups [ group ] ) return false ; if ( window_list -> window_num == 0 ) { if ( path == path_double && ( window_list -> num_uops + 2 ) > MAX_INSN ) return false ; else if ( path != path_single ) return false ; } return true ; } </s>

This function returns true if insn satisfies dispatch rules on the last window scheduled .


<s> void ix86_bd_do_dispatch ( rtx_insn * insn , int mode ) { if ( mode == DISPATCH_INIT ) init_dispatch_sched ( ) ; else if ( mode == ADD_TO_DISPATCH_WINDOW ) add_to_dispatch_window ( insn ) ; } </s>

This routine is the driver of the dispatch scheduler .


<s> bool ix86_bd_has_dispatch ( rtx_insn * insn , int action ) { if ( ( TARGET_CPU_P ( BDVER1 ) || TARGET_CPU_P ( BDVER2 ) || TARGET_CPU_P ( BDVER3 ) || TARGET_CPU_P ( BDVER4 ) ) && flag_dispatch_scheduler ) switch ( action ) { default : return false ; case IS_DISPATCH_ON : return true ; case IS_CMP : return is_cmp ( insn ) ; case DISPATCH_VIOLATION : return dispatch_violation ( ) ; case FITS_DISPATCH_WINDOW : return fits_dispatch_window ( insn ) ; } return false ; } </s>

Return TRUE if Dispatch Scheduling is supported .


INSN is being issued in current solution . Account for its impact on the decoder model .


<s> int ix86_issue_rate ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : case PROCESSOR_LAKEMONT : case PROCESSOR_BONNELL : case PROCESSOR_SILVERMONT : case PROCESSOR_KNL : case PROCESSOR_KNM : case PROCESSOR_INTEL : case PROCESSOR_K6 : case PROCESSOR_BTVER2 : case PROCESSOR_PENTIUM4 : case PROCESSOR_NOCONA : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_ATHLON : case PROCESSOR_K8 : case PROCESSOR_AMDFAM10 : case PROCESSOR_BTVER1 : case PROCESSOR_LUJIAZUI : return 3 ; case PROCESSOR_BDVER1 : case PROCESSOR_BDVER2 : case PROCESSOR_BDVER3 : case PROCESSOR_BDVER4 : case PROCESSOR_ZNVER1 : case PROCESSOR_ZNVER2 : case PROCESSOR_ZNVER3 : case PROCESSOR_ZNVER4 : case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : case PROCESSOR_TREMONT : case PROCESSOR_SKYLAKE : case PROCESSOR_SKYLAKE_AVX512 : case PROCESSOR_CASCADELAKE : case PROCESSOR_CANNONLAKE : case PROCESSOR_ALDERLAKE : case PROCESSOR_GENERIC : return 4 ; case PROCESSOR_ICELAKE_CLIENT : case PROCESSOR_ICELAKE_SERVER : case PROCESSOR_TIGERLAKE : case PROCESSOR_COOPERLAKE : case PROCESSOR_ROCKETLAKE : return 5 ; case PROCESSOR_SAPPHIRERAPIDS : return 6 ; default : return 1 ; } } </s>

Return the maximum number of instructions a cpu can issue .


<s> int ix86_issue_rate ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : case PROCESSOR_LAKEMONT : case PROCESSOR_BONNELL : case PROCESSOR_SILVERMONT : case PROCESSOR_KNL : case PROCESSOR_KNM : case PROCESSOR_INTEL : case PROCESSOR_K6 : case PROCESSOR_BTVER2 : case PROCESSOR_PENTIUM4 : case PROCESSOR_NOCONA : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_ATHLON : case PROCESSOR_K8 : case PROCESSOR_AMDFAM10 : case PROCESSOR_BTVER1 : return 3 ; case PROCESSOR_BDVER1 : case PROCESSOR_BDVER2 : case PROCESSOR_BDVER3 : case PROCESSOR_BDVER4 : case PROCESSOR_ZNVER1 : case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : case PROCESSOR_GENERIC : return 4 ; default : return 1 ; } } </s>


<s> static bool exact_dependency_1 ( rtx addr , rtx insn ) { enum rtx_code code ; const char * format_ptr ; int i , j ; code = GET_CODE ( insn ) ; switch ( code ) { case MEM : if ( rtx_equal_p ( addr , insn ) ) return true ; break ; case REG : CASE_CONST_ANY : case SYMBOL_REF : case CODE_LABEL : case PC : case EXPR_LIST : return false ; default : break ; } format_ptr = GET_RTX_FORMAT ( code ) ; for ( i = 0 ; i < GET_RTX_LENGTH ( code ) ; i ++ ) { switch ( * format_ptr ++ ) { case 'e' : if ( exact_dependency_1 ( addr , XEXP ( insn , i ) ) ) return true ; break ; case 'E' : for ( j = 0 ; j < XVECLEN ( insn , i ) ; j ++ ) if ( exact_dependency_1 ( addr , XVECEXP ( insn , i , j ) ) ) return true ; break ; } } return false ; } </s>

Helper function for exact_store_load_dependency . Return true if addr is found in insn .


<s> int ia32_multipass_dfa_lookahead ( void ) { if ( reload_completed ) return ix86_issue_rate ( ) ; return 0 ; } </s>

How many alternative schedules to try . This should be as wide as the scheduling freedom in the DFA , but no wider . Making this value too large results extra work for the scheduler .


<s> bool ix86_agi_dependent ( rtx_insn * set_insn , rtx_insn * use_insn ) { int i ; extract_insn_cached ( use_insn ) ; for ( i = recog_data . n_operands - 1 ; i >= 0 ; -- i ) if ( MEM_P ( recog_data . operand [ i ] ) ) { rtx addr = XEXP ( recog_data . operand [ i ] , 0 ) ; if ( modified_in_p ( addr , set_insn ) != 0 ) { rtx set = single_set ( set_insn ) ; if ( set && ( push_operand ( SET_DEST ( set ) , GET_MODE ( SET_DEST ( set ) ) ) || pop_operand ( SET_SRC ( set ) , GET_MODE ( SET_SRC ( set ) ) ) ) ) { struct ix86_address parts ; if ( ix86_decompose_address ( addr , & parts ) && parts . base == stack_pointer_rtx && ( parts . index == NULL_RTX || MEM_P ( SET_DEST ( set ) ) || ! modified_in_p ( parts . index , set_insn ) ) ) return false ; } return true ; } return false ; } return false ; } </s>

Return true iff USE_INSN has a memory address with operands set by SET_INSN .


<s> int ix86_issue_rate ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : case PROCESSOR_LAKEMONT : case PROCESSOR_BONNELL : case PROCESSOR_SILVERMONT : case PROCESSOR_KNL : case PROCESSOR_KNM : case PROCESSOR_INTEL : case PROCESSOR_K6 : case PROCESSOR_BTVER2 : case PROCESSOR_PENTIUM4 : case PROCESSOR_NOCONA : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_ATHLON : case PROCESSOR_K8 : case PROCESSOR_AMDFAM10 : case PROCESSOR_BTVER1 : return 3 ; case PROCESSOR_BDVER1 : case PROCESSOR_BDVER2 : case PROCESSOR_BDVER3 : case PROCESSOR_BDVER4 : case PROCESSOR_ZNVER1 : case PROCESSOR_ZNVER2 : case PROCESSOR_ZNVER3 : case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : case PROCESSOR_TREMONT : case PROCESSOR_ALDERLAKE : case PROCESSOR_GENERIC : return 4 ; default : return 1 ; } } </s>


<s> bool ix86_macro_fusion_p ( ) { return TARGET_FUSE_CMP_AND_BRANCH ; } </s>

Return true if target platform supports macro-fusion .