Ejemplo n.º 1
0
static void
gfc_be_parse_file (void)
{
  gfc_create_decls ();
  gfc_parse_file ();
  gfc_generate_constructors ();

  /* Clear the binding level stack.  */
  while (!global_bindings_p ())
    poplevel (0, 0);

  /* Finalize all of the globals.

     Emulated tls lowering needs to see all TLS variables before we
     call finalize_compilation_unit.  The C/C++ front ends manage this
     by calling decl_rest_of_compilation on each global and static
     variable as they are seen.  The Fortran front end waits until
     here.  */
  for (tree decl = getdecls (); decl ; decl = DECL_CHAIN (decl))
    rest_of_decl_compilation (decl, true, true);

  /* Switch to the default tree diagnostics here, because there may be
     diagnostics before gfc_finish().  */
  gfc_diagnostics_finish ();

  global_decl_processing ();
}
Ejemplo n.º 2
0
tree
gfc_finish_block (stmtblock_t * stmtblock)
{
  tree decl;
  tree expr;
  tree block;

  expr = stmtblock->head;
  if (!expr)
    expr = build_empty_stmt ();

  stmtblock->head = NULL_TREE;

  if (stmtblock->has_scope)
    {
      decl = getdecls ();

      if (decl)
	{
	  block = poplevel (1, 0, 0);
	  expr = build3_v (BIND_EXPR, decl, expr, block);
	}
      else
	poplevel (0, 0, 0);
    }

  return expr;
}
Ejemplo n.º 3
0
static void
gfc_write_global_declarations (void)
{
  tree decl;

  /* Finalize all of the globals.  */
  for (decl = getdecls(); decl ; decl = DECL_CHAIN (decl))
    rest_of_decl_compilation (decl, true, true);

  write_global_declarations ();
}
Ejemplo n.º 4
0
void
c_objc_common_finish_file (void)
{
  if (pch_file)
    c_common_write_pch ();

  /* If multiple translation units were built, copy information between
     them based on linkage rules.  */
  merge_translation_unit_decls ();

  cgraph_finalize_compilation_unit ();
  cgraph_optimize ();

  if (static_ctors)
    {
      tree body = start_cdtor ('I');

      for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
	c_expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
						 NULL_TREE));

      finish_cdtor (body);
    }

  if (static_dtors)
    {
      tree body = start_cdtor ('D');

      for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
	c_expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
						 NULL_TREE));

      finish_cdtor (body);
    }

  {
    int flags;
    FILE *stream = dump_begin (TDI_all, &flags);

    if (stream)
      {
	dump_node (getdecls (), flags & ~TDF_SLIM, stream);
	dump_end (TDI_all, stream);
      }
  }
}
Ejemplo n.º 5
0
void
gfc_merge_block_scope (stmtblock_t * block)
{
  tree decl;
  tree next;

  gcc_assert (block->has_scope);
  block->has_scope = 0;

  /* Remember the decls in this scope.  */
  decl = getdecls ();
  poplevel (0, 0, 0);

  /* Add them to the parent scope.  */
  while (decl != NULL_TREE)
    {
      next = TREE_CHAIN (decl);
      TREE_CHAIN (decl) = NULL_TREE;

      pushdecl (decl);
      decl = next;
    }
}
Ejemplo n.º 6
0
tree
poplevel (int keep, int functionbody)
{
  /* Points to a BLOCK tree node. This is the BLOCK node constructed for the
     binding level that we are about to exit and which is returned by this
     routine.  */
  tree block_node = NULL_TREE;
  tree decl_chain = getdecls ();
  tree subblock_chain = current_binding_level->blocks;
  tree subblock_node;

  /* If there were any declarations in the current binding level, or if this
     binding level is a function body, or if there are any nested blocks then
     create a BLOCK node to record them for the life of this function.  */
  if (keep || functionbody)
    block_node = build_block (keep ? decl_chain : 0, subblock_chain, 0, 0);

  /* Record the BLOCK node just built as the subblock its enclosing scope.  */
  for (subblock_node = subblock_chain; subblock_node;
       subblock_node = BLOCK_CHAIN (subblock_node))
    BLOCK_SUPERCONTEXT (subblock_node) = block_node;

  /* Clear out the meanings of the local variables of this level.  */

  for (subblock_node = decl_chain; subblock_node;
       subblock_node = DECL_CHAIN (subblock_node))
    if (DECL_NAME (subblock_node) != 0)
      /* If the identifier was used or addressed via a local extern decl,
         don't forget that fact.  */
      if (DECL_EXTERNAL (subblock_node))
	{
	  if (TREE_USED (subblock_node))
	    TREE_USED (DECL_NAME (subblock_node)) = 1;
	  if (TREE_ADDRESSABLE (subblock_node))
	    TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (subblock_node)) = 1;
	}

  /* Pop the current level.  */
  current_binding_level = current_binding_level->level_chain;

  if (functionbody)
    /* This is the top level block of a function.  */
    DECL_INITIAL (current_function_decl) = block_node;
  else if (current_binding_level == global_binding_level)
    /* When using gfc_start_block/gfc_finish_block from middle-end hooks,
       don't add newly created BLOCKs as subblocks of global_binding_level.  */
    ;
  else if (block_node)
    {
      current_binding_level->blocks
	= block_chainon (current_binding_level->blocks, block_node);
    }

  /* If we did not make a block for the level just exited, any blocks made for
     inner levels (since they cannot be recorded as subblocks in that level)
     must be carried forward so they will later become subblocks of something
     else.  */
  else if (subblock_chain)
    current_binding_level->blocks
      = block_chainon (current_binding_level->blocks, subblock_chain);
  if (block_node)
    TREE_USED (block_node) = 1;

  return block_node;
}
Ejemplo n.º 7
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.  */
}