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"); }
void xcoffout_declare_function (FILE *file, tree decl, const char *name) { size_t len; if (*name == '*') name++; len = strlen (name); if (name[len - 1] == ']') { char *n = alloca (len - 3); memcpy (n, name, len - 4); n[len - 4] = '\0'; name = n; } /* Any pending .bi or .ei must occur before the .function pseudo op. Otherwise debuggers will think that the function is in the previous file and/or at the wrong line number. */ xcoffout_source_file (file, DECL_SOURCE_FILE (decl), 0); dbxout_symbol (decl, 0); /* .function NAME, TOP, MAPPING, TYPE, SIZE 16 and 044 are placeholders for backwards compatibility */ fprintf (file, "\t.function .%s,.%s,16,044,FE..%s-.%s\n", name, name, name, name); }
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; }
static tree mf_file_function_line_tree (location_t location) { expanded_location xloc = expand_location (location); const char *file = NULL, *colon, *line, *op, *name, *cp; char linecolbuf[30]; /* Enough for two decimal numbers plus a colon. */ char *string; tree result; /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */ file = xloc.file; if (file == NULL && current_function_decl != NULL_TREE) file = DECL_SOURCE_FILE (current_function_decl); if (file == NULL) file = "<unknown file>"; if (xloc.line > 0) { #ifdef USE_MAPPED_LOCATION if (xloc.column > 0) sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column); else #endif sprintf (linecolbuf, "%d", xloc.line); colon = ":"; line = linecolbuf; } else colon = line = ""; /* Add (FUNCTION). */ name = lang_hooks.decl_printable_name (current_function_decl, 1); if (name) { op = " ("; cp = ")"; } else op = name = cp = ""; string = concat (file, colon, line, op, name, cp, NULL); result = mf_build_string (string); free (string); return result; }
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); } }
static tree mf_varname_tree (tree decl) { const char *buf_contents; tree result; gcc_assert (decl); pretty_printer buf; /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */ { expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl)); const char *sourcefile; unsigned sourceline = xloc.line; unsigned sourcecolumn = 0; sourcecolumn = xloc.column; sourcefile = xloc.file; if (sourcefile == NULL && current_function_decl != NULL_TREE) sourcefile = DECL_SOURCE_FILE (current_function_decl); if (sourcefile == NULL) sourcefile = "<unknown file>"; pp_string (&buf, sourcefile); if (sourceline != 0) { pp_colon (&buf); pp_decimal_int (&buf, sourceline); if (sourcecolumn != 0) { pp_colon (&buf); pp_decimal_int (&buf, sourcecolumn); } } } if (current_function_decl != NULL_TREE) { /* Add (FUNCTION) */ pp_string (&buf, " ("); { const char *funcname = NULL; if (DECL_NAME (current_function_decl)) funcname = lang_hooks.decl_printable_name (current_function_decl, 1); if (funcname == NULL) funcname = "anonymous fn"; pp_string (&buf, funcname); } pp_string (&buf, ") "); } else pp_space (&buf); /* Add <variable-declaration>, possibly demangled. */ { const char *declname = NULL; if (DECL_NAME (decl) != NULL) { if (strcmp ("GNU C++", lang_hooks.name) == 0) { /* The gcc/cp decl_printable_name hook doesn't do as good a job as the libiberty demangler. */ declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)), DMGL_AUTO | DMGL_VERBOSE); } if (declname == NULL) declname = lang_hooks.decl_printable_name (decl, 3); } if (declname == NULL) declname = "<unnamed variable>"; pp_string (&buf, declname); } /* Return the lot as a new STRING_CST. */ buf_contents = ggc_strdup (pp_formatted_text (&buf)); result = mf_build_string (buf_contents); pp_clear_output_area (&buf); return result; }
// 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; }