void oacc_replace_fn_attrib (tree fn, tree dims) { tree ident = get_identifier (OACC_FN_ATTRIB); tree attribs = DECL_ATTRIBUTES (fn); /* If we happen to be present as the first attrib, drop it. */ if (attribs && TREE_PURPOSE (attribs) == ident) attribs = TREE_CHAIN (attribs); DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs); }
static inline void maybe_add_dllexport (tree decl) { if (i386_pe_type_dllexport_p (decl)) { tree decl_attrs = DECL_ATTRIBUTES (decl); if (lookup_attribute ("dllexport", decl_attrs) != NULL_TREE) /* Already done. */ return; DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("dllexport"), NULL_TREE, decl_attrs); } }
bool i386_pe_dllimport_p (tree decl) { if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return false; /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag. We may need to override an earlier decision. */ if (DECL_DLLIMPORT_P (decl) && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) { /* Make a final check to see if this is a definition before we generate RTL for an indirect reference. */ if (!DECL_EXTERNAL (decl)) { error ("%q+D: definition is marked as dllimport", decl); DECL_DLLIMPORT_P (decl) = 0; return false; } return true; } /* The DECL_DLLIMPORT_P flag was set for decls in the class definition by targetm.cxx.adjust_class_at_definition. Check again to emit warnings if the class attribute has been overridden by an out-of-class definition. */ else if (associated_type (decl) && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (associated_type (decl)))) return i386_pe_type_dllimport_p (decl); return false; }
const_tree get_attribute(const char* attr_name, const_tree decl) { const_tree attr = lookup_attribute(attr_name, DECL_ATTRIBUTES(decl)); if (attr && TREE_VALUE(attr)) return attr; return NULL_TREE; }
static inline bool has_proper_scope_for_analysis (tree t) { /* If the variable has the "used" attribute, treat it as if it had a been touched by the devil. */ if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) return false; /* Do not want to do anything with volatile except mark any function that uses one to be not const or pure. */ if (TREE_THIS_VOLATILE (t)) return false; /* Do not care about a local automatic that is not static. */ if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) return false; if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) return false; /* This is a variable we care about. Check if we have seen it before, and if not add it the set of variables we care about. */ if (!bitmap_bit_p (all_module_statics, DECL_UID (t))) add_static_var (t); return true; }
static void write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr, bool ref_p) { stream_write_tree (ob, DECL_SIZE (expr), ref_p); stream_write_tree (ob, DECL_SIZE_UNIT (expr), ref_p); /* Note, DECL_INITIAL is not handled here. Since DECL_INITIAL needs special handling in LTO, it must be handled by streamer hooks. */ stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p); /* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in dwarf2out.c. */ if (TREE_CODE (expr) == PARM_DECL) streamer_write_chain (ob, TREE_CHAIN (expr), ref_p); if ((TREE_CODE (expr) == VAR_DECL || TREE_CODE (expr) == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (expr)) stream_write_tree (ob, DECL_VALUE_EXPR (expr), ref_p); if (TREE_CODE (expr) == VAR_DECL) stream_write_tree (ob, DECL_DEBUG_EXPR (expr), ref_p); }
void solaris_insert_attributes (tree decl, tree *attributes) { tree *x, next; if (solaris_pending_aligns != NULL && TREE_CODE (decl) == VAR_DECL) for (x = &solaris_pending_aligns; *x; x = &TREE_CHAIN (*x)) { tree name = TREE_PURPOSE (*x); tree value = TREE_VALUE (*x); if (DECL_NAME (decl) == name) { if (lookup_attribute ("aligned", DECL_ATTRIBUTES (decl)) || lookup_attribute ("aligned", *attributes)) warning (0, "ignoring %<#pragma align%> for explicitly " "aligned %q+D", decl); else *attributes = tree_cons (get_identifier ("aligned"), value, *attributes); next = TREE_CHAIN (*x); ggc_free (*x); *x = next; break; } } if (solaris_pending_inits != NULL && TREE_CODE (decl) == FUNCTION_DECL) for (x = &solaris_pending_inits; *x; x = &TREE_CHAIN (*x)) { tree name = TREE_PURPOSE (*x); if (DECL_NAME (decl) == name) { *attributes = tree_cons (get_identifier ("init"), NULL, *attributes); *attributes = tree_cons (get_identifier ("used"), NULL, *attributes); next = TREE_CHAIN (*x); ggc_free (*x); *x = next; break; } } if (solaris_pending_finis != NULL && TREE_CODE (decl) == FUNCTION_DECL) for (x = &solaris_pending_finis; *x; x = &TREE_CHAIN (*x)) { tree name = TREE_PURPOSE (*x); if (DECL_NAME (decl) == name) { *attributes = tree_cons (get_identifier ("fini"), NULL, *attributes); *attributes = tree_cons (get_identifier ("used"), NULL, *attributes); next = TREE_CHAIN (*x); ggc_free (*x); *x = next; break; } } }
static void lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib, struct data_in *data_in, tree expr) { DECL_SIZE (expr) = stream_read_tree (ib, data_in); DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in); DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in); /* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in dwarf2out.c. */ if (TREE_CODE (expr) == PARM_DECL) TREE_CHAIN (expr) = streamer_read_chain (ib, data_in); if ((TREE_CODE (expr) == VAR_DECL || TREE_CODE (expr) == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (expr)) SET_DECL_VALUE_EXPR (expr, stream_read_tree (ib, data_in)); if (TREE_CODE (expr) == VAR_DECL) { tree dexpr = stream_read_tree (ib, data_in); if (dexpr) SET_DECL_DEBUG_EXPR (expr, dexpr); } }
void solaris_output_init_fini (FILE *file, tree decl) { if (lookup_attribute ("init", DECL_ATTRIBUTES (decl))) { fprintf (file, "\t.pushsection\t\".init\"\n"); ASM_OUTPUT_CALL (file, decl); fprintf (file, "\t.popsection\n"); } if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl))) { fprintf (file, "\t.pushsection\t\".fini\"\n"); ASM_OUTPUT_CALL (file, decl); fprintf (file, "\t.popsection\n"); } }
static inline void check_decl (funct_state local, tree t, bool checking_write) { /* If the variable has the "used" attribute, treat it as if it had a been touched by the devil. */ if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) { local->pure_const_state = IPA_NEITHER; return; } /* Do not want to do anything with volatile except mark any function that uses one to be not const or pure. */ if (TREE_THIS_VOLATILE (t)) { local->pure_const_state = IPA_NEITHER; return; } /* Do not care about a local automatic that is not static. */ if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) return; /* Since we have dealt with the locals and params cases above, if we are CHECKING_WRITE, this cannot be a pure or constant function. */ if (checking_write) local->pure_const_state = IPA_NEITHER; if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) { /* If the front end set the variable to be READONLY and constant, we can allow this variable in pure or const functions but the scope is too large for our analysis to set these bits ourselves. */ if (TREE_READONLY (t) && DECL_INITIAL (t) && is_gimple_min_invariant (DECL_INITIAL (t))) ; /* Read of a constant, do not change the function state. */ else { /* Just a regular read. */ if (local->pure_const_state == IPA_CONST) local->pure_const_state = IPA_PURE; } } /* Compilation level statics can be read if they are readonly variables. */ if (TREE_READONLY (t)) return; /* Just a regular read. */ if (local->pure_const_state == IPA_CONST) local->pure_const_state = IPA_PURE; }
static bool decide_is_function_needed (struct cgraph_node *node, tree decl) { if (MAIN_NAME_P (DECL_NAME (decl)) && TREE_PUBLIC (decl)) { node->local.externally_visible = true; return true; } /* If the user told us it is used, then it must be so. */ if (node->local.externally_visible) return true; /* ??? If the assembler name is set by hand, it is possible to assemble the name later after finalizing the function and the fact is noticed in assemble_name then. This is arguably a bug. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) return true; /* With -fkeep-inline-functions we are keeping all inline functions except for extern inline ones. */ if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (decl) && !DECL_EXTERNAL (decl) && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))) return true; /* If we decided it was needed before, but at the time we didn't have the body of the function available, then it's still needed. We have to go back and re-check its dependencies now. */ if (node->needed) return true; /* Externally visible functions must be output. The exception is COMDAT functions that must be output only when they are needed. When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions declared inline and nested functions. These was optimized out in the original implementation and it is unclear whether we want to change the behavior here. */ if (((TREE_PUBLIC (decl) || (!optimize && !node->local.disregard_inline_limits && !DECL_DECLARED_INLINE_P (decl) && !node->origin)) && !flag_whole_program) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* Constructors and destructors are reachable from the runtime by some mechanism. */ if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)) return true; return false; }
int c_disregard_inline_limits (tree fn) { if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL) return 1; return (!flag_really_no_inline && DECL_DECLARED_INLINE_P (fn) && DECL_EXTERNAL (fn)); }
tree copy_var_decl (tree var, tree name, tree type) { tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type); TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var); TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var); DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var); DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var); DECL_IGNORED_P (copy) = DECL_IGNORED_P (var); DECL_CONTEXT (copy) = DECL_CONTEXT (var); TREE_NO_WARNING (copy) = TREE_NO_WARNING (var); TREE_USED (copy) = 1; DECL_SEEN_IN_BIND_EXPR_P (copy) = 1; DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var); return copy; }
void build_module_descriptor (long vers, tree attr) { tree decls, *chain = NULL; #ifdef OBJCPLUS push_lang_context (lang_name_c); /* extern "C" */ #endif objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE)); /* long version; */ decls = add_field_decl (long_integer_type_node, "version", &chain); /* long size; */ add_field_decl (long_integer_type_node, "size", &chain); /* char *name; */ add_field_decl (string_type_node, "name", &chain); /* struct _objc_symtab *symtab; */ add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (UTAG_SYMTAB))), "symtab", &chain); objc_finish_struct (objc_module_template, decls); /* Create an instance of "_objc_module". */ UOBJC_MODULES_decl = start_var_decl (objc_module_template, /* FIXME - why the conditional if the symbol is the same. */ flag_next_runtime ? "_OBJC_Module" : "_OBJC_Module"); /* This is the root of the metadata for defined classes and categories, it is referenced by the runtime and, therefore, needed. */ DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1; /* Squash `defined but not used' warning. */ TREE_USED (UOBJC_MODULES_decl) = 1; /* Allow the runtime to mark meta-data such that it can be assigned to target specific sections by the back-end. */ if (attr) DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr; finish_var_decl (UOBJC_MODULES_decl, init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl), vers)); #ifdef OBJCPLUS pop_lang_context (); #endif }
static bool gate_latent_entropy(void) { // don't bother with noreturn functions for now if (TREE_THIS_VOLATILE(current_function_decl)) return false; // gcc-4.5 doesn't discover some trivial noreturn functions if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds) == 0) return false; return lookup_attribute("latent_entropy", DECL_ATTRIBUTES(current_function_decl)) != NULL_TREE; }
static unsigned int instrument_assignments_plugin_exec(void) { #ifdef DEBUG fprintf(stderr, "* Inspecting function `%s'\n", FN_NAME); #endif basic_block bb; FOR_EACH_BB(bb) { gimple_stmt_iterator gsi; for (gsi = gsi_start_bb(bb) ; !gsi_end_p(gsi) ; gsi_next(&gsi)) { gimple curr_stmt = gsi_stmt(gsi); tree lhs = gimple_get_lhs(curr_stmt); // We only care about assignments to “real” variables – i.e. not // variable versions that were created as part of the transformation // to SSA form. if (gimple_code(curr_stmt) == GIMPLE_ASSIGN && lhs != NULL_TREE && TREE_CODE(lhs) != SSA_NAME && DECL_P(lhs)) { tree attrlist = DECL_ATTRIBUTES(lhs); tree attr = lookup_attribute("instrument", attrlist); // the princess is in another castle if (attr == NULL_TREE) continue; // read the variable id that was passed to the `instrument' // attribute const_tree arg = TREE_VALUE(TREE_VALUE(attr)); tree var_id = build_int_cst(NULL_TREE, tree_low_cst (arg, 1)); #ifdef DEBUG fprintf(stderr, " > found assignment to instrumented variable `%s': \n\t", get_name(lhs)); print_gimple_stmt(stderr, curr_stmt, 0, 0); fprintf(stderr, "\tbase address of `%s' is %p\n", get_name(lhs), get_base_address(lhs)); #endif // insert our instrumentation function before the current // statement and pass along the rhs (i.e. the new value) tree rhs = gimple_op(curr_stmt, 1); insert_instrumentation_fn(curr_stmt, var_id, rhs); } } } #ifdef DEBUG fprintf(stderr, "\n"); #endif return 0; }
static bool i386_pe_determine_dllexport_p (tree decl) { if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return false; /* Don't export local clones of dllexports. */ if (!TREE_PUBLIC (decl)) return false; if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return true; return false; }
varpool_node * varpool_create_variable_alias (tree alias, tree decl) { varpool_node *alias_node; gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); alias_node = varpool_node_for_decl (alias); alias_node->alias = true; alias_node->definition = true; alias_node->alias_target = decl; if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) alias_node->weakref = true; return alias_node; }
unsigned int i386_pe_section_type_flags (tree decl, const char *name, int reloc) { static htab_t htab; unsigned int flags; unsigned int **slot; /* The names we put in the hashtable will always be the unique versions given to us by the stringtable, so we can just use their addresses as the keys. */ if (!htab) htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); if (decl && TREE_CODE (decl) == FUNCTION_DECL) flags = SECTION_CODE; else if (decl && decl_readonly_section (decl, reloc)) flags = 0; else { flags = SECTION_WRITE; if (decl && TREE_CODE (decl) == VAR_DECL /* APPLE LOCAL begin mainline 2005-04-01 */ && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) flags |= SECTION_PE_SHARED; /* APPLE LOCAL end mainline 2005-04-01 */ } if (decl && DECL_ONE_ONLY (decl)) flags |= SECTION_LINKONCE; /* See if we already have an entry for this section. */ slot = (unsigned int **) htab_find_slot (htab, name, INSERT); if (!*slot) { *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); **slot = flags; } else { if (decl && **slot != flags) error ("%J'%D' causes a section type conflict", decl, decl); } return flags; }
static bool kernexec_cmodel_check(void) { tree section; if (ix86_cmodel != CM_KERNEL) return false; section = lookup_attribute("section", DECL_ATTRIBUTES(current_function_decl)); if (!section || !TREE_VALUE(section)) return true; section = TREE_VALUE(TREE_VALUE(section)); if (strncmp(TREE_STRING_POINTER(section), ".vsyscall_", 10)) return true; return false; }
void gcc_plugin_pre_genericize(void *gcc_data, void *user_data) { tree decl = (tree) gcc_data; // check for __base_ctor/__comp_ctor fake constructors. these correspond // directly to another constructor for the type, and we will replace // references to these with references to that other constructor. // we will see the other constructor first, and its TREE_CHAINs will // have the __base_ctor and __comp_ctor. tree chain = TREE_CHAIN(decl); if (chain && TREE_CODE(chain) == FUNCTION_DECL) { const char *chain_name = IDENTIFIER_POINTER(DECL_NAME(chain)); if (!strncmp(chain_name,"__base_ctor",11) || !strncmp(chain_name,"__base_dtor",11)) { bool *skip_info = (bool*) XIL_Associate(XIL_AscGlobal, "func_skip",chain); *skip_info = true; chain = TREE_CHAIN(chain); if (chain && TREE_CODE(chain) == FUNCTION_DECL) { const char *chain_name = IDENTIFIER_POINTER(DECL_NAME(chain)); if (!strncmp(chain_name,"__comp_ctor",11) || !strncmp(chain_name,"__comp_dtor",11)) { skip_info = (bool*) XIL_Associate(XIL_AscGlobal, "func_skip",chain); *skip_info = true; } } } } // if this is the __base_ctor or __comp_ctor, skip it. bool *skip_info = (bool*) XIL_Associate(XIL_AscGlobal, "func_skip",decl); if (*skip_info) return; // check for annotations on this function. tree attr = DECL_ATTRIBUTES(decl); while (attr) { XIL_ProcessAnnotationAttr(decl, attr, NULL, NULL); attr = TREE_CHAIN(attr); } XIL_GenerateBlock(decl); // future parameter declarations will be for a different function. xil_pending_param_decls = NULL; }
static tree handle_nocapture_attribute(tree *node, tree __unused name, tree args, int __unused flags, bool *no_add_attrs) { tree orig_attr, arg; *no_add_attrs = true; switch (TREE_CODE(*node)) { case FUNCTION_DECL: case FUNCTION_TYPE: case METHOD_TYPE: break; case TYPE_DECL: { const_tree fntype = TREE_TYPE(*node); if (TREE_CODE(fntype) == POINTER_TYPE) fntype = TREE_TYPE(fntype); if (TREE_CODE(fntype) == FUNCTION_TYPE || TREE_CODE(fntype) == METHOD_TYPE) break; // FALLTHROUGH } default: error("%s: %qE attribute only applies to functions", __func__, name); debug_tree(*node); return NULL_TREE; } for (arg = args; arg; arg = TREE_CHAIN(arg)) { tree position = TREE_VALUE(arg); if (TREE_CODE(position) != INTEGER_CST) { error("%s: parameter isn't an integer", __func__); debug_tree(arg); return NULL_TREE; } } orig_attr = lookup_attribute("nocapture", DECL_ATTRIBUTES(*node)); if (orig_attr) chainon(TREE_VALUE(orig_attr), args); else *no_add_attrs = false; return NULL_TREE; }
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; /* Also mark class members of exported classes with dllexport. */ if (associated_type (decl) && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (associated_type (decl)))) return i386_pe_type_dllexport_p (decl); return false; }
void handle_pre_generic (void *event_data, void *data) { tree fndecl = (tree) event_data; tree arg; for (arg = DECL_ARGUMENTS(fndecl); arg; arg = DECL_CHAIN (arg)) { tree attr; for (attr = DECL_ATTRIBUTES (arg); attr; attr = TREE_CHAIN (attr)) { tree attrname = TREE_PURPOSE (attr); tree attrargs = TREE_VALUE (attr); warning (0, G_("attribute '%s' on param '%s' of function %s"), IDENTIFIER_POINTER (attrname), IDENTIFIER_POINTER (DECL_NAME (arg)), IDENTIFIER_POINTER (DECL_NAME (fndecl)) ); } } }
static int msp430_get_stack_reserve(void) { int stack_reserve = 0; tree ss = lookup_attribute ("reserve", DECL_ATTRIBUTES (current_function_decl)); if (ss) { ss = TREE_VALUE (ss); if (ss) { ss = TREE_VALUE (ss); if (ss) stack_reserve = TREE_INT_CST_LOW (ss); stack_reserve++; stack_reserve &= ~1; } } return stack_reserve; }
/// AddAnnotateAttrsToGlobal - Adds decls that have a /// annotate attribute to a vector to be emitted later. void AddAnnotateAttrsToGlobal(GlobalValue *GV, tree decl) { // Handle annotate attribute on global. tree annotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES (decl)); // Get file and line number Constant *lineNo = ConstantInt::get(Type::Int32Ty, DECL_SOURCE_LINE(decl)); Constant *file = ConvertMetadataStringToGV(DECL_SOURCE_FILE(decl)); const Type *SBP= PointerType::get(Type::Int8Ty); file = ConstantExpr::getBitCast(file, SBP); // There may be multiple annotate attributes. Pass return of lookup_attr // to successive lookups. while (annotateAttr) { // Each annotate attribute is a tree list. // Get value of list which is our linked list of args. tree args = TREE_VALUE(annotateAttr); // Each annotate attribute may have multiple args. // Treat each arg as if it were a separate annotate attribute. for (tree a = args; a; a = TREE_CHAIN(a)) { // Each element of the arg list is a tree list, so get value tree val = TREE_VALUE(a); // Assert its a string, and then get that string. assert(TREE_CODE(val) == STRING_CST && "Annotate attribute arg should always be a string"); Constant *strGV = TreeConstantToLLVM::EmitLV_STRING_CST(val); Constant *Element[4] = {ConstantExpr::getBitCast(GV,SBP), ConstantExpr::getBitCast(strGV,SBP), file, lineNo}; AttributeAnnotateGlobals.push_back(ConstantStruct::get(Element, 4, false)); } // Get next annotate attribute. annotateAttr = TREE_CHAIN(annotateAttr); if (annotateAttr) annotateAttr = lookup_attribute("annotate", annotateAttr); } }
void i386_pe_asm_named_section (const char *name, unsigned int flags, tree decl) { char flagchars[8], *f = flagchars; if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0) /* readonly data */ { *f++ ='d'; /* This is necessary for older versions of gas. */ *f++ ='r'; } else { if (flags & SECTION_CODE) *f++ = 'x'; if (flags & SECTION_WRITE) *f++ = 'w'; if (flags & SECTION_PE_SHARED) *f++ = 's'; } *f = '\0'; fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); if (flags & SECTION_LINKONCE) { /* Functions may have been compiled at various levels of optimization so we can't use `same_size' here. Instead, have the linker pick one, without warning. If 'selectany' attibute has been specified, MS compiler sets 'discard' characteristic, rather than telling linker to warn of size or content mismatch, so do the same. */ /* APPLE LOCAL begin mainline 2005-04-01 */ bool discard = (flags & SECTION_CODE) || lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)); fprintf (asm_out_file, "\t.linkonce %s\n", (discard ? "discard" : "same_size")); /* APPLE LOCAL end mainline 2005-10-12 */ } }
int c_cannot_inline_tree_fn (tree *fnp) { tree fn = *fnp; bool do_warning = (warn_inline && DECL_INLINE (fn) && DECL_DECLARED_INLINE_P (fn) && !DECL_IN_SYSTEM_HEADER (fn)); if (flag_really_no_inline && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL) { if (do_warning) warning (OPT_Winline, "function %q+F can never be inlined because it " "is suppressed using -fno-inline", fn); goto cannot_inline; } /* Don't auto-inline anything that might not be bound within this unit of translation. */ if (!DECL_DECLARED_INLINE_P (fn) && !targetm.binds_local_p (fn)) { if (do_warning) warning (OPT_Winline, "function %q+F can never be inlined because it " "might not be bound within this unit of translation", fn); goto cannot_inline; } if (!function_attribute_inlinable_p (fn)) { if (do_warning) warning (OPT_Winline, "function %q+F can never be inlined because it " "uses attributes conflicting with inlining", fn); goto cannot_inline; } return 0; cannot_inline: DECL_UNINLINABLE (fn) = 1; return 1; }
int i386_pe_dllexport_p (tree decl) { if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; /* APPLE LOCAL begin mainline 2005-10-12 */ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return 1; /* Also mark class members of exported classes with dllexport. */ if (associated_type (decl) && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (associated_type (decl)))) return i386_pe_type_dllexport_p (decl); /* APPLE LOCAL end mainline 2005-10-12 */ return 0; }
/* Return false if the function FNDECL cannot be inlined on account of its attributes, true otherwise. */ bool function_attribute_inlinable_p (const_tree fndecl) { if (targetm.attribute_table) { const_tree a; for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) { const_tree name = TREE_PURPOSE (a); int i; for (i = 0; targetm.attribute_table[i].name != NULL; i++) if (is_attribute_p (targetm.attribute_table[i].name, name)) return targetm.function_attribute_inlinable_p (fndecl); } } return true; }