static unsigned get_combined_location (location_t loc, tree decl) { /* TODO: allow more bits for line and less bits for discriminator. */ if (LOCATION_LINE (loc) - DECL_SOURCE_LINE (decl) >= (1<<16)) warning_at (loc, OPT_Woverflow, "offset exceeds 16 bytes"); return ((LOCATION_LINE (loc) - DECL_SOURCE_LINE (decl)) << 16); }
void declare_function_name () { tree decl, init; char *name, *printable_name; if (current_function_decl == NULL) { name = ""; printable_name = "top level"; } else { char *kind = "function"; if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) kind = "method"; /* Allow functions to be nameless (such as artificial ones). */ if (DECL_NAME (current_function_decl)) name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); else name = ""; printable_name = (*decl_printable_name) (current_function_decl, &kind); } push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"), char_array_type_node); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (name) + 1, name); TREE_TYPE (init) = char_array_type_node; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"), char_array_type_node); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (printable_name) + 1, printable_name); TREE_TYPE (init) = char_array_type_node; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); }
tree pushdecl (tree decl) { if (global_bindings_p ()) DECL_CONTEXT (decl) = current_translation_unit; else { /* External objects aren't nested. For debug info insert a copy of the decl into the binding level. */ if (DECL_EXTERNAL (decl)) { tree orig = decl; decl = copy_node (decl); DECL_CONTEXT (orig) = NULL_TREE; } DECL_CONTEXT (decl) = current_function_decl; } /* Put the declaration on the list. */ DECL_CHAIN (decl) = current_binding_level->names; current_binding_level->names = decl; /* For the declaration of a type, set its name if it is not already set. */ if (TREE_CODE (decl) == TYPE_DECL && TYPE_NAME (TREE_TYPE (decl)) == 0) { if (DECL_SOURCE_LINE (decl) == 0) TYPE_NAME (TREE_TYPE (decl)) = decl; else TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl); } return decl; }
static void dump_odr_type (FILE *f, odr_type t, int indent=0) { unsigned int i; fprintf (f, "%*s type %i: ", indent * 2, "", t->id); print_generic_expr (f, t->type, TDF_SLIM); fprintf (f, "%s\n", t->anonymous_namespace ? " (anonymous namespace)":""); if (TYPE_NAME (t->type)) { fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "", DECL_SOURCE_FILE (TYPE_NAME (t->type)), DECL_SOURCE_LINE (TYPE_NAME (t->type))); } if (t->bases.length ()) { fprintf (f, "%*s base odr type ids: ", indent * 2, ""); for (i = 0; i < t->bases.length (); i++) fprintf (f, " %i", t->bases[i]->id); fprintf (f, "\n"); } if (t->derived_types.length ()) { fprintf (f, "%*s derived types:\n", indent * 2, ""); for (i = 0; i < t->derived_types.length (); i++) dump_odr_type (f, t->derived_types[i], indent + 1); } fprintf (f, "\n"); }
struct RecordInfo* createRecordInfo(const tree type_decl, const tree record_type) { struct RecordInfo* ri = (struct RecordInfo*) xcalloc(1, sizeof(struct RecordInfo)); ri->name = xstrdup(type_as_string(record_type, 0)); ri->fileName = xstrdup(DECL_SOURCE_FILE(type_decl)); ri->line = DECL_SOURCE_LINE(type_decl); ri->size = TREE_INT_CST_LOW(TYPE_SIZE(record_type)); ri->align = TYPE_ALIGN(record_type); ri->isInstance = CLASSTYPE_TEMPLATE_INSTANTIATION(record_type); ri->firstField = SIZE_MAX; ri->estMinSize = SIZE_MAX; size_t fieldCapacity = 4; ri->fields = (struct FieldInfo**)xmalloc(fieldCapacity * sizeof(struct FieldInfo*)); // Fields/variables/constants/functions are chained via TYPE_FIELDS of record for (tree field = TYPE_FIELDS(record_type); field; field = TREE_CHAIN(field)) { // We're intersted in fields only if (TREE_CODE(field) != FIELD_DECL) continue; struct FieldInfo* fi = createFieldInfo(field); ri->fieldCount++; // Allocate more storage for fields if needed if (ri->fieldCount > fieldCapacity) { fieldCapacity *= 2; ri->fields = (struct FieldInfo**)xrealloc(ri->fields, fieldCapacity * sizeof(struct FieldInfo*)); } ri->fields[ri->fieldCount - 1] = fi; // Mark record as containing bit-fields if (fi->isBitField) ri->hasBitFields = true; // Field is base/vptr if (fi->isSpecial) { // If we encounter special field somewhere after regular fields // it means class has virtual base. if (ri->firstField != SIZE_MAX) ri->hasVirtualBase = true; } else if (ri->firstField == SIZE_MAX) ri->firstField = ri->fieldCount - 1; } return ri; }
bool vect_print_dump_info (enum vect_verbosity_levels vl) { if (vl > vect_verbosity_level) return false; if (!current_function_decl || !vect_dump) return false; if (vect_location == UNKNOWN_LOC) fprintf (vect_dump, "\n%s:%d: note: ", DECL_SOURCE_FILE (current_function_decl), DECL_SOURCE_LINE (current_function_decl)); else fprintf (vect_dump, "\n%d: ", LOC_LINE (vect_location)); return true; }
/// 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 declare_function_name () { tree decl, type, init; char *name, *printable_name; int len; if (current_function_decl == NULL) { name = ""; printable_name = "top level"; } else { char *kind = "function"; if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) kind = "method"; /* Allow functions to be nameless (such as artificial ones). */ if (DECL_NAME (current_function_decl)) name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); else name = ""; printable_name = (*decl_printable_name) (current_function_decl, &kind); } /* If the default size of char arrays isn't big enough for the name, make a bigger one. */ len = strlen (name) + 1; type = char_array_type_node; if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node))) < len) type = build_array_type (char_type_node, build_index_type (build_int_2 (len, 0))); push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (len, name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); len = strlen (printable_name) + 1; type = char_array_type_node; if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node))) < len) type = build_array_type (char_type_node, build_index_type (build_int_2 (len, 0))); push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (len, printable_name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); }
// generate a block for a declaration, which is either a function or global. void XIL_GenerateBlock(tree decl) { memset(&xil_active_env, 0, sizeof(struct XIL_BlockEnv)); XIL_Var xil_var = NULL; int annot_type = 0; if (xil_has_annotation) { gcc_assert(annotation_name); gcc_assert(TREE_CODE(decl) == FUNCTION_DECL); // get the name of the function/global/type being annotated; this looks at // any annot_global / annot_source attributes on the decl. const char *full_name = XIL_GlobalName(decl); const char *name = XIL_SourceName(decl); if (!strcmp(annotation_class, "func")) xil_var = XIL_VarFunc(full_name, name); else if (!strcmp(annotation_class, "init")) xil_var = XIL_VarGlob(full_name, name); else if (!strcmp(annotation_class, "comp")) { xil_var = XIL_VarGlob(full_name, name); annot_type = 1; } gcc_assert(xil_var); } else { xil_var = XIL_TranslateVar(decl); } tree type = TREE_TYPE(decl); XIL_Type xil_type = XIL_TranslateType(type); // fixup the type for destructors. these have an __in_chrg argument that // doesn't show up when the functions are called. if (XIL_IsDestructor(decl)) { if (TREE_CODE(type) == METHOD_TYPE) { tree base_type = TYPE_METHOD_BASETYPE(type); XIL_Type xil_base_type = XIL_TranslateType(base_type); const char *this_csu = XIL_GetTypeCSUName(xil_base_type); xil_type = XIL_TypeFunction(XIL_TypeVoid(), this_csu, false, NULL, 0); } else { TREE_UNEXPECTED(decl); } } // don't deal with extern functions/globals. we will see the definition later // (hopefully!), including the complete type for arrays and any initializer. // we still want to process the type for these in case anonymous types are // being used. if (DECL_EXTERNAL(decl)) return; // parse the annotation kind. XIL_AnnotationKind use_kind = 0; if (annotation_kind) { #define XIL_TEST_ANNOT(_, STR, VALUE) \ if (!strcmp(annotation_kind, STR)) use_kind = VALUE; XIL_ITERATE_ANNOT(XIL_TEST_ANNOT) #undef XIL_TEST_ANNOT gcc_assert(use_kind); } const char *name = XIL_GetVarName(xil_var); xil_active_env.decl = decl; xil_active_env.decl_name = name; XIL_SetActiveBlock(xil_var, annotation_name, use_kind, annot_type); const char *decl_file = DECL_SOURCE_FILE(decl); int decl_line = DECL_SOURCE_LINE(decl); // get the begin file/line for a function definition. this is somewhat // trickier than might be expected. the decl's location sometimes comes from // a header file and not the definition we are interested in, while the // result variable's location corresponds to the ')' for the function, // not the function symbol which we want. solution: use the decl's location // unless it looks like it came from a declaration (in a different file // than the result, or many lines earlier). if (TREE_CODE(decl) == FUNCTION_DECL) { tree result = DECL_RESULT(decl); if (result) { const char *res_decl_file = DECL_SOURCE_FILE(result); int res_decl_line = DECL_SOURCE_LINE(result); if (strcmp(decl_file, res_decl_file) || res_decl_line > decl_line + 10) { decl_file = res_decl_file; decl_line = res_decl_line; } } } XIL_Location begin_loc = XIL_MakeLocation(decl_file, decl_line); // get the end file/line from the parser's current position, unless the // parser has no current position. const char *end_file = input_filename; int end_line = input_line; if (!input_filename) { end_file = decl_file; end_line = decl_line; } // the begin/end points of the declaration should be in the same file. if (strcmp(decl_file, end_file)) TREE_UNEXPECTED(decl); XIL_Location end_loc = XIL_MakeLocation(end_file, end_line); XIL_CFGSetCommand(xil_command); XIL_CFGSetBeginLocation(begin_loc); XIL_CFGSetEndLocation(end_loc); xil_active_env.entry_point = xil_active_env.last_point = XIL_CFGAddPoint(begin_loc); xil_active_env.exit_point = XIL_CFGAddPoint(end_loc); XIL_CFGSetEntryPoint(xil_active_env.entry_point); XIL_CFGSetExitPoint(xil_active_env.exit_point); // add the decl variable to the active CFG. override any previous type we // had for the variable, to account for seeing multiple definitions of // a variable, which gcc allows, e.g. int buf[]; int buf[10]; if (!xil_has_annotation) XIL_CFGAddVar(xil_var, xil_type, 1); // current point for traversal of the function/initializer. XIL_PPoint point = xil_active_env.entry_point; bool is_function = (TREE_CODE(decl) == FUNCTION_DECL); if (is_function) { // handling for function definitions. tree defn = DECL_SAVED_TREE(decl); // add the parameters to the active CFG. skip this for destructors // to avoid the __in_chrg argument. if (!XIL_IsDestructor(decl)) { tree param = DECL_ARGUMENTS(decl); while (param) { gcc_assert(TREE_CODE(param) == PARM_DECL); XIL_TranslateVar(param); // forces insertion of the parameter. param = TREE_CHAIN(param); } } // generate edges for the function body. XIL_ActivePushScope(); MAKE_ENV(body_env, &point, NULL); XIL_TranslateTree(&body_env, defn); XIL_ActivePopScope(); } else { // handling for global variables. tree initial = DECL_INITIAL(decl); // make an assignment for any initializer. for compound initializers // this may get fairly involved. if (initial) { MAKE_ENV(initial_env, &point, NULL); initial_env.result_assign = XIL_ExpVar(xil_var); initial_env.result_assign_type = xil_type; XIL_TranslateTree(&initial_env, initial); } } // connect any fall through to the exit point. XIL_CFGEdgeSkip(point, xil_active_env.exit_point); // for debugging, bail out of compilation at the first error. //if (xil_active_env.dropped) { // printf("XIL: Bailing out\n"); // exit(1); //} // process any annotations read in from file for the function, // now that we know all locals. int count = XIL_GetAnnotationCount(name, !is_function, false); int ind = 0; for (; ind < count; ind++) { const char *where; const char *point_text, *annot_text; int trusted; XIL_GetAnnotation(name, !is_function, false, ind, &where, &point_text, &annot_text, &trusted); XIL_ProcessAnnotationRead(decl, where, point_text, annot_text, trusted); } // process annotations discovered for CSU types. while (xil_active_env.annots) { struct XIL_PendingAnnotation *annot = xil_active_env.annots; xil_active_env.annots = annot->next; XIL_ProcessAnnotationAttr(annot->type, annot->attr, NULL, NULL); } XIL_ClearActiveBlock(xil_active_env.dropped); XIL_ClearAssociate(XIL_AscBlock); memset(&xil_active_env, 0, sizeof(struct XIL_BlockEnv)); }
tree tree_code_create_variable (unsigned int storage_class, unsigned char* chars, unsigned int length, unsigned int expression_type, tree init, unsigned char* filename, int lineno) { tree var_type; tree var_id; tree var_decl; /* 1. Build the type. */ var_type = get_type_for_numeric_type (expression_type); /* 2. Build the name. */ if (chars[length] != 0) abort (); /* Should be null terminated. */ var_id = get_identifier ((const char*)chars); /* 3. Build the decl and set up init. */ var_decl = build_decl (VAR_DECL, var_id, var_type); /* 3a. Initialization. */ if (init) DECL_INITIAL (var_decl) = build1 (CONVERT_EXPR, var_type, init); else DECL_INITIAL (var_decl) = NULL_TREE; /* 4. Compute size etc. */ layout_decl (var_decl, 0); if (TYPE_SIZE (var_type) == 0) abort (); /* Did not calculate size. */ DECL_CONTEXT (var_decl) = current_function_decl; DECL_SOURCE_FILE (var_decl) = (const char *)filename; DECL_SOURCE_LINE (var_decl) = lineno; /* Set the storage mode and whether only visible in the same file. */ switch (storage_class) { case STATIC_STORAGE: TREE_STATIC (var_decl) = 1; TREE_PUBLIC (var_decl) = 0; break; case AUTOMATIC_STORAGE: TREE_STATIC (var_decl) = 0; TREE_PUBLIC (var_decl) = 0; break; case EXTERNAL_DEFINITION_STORAGE: TREE_STATIC (var_decl) = 0; TREE_PUBLIC (var_decl) = 1; break; case EXTERNAL_REFERENCE_STORAGE: DECL_EXTERNAL (var_decl) = 1; TREE_PUBLIC (var_decl) = 0; break; default: abort (); } /* This should really only be set if the variable is used. */ TREE_USED (var_decl) = 1; /* Expand declaration and initial value if any. */ if (TREE_STATIC (var_decl)) rest_of_decl_compilation (var_decl, 0, 0, 0); else { expand_decl (var_decl); if (DECL_INITIAL (var_decl)) expand_decl_init (var_decl); } return pushdecl (copy_node (var_decl)); }
/* Output code for start of function; the decl of the function is in PREV_SAVED (as created by tree_code_create_function_prototype), the function is at line number LINENO in file FILENAME. The parameter details are in the lists PARMS. Returns nothing. */ void tree_code_create_function_initial (tree prev_saved, unsigned char* filename, int lineno, struct prod_token_parm_item* parms) { tree fn_decl; tree param_decl; tree next_param; tree first_param; tree parm_decl; tree parm_list; tree resultdecl; struct prod_token_parm_item* this_parm; struct prod_token_parm_item* parm; fn_decl = prev_saved; if (!fn_decl) abort (); /* Output message if not -quiet. */ announce_function (fn_decl); /* This has something to do with forcing output also. */ pushdecl (fn_decl); /* Set current function for error msgs etc. */ current_function_decl = fn_decl; DECL_INITIAL (fn_decl) = error_mark_node; DECL_SOURCE_FILE (fn_decl) = (const char *)filename; DECL_SOURCE_LINE (fn_decl) = lineno; /* Prepare creation of rtl for a new function. */ resultdecl = DECL_RESULT (fn_decl) = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl))); DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl; DECL_SOURCE_FILE (resultdecl) = (const char *)filename; DECL_SOURCE_LINE (resultdecl) = lineno; /* Work out the size. ??? is this needed. */ layout_decl (DECL_RESULT (fn_decl), 0); /* Make the argument variable decls. */ parm_list = NULL_TREE; for (parm = parms; parm; parm = parm->tp.par.next) { parm_decl = build_decl (PARM_DECL, get_identifier ((const char*) (parm->tp.par.variable_name)), get_type_for_numeric_type (parm->type)); /* Some languages have different nominal and real types. */ DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl); if (!DECL_ARG_TYPE (parm_decl)) abort (); if (!fn_decl) abort (); DECL_CONTEXT (parm_decl) = fn_decl; DECL_SOURCE_FILE (parm_decl) = (const char *)filename; DECL_SOURCE_LINE (parm_decl) = lineno; parm_list = chainon (parm_decl, parm_list); } /* Back into reverse order as the back end likes them. */ parm_list = nreverse (parm_list); DECL_ARGUMENTS (fn_decl) = parm_list; /* Save the decls for use when the args are referred to. */ for (param_decl = DECL_ARGUMENTS (fn_decl), this_parm = parms; param_decl; param_decl = TREE_CHAIN (param_decl), this_parm = this_parm->tp.par.next) { if (!this_parm) abort (); /* Too few. */ *this_parm->tp.par.where_to_put_var_tree = param_decl; } if (this_parm) abort (); /* Too many. */ /* Output the decl rtl (not the rtl for the function code). ???. If the function is not defined in this file, when should you execute this? */ make_decl_rtl (fn_decl, NULL); /* Use filename/lineno from above. */ init_function_start (fn_decl, (const char *)filename, lineno); /* Create rtl for startup code of function, such as saving registers. */ expand_function_start (fn_decl, 0); /* Function.c requires a push at the start of the function. that looks like a bug to me but let's make it happy. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (2); /* Put the parameters into the symbol table. */ for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl)); param_decl; param_decl = next_param) { next_param = TREE_CHAIN (param_decl); TREE_CHAIN (param_decl) = NULL; /* layout_decl (param_decl, 0); Already done in build_decl tej 13/4/2002. */ pushdecl (param_decl); if (DECL_CONTEXT (param_decl) != current_function_decl) abort (); } /* Store back the PARM_DECL nodes. They appear in the right order. */ DECL_ARGUMENTS (fn_decl) = getdecls (); /* Force it to be output, else may be solely inlined. */ TREE_ADDRESSABLE (fn_decl) = 1; /* Stop -O3 from deleting it. */ TREE_USED (fn_decl) = 1; /* Add a new level to the debugger symbol table. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (0); emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ }
tree tree_code_create_function_prototype (unsigned char* chars, unsigned int storage_class, unsigned int ret_type, struct prod_token_parm_item* parms, unsigned char* filename, int lineno) { tree id; struct prod_token_parm_item* parm; tree type_list = NULL_TREE; tree type_node; tree fn_type; tree fn_decl; /* Build the type. */ id = get_identifier ((const char*)chars); for (parm = parms; parm; parm = parm->tp.par.next) { type_node = get_type_for_numeric_type (parm->type); type_list = tree_cons (NULL_TREE, type_node, type_list); } /* Last parm if void indicates fixed length list (as opposed to printf style va_* list). */ type_list = tree_cons (NULL_TREE, void_type_node, type_list); /* The back end needs them in reverse order. */ type_list = nreverse (type_list); type_node = get_type_for_numeric_type (ret_type); fn_type = build_function_type (type_node, type_list); id = get_identifier ((const char*)chars); fn_decl = build_decl (FUNCTION_DECL, id, fn_type); DECL_CONTEXT (fn_decl) = NULL_TREE; /* Nested functions not supported here. */ DECL_SOURCE_FILE (fn_decl) = (const char *)filename; /* if (lineno > 1000000) ; */ /* Probably the line # is rubbish because someone forgot to set the line number - and unfortunately impossible line #s are used as magic flags at various times. The longest known function for example is about 550,000 lines (it was written in COBOL). */ DECL_SOURCE_LINE (fn_decl) = lineno; TREE_USED (fn_decl) = 1; /* Real name (optional). */ SET_DECL_ASSEMBLER_NAME (fn_decl, DECL_NAME (fn_decl)); TREE_PUBLIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 0; TREE_STATIC (fn_decl) = 0; switch (storage_class) { case STATIC_STORAGE: TREE_PUBLIC (fn_decl) = 0; break; case EXTERNAL_DEFINITION_STORAGE: TREE_PUBLIC (fn_decl) = 1; TREE_STATIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 0; break; case EXTERNAL_REFERENCE_STORAGE: TREE_PUBLIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 1; break; case AUTOMATIC_STORAGE: default: abort (); } /* Process declaration of function defined elsewhere. */ rest_of_decl_compilation (fn_decl, NULL, 1, 0); return fn_decl; }
void write_resource_constructor (void) { tree init_name, init_type, init_decl; tree iter; location_t saved_loc = input_location; char *resource_ctor_name; /* Only do work if required. */ if (resources == NULL_TREE) return; resource_ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_resource", NULL); init_name = get_identifier (resource_ctor_name); free (resource_ctor_name); init_type = build_function_type (void_type_node, end_params_node); init_decl = build_decl (FUNCTION_DECL, init_name, init_type); DECL_SOURCE_LINE (init_decl) = 0; SET_DECL_ASSEMBLER_NAME (init_decl, init_name); TREE_STATIC (init_decl) = 1; current_function_decl = init_decl; DECL_RESULT (init_decl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node); /* It can be a static function as long as collect2 does not have to scan the object file to find its ctor/dtor routine. */ TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors; pushlevel (0); make_decl_rtl (init_decl, NULL); init_function_start (init_decl); expand_function_start (init_decl, 0); /* Write out entries in the same order in which they were defined. */ for (iter = nreverse (resources); iter != NULL_TREE; iter = TREE_CHAIN (iter)) { emit_library_call (registerResource_libfunc, 0, VOIDmode, 1, expand_expr (build_address_of (TREE_VALUE (iter)), 0, Pmode, 0), Pmode); } input_location = DECL_SOURCE_LOCATION (init_decl); expand_function_end (); poplevel (1, 0, 1); { /* Force generation, even with -O3 or deeper. Gross hack. FIXME. */ int saved_flag = flag_inline_functions; flag_inline_functions = 0; rest_of_compilation (init_decl); flag_inline_functions = saved_flag; } current_function_decl = NULL_TREE; (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0), DEFAULT_INIT_PRIORITY); input_location = saved_loc; }