Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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");
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
  }
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
// 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));
}
Esempio n. 10
0
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));
  
}
Esempio n. 11
0
/* 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.  */
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}