Ejemplo n.º 1
0
/* Emit any file-wide instrumentation.  */
void
mudflap_finish_file (void)
{
  tree ctor_statements = NULL_TREE;

  /* No need to continue when there were errors.  */
  if (errorcount != 0 || sorrycount != 0)
    return;

  /* Insert a call to __mf_init.  */
  {
    tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
    append_to_statement_list (call2_stmt, &ctor_statements);
  }
  
  /* If appropriate, call __mf_set_options to pass along read-ignore mode.  */
  if (flag_mudflap_ignore_reads)
    {
      tree arg = tree_cons (NULL_TREE, 
                            mf_build_string ("-ignore-reads"), NULL_TREE);
      tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
      append_to_statement_list (call_stmt, &ctor_statements);
    }

  /* Process all enqueued object decls.  */
  if (deferred_static_decls)
    {
      size_t i;
      tree obj;
      for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
        {
          gcc_assert (DECL_P (obj));

          if (mf_marked_p (obj))
            continue;

          /* Omit registration for static unaddressed objects.  NB:
             Perform registration for non-static objects regardless of
             TREE_USED or TREE_ADDRESSABLE, because they may be used
             from other compilation units.  */
          if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
            continue;

          if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
            {
              warning (0, "mudflap cannot track unknown size extern %qs",
                       IDENTIFIER_POINTER (DECL_NAME (obj)));
              continue;
            }
          
          mudflap_register_call (obj, 
                                 size_in_bytes (TREE_TYPE (obj)),
                                 mf_varname_tree (obj));
        }

      VEC_truncate (tree, deferred_static_decls, 0);
    }

  /* Append all the enqueued registration calls.  */
  if (enqueued_call_stmt_chain)
    {
      append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
      enqueued_call_stmt_chain = NULL_TREE;
    }

  cgraph_build_static_cdtor ('I', ctor_statements, 
                             MAX_RESERVED_INIT_PRIORITY-1);
}
Ejemplo n.º 2
0
void
print_insn (pretty_printer *pp, const_rtx x, int verbose)
{
  if (verbose)
    {
      /* Blech, pretty-print can't print integers with a specified width.  */
      char uid_prefix[32];
      snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x));
      pp_string (pp, uid_prefix);
    }

  switch (GET_CODE (x))
    {
    case INSN:
      print_pattern (pp, PATTERN (x), verbose);
      break;

    case DEBUG_INSN:
      {
	const char *name = "?";

	if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
	  {
	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
	    char idbuf[32];
	    if (id)
	      name = IDENTIFIER_POINTER (id);
	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x))
		     == DEBUG_EXPR_DECL)
	      {
		sprintf (idbuf, "D#%i",
			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x)));
		name = idbuf;
	      }
	    else
	      {
		sprintf (idbuf, "D.%i",
			 DECL_UID (INSN_VAR_LOCATION_DECL (x)));
		name = idbuf;
	      }
	  }
	pp_printf (pp, "debug %s => ", name);
	if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x)))
	  pp_string (pp, "optimized away");
	else
	  print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose);
      }
      break;

    case JUMP_INSN:
      print_pattern (pp, PATTERN (x), verbose);
      break;
    case CALL_INSN:
      if (GET_CODE (PATTERN (x)) == PARALLEL)
        print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose);
      else
	print_pattern (pp, PATTERN (x), verbose);
      break;
    case CODE_LABEL:
      pp_printf (pp, "L%d:", INSN_UID (x));
      break;
    case JUMP_TABLE_DATA:
      pp_string (pp, "jump_table_data{\n");
      print_pattern (pp, PATTERN (x), verbose);
      pp_right_brace (pp);
      break;
    case BARRIER:
      pp_string (pp, "barrier");
      break;
    case NOTE:
      {
	pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x)));
	switch (NOTE_KIND (x))
	  {
	  case NOTE_INSN_EH_REGION_BEG:
	  case NOTE_INSN_EH_REGION_END:
	    pp_printf (pp, " %d", NOTE_EH_HANDLER (x));
	    break;

	  case NOTE_INSN_BLOCK_BEG:
	  case NOTE_INSN_BLOCK_END:
	    pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x)));
	    break;

	  case NOTE_INSN_BASIC_BLOCK:
	    pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index);
	    break;

	  case NOTE_INSN_DELETED_LABEL:
	  case NOTE_INSN_DELETED_DEBUG_LABEL:
	    {
	      const char *label = NOTE_DELETED_LABEL_NAME (x);
	      if (label == NULL)
		label = "";
	      pp_printf (pp, " (\"%s\")", label);
	    }
	    break;

	  case NOTE_INSN_VAR_LOCATION:
	  case NOTE_INSN_CALL_ARG_LOCATION:
	    pp_left_brace (pp);
	    print_pattern (pp, NOTE_VAR_LOCATION (x), verbose);
	    pp_right_brace (pp);
	    break;

	  default:
	    break;
	  }
	break;
      }
    default:
      gcc_unreachable ();
    }
}				/* print_insn */
Ejemplo n.º 3
0
static void
sdbout_parms (tree parms)
{
  for (; parms; parms = TREE_CHAIN (parms))
    if (DECL_NAME (parms))
      {
	int current_sym_value = 0;
	const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));

	if (name == 0 || *name == 0)
	  name = gen_fake_label ();

	/* Perform any necessary register eliminations on the parameter's rtl,
	   so that the debugging output will be accurate.  */
	DECL_INCOMING_RTL (parms)
	  = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
	SET_DECL_RTL (parms,
		      eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));

	if (PARM_PASSED_IN_MEMORY (parms))
	  {
	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
	    tree type;

	    /* ??? Here we assume that the parm address is indexed
	       off the frame pointer or arg pointer.
	       If that is not true, we produce meaningless results,
	       but do not crash.  */
	    if (GET_CODE (addr) == PLUS
		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
	      current_sym_value = INTVAL (XEXP (addr, 1));
	    else
	      current_sym_value = 0;

	    if (REG_P (DECL_RTL (parms))
		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
	      type = DECL_ARG_TYPE (parms);
	    else
	      {
		int original_sym_value = current_sym_value;

		/* This is the case where the parm is passed as an int or
		   double and it is converted to a char, short or float
		   and stored back in the parmlist.  In this case, describe
		   the parm with the variable's declared type, and adjust
		   the address if the least significant bytes (which we are
		   using) are not the first ones.  */
		if (BYTES_BIG_ENDIAN
		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
		  current_sym_value +=
		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));

		if (MEM_P (DECL_RTL (parms))
		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
		    && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1))
			== CONST_INT)
		    && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))
			== current_sym_value))
		  type = TREE_TYPE (parms);
		else
		  {
		    current_sym_value = original_sym_value;
		    type = DECL_ARG_TYPE (parms);
		  }
	      }

	    PUT_SDB_DEF (name);
	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
	    PUT_SDB_SCL (C_ARG);
	    PUT_SDB_TYPE (plain_type (type));
	    PUT_SDB_ENDEF;
	  }
	else if (REG_P (DECL_RTL (parms)))
	  {
	    rtx best_rtl;
	    /* Parm passed in registers and lives in registers or nowhere.  */

	    /* If parm lives in a register, use that register;
	       pretend the parm was passed there.  It would be more consistent
	       to describe the register where the parm was passed,
	       but in practice that register usually holds something else.  */
	    if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
	      best_rtl = DECL_RTL (parms);
	    /* If the parm lives nowhere,
	       use the register where it was passed.  */
	    else
	      best_rtl = DECL_INCOMING_RTL (parms);

	    PUT_SDB_DEF (name);
	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
	    PUT_SDB_SCL (C_REGPARM);
	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
	    PUT_SDB_ENDEF;
	  }
	else if (MEM_P (DECL_RTL (parms))
		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)
	  {
	    /* Parm was passed in registers but lives on the stack.  */

	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
	       in which case we want the value of that CONST_INT,
	       or (MEM (REG ...)) or (MEM (MEM ...)),
	       in which case we use a value of zero.  */
	    if (REG_P (XEXP (DECL_RTL (parms), 0))
		|| MEM_P (XEXP (DECL_RTL (parms), 0)))
	      current_sym_value = 0;
	    else
	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));

	    /* Again, this assumes the offset is based on the arg pointer.  */
	    PUT_SDB_DEF (name);
	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
						  XEXP (DECL_RTL (parms), 0)));
	    PUT_SDB_SCL (C_ARG);
	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
	    PUT_SDB_ENDEF;
	  }
      }
}
Ejemplo n.º 4
0
tree
ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
{
  /* See through any typedefs.  */
  type = TYPE_MAIN_VARIANT (type);

  tree decl = decl_for_type_lookup (type);
  /* It is possible that some of the earlier created DECLs were found
     unused, in that case they weren't emitted and varpool_get_node
     returns NULL node on them.  But now we really need them.  Thus,
     renew them here.  */
  if (decl != NULL_TREE && varpool_get_node (decl))
    return build_fold_addr_expr (decl);

  tree dtype = ubsan_type_descriptor_type ();
  tree type2 = type;
  const char *tname = NULL;
  char *pretty_name;
  unsigned char deref_depth = 0;
  unsigned short tkind, tinfo;

  /* Get the name of the type, or the name of the pointer type.  */
  if (pstyle == UBSAN_PRINT_POINTER)
    {
      gcc_assert (POINTER_TYPE_P (type));
      type2 = TREE_TYPE (type);

      /* Remove any '*' operators from TYPE.  */
      while (POINTER_TYPE_P (type2))
        deref_depth++, type2 = TREE_TYPE (type2);

      if (TREE_CODE (type2) == METHOD_TYPE)
        type2 = TYPE_METHOD_BASETYPE (type2);
    }

  /* If an array, get its type.  */
  type2 = strip_array_types (type2);

  if (pstyle == UBSAN_PRINT_ARRAY)
    {
      while (POINTER_TYPE_P (type2))
        deref_depth++, type2 = TREE_TYPE (type2);
    }

  if (TYPE_NAME (type2) != NULL)
    {
      if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
	tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
      else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
    }

  if (tname == NULL)
    /* We weren't able to determine the type name.  */
    tname = "<unknown>";

  /* Decorate the type name with '', '*', "struct", or "union".  */
  pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
  if (pstyle == UBSAN_PRINT_POINTER)
    {
      int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
			 TYPE_VOLATILE (type2) ? "volatile " : "",
			 TYPE_READONLY (type2) ? "const " : "",
			 TYPE_RESTRICT (type2) ? "restrict " : "",
			 TYPE_ATOMIC (type2) ? "_Atomic " : "",
			 TREE_CODE (type2) == RECORD_TYPE
			 ? "struct "
			 : TREE_CODE (type2) == UNION_TYPE
			   ? "union " : "", tname,
			 deref_depth == 0 ? "" : " ");
      while (deref_depth-- > 0)
        pretty_name[pos++] = '*';
      pretty_name[pos++] = '\'';
      pretty_name[pos] = '\0';
    }
  else if (pstyle == UBSAN_PRINT_ARRAY)
    {
      /* Pretty print the array dimensions.  */
      gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
      tree t = type;
      int pos = sprintf (pretty_name, "'%s ", tname);
      while (deref_depth-- > 0)
        pretty_name[pos++] = '*';
      while (TREE_CODE (t) == ARRAY_TYPE)
	{
	  pretty_name[pos++] = '[';
	  tree dom = TYPE_DOMAIN (t);
	  if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
	    pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
			    tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1);
	  else
	    /* ??? We can't determine the variable name; print VLA unspec.  */
	    pretty_name[pos++] = '*';
	  pretty_name[pos++] = ']';
	  t = TREE_TYPE (t);
	}
      pretty_name[pos++] = '\'';
      pretty_name[pos] = '\0';

     /* Save the tree with stripped types.  */
     type = t;
    }
  else
    sprintf (pretty_name, "'%s'", tname);

  switch (TREE_CODE (type))
    {
    case BOOLEAN_TYPE:
    case ENUMERAL_TYPE:
    case INTEGER_TYPE:
      tkind = 0x0000;
      break;
    case REAL_TYPE:
      /* FIXME: libubsan right now only supports float, double and
	 long double type formats.  */
      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
	  || TYPE_MODE (type) == TYPE_MODE (double_type_node)
	  || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
	tkind = 0x0001;
      else
	tkind = 0xffff;
      break;
    default:
      tkind = 0xffff;
      break;
    }
  tinfo = get_ubsan_type_info_for_type (type);

  /* Create a new VAR_DECL of type descriptor.  */
  char tmp_name[32];
  static unsigned int type_var_id_num;
  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
			  dtype);
  TREE_STATIC (decl) = 1;
  TREE_PUBLIC (decl) = 0;
  DECL_ARTIFICIAL (decl) = 1;
  DECL_IGNORED_P (decl) = 1;
  DECL_EXTERNAL (decl) = 0;

  size_t len = strlen (pretty_name);
  tree str = build_string (len + 1, pretty_name);
  TREE_TYPE (str) = build_array_type (char_type_node,
				      build_index_type (size_int (len)));
  TREE_READONLY (str) = 1;
  TREE_STATIC (str) = 1;
  tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tkind), NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tinfo), NULL_TREE, str);
  TREE_CONSTANT (ctor) = 1;
  TREE_STATIC (ctor) = 1;
  DECL_INITIAL (decl) = ctor;
  varpool_finalize_decl (decl);

  /* Save the VAR_DECL into the hash table.  */
  decl_for_type_insert (type, decl);

  return build_fold_addr_expr (decl);
}
Ejemplo n.º 5
0
vfy_string
vfy_get_class_name (vfy_jclass klass)
{
  return DECL_NAME (TYPE_NAME (klass));
}
Ejemplo n.º 6
0
tree
build_java_signature (tree type)
{
  tree sig, t;
  while (TREE_CODE (type) == POINTER_TYPE)
    type = TREE_TYPE (type);
  MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
  sig = TYPE_SIGNATURE (type);
  if (sig == NULL_TREE)
    {
      char sg[2];
      switch (TREE_CODE (type))
	{
	case BOOLEAN_TYPE: sg[0] = 'Z';  goto native;
	case VOID_TYPE:    sg[0] = 'V';  goto native;
	case INTEGER_TYPE:
          if (type == char_type_node || type == promoted_char_type_node)
	    {
	      sg[0] = 'C';
	      goto native;
	    }
	  switch (TYPE_PRECISION (type))
	    {
	    case  8:       sg[0] = 'B';  goto native;
	    case 16:       sg[0] = 'S';  goto native;
	    case 32:       sg[0] = 'I';  goto native;
	    case 64:       sg[0] = 'J';  goto native;
	    default:  goto bad_type;
	    }
	case REAL_TYPE:
	  switch (TYPE_PRECISION (type))
	    {
	    case 32:       sg[0] = 'F';  goto native;
	    case 64:       sg[0] = 'D';  goto native;
	    default:  goto bad_type;
	    }
	native:
	  sg[1] = 0;
	  sig = get_identifier (sg);
	  break;
	case RECORD_TYPE:
	  if (TYPE_ARRAY_P (type))
	    {
	      t = build_java_signature (TYPE_ARRAY_ELEMENT (type));
	      sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
				 "[", 0, 0, "");
	    }
	  else
	    {
	      t = DECL_NAME (TYPE_NAME (type));
	      sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
				 "L", '.', '/', ";");
	    }
	  break;
	case METHOD_TYPE:
	case FUNCTION_TYPE:
	  {
	    extern struct obstack temporary_obstack;
	    sig = build_java_argument_signature (type);
	    obstack_1grow (&temporary_obstack, '(');
	    obstack_grow (&temporary_obstack,
			  IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig));
	    obstack_1grow (&temporary_obstack, ')');

	    t = build_java_signature (TREE_TYPE (type));
	    obstack_grow0 (&temporary_obstack,
			   IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));

	    sig = get_identifier (obstack_base (&temporary_obstack));
	    obstack_free (&temporary_obstack,
			  obstack_base (&temporary_obstack));
	  }
	  break;
	bad_type:
	default:
	  gcc_unreachable ();
	}
      TYPE_SIGNATURE (type) = sig;
    }
  return sig;
}
Ejemplo n.º 7
0
static symtab_node *
lto_symtab_resolve_symbols (symtab_node *first)
{
  symtab_node *e;
  symtab_node *prevailing = NULL;

  /* Always set e->node so that edges are updated to reflect decl merging. */
  for (e = first; e; e = e->next_sharing_asm_name)
    if (lto_symtab_symbol_p (e)
	&& (e->resolution == LDPR_PREVAILING_DEF_IRONLY
	    || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
	    || e->resolution == LDPR_PREVAILING_DEF))
      {
	prevailing = e;
	break;
      }

  /* If the chain is already resolved there is nothing else to do.  */
  if (prevailing)
    {
      /* Assert it's the only one.  */
      for (e = prevailing->next_sharing_asm_name; e; e = e->next_sharing_asm_name)
	if (lto_symtab_symbol_p (e)
	    && (e->resolution == LDPR_PREVAILING_DEF_IRONLY
		|| e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
		|| e->resolution == LDPR_PREVAILING_DEF))
	  fatal_error (input_location, "multiple prevailing defs for %qE",
		       DECL_NAME (prevailing->decl));
      return prevailing;
    }

  /* Find the single non-replaceable prevailing symbol and
     diagnose ODR violations.  */
  for (e = first; e; e = e->next_sharing_asm_name)
    {
      if (!lto_symtab_resolve_can_prevail_p (e))
	continue;

      /* If we have a non-replaceable definition it prevails.  */
      if (!lto_symtab_resolve_replaceable_p (e))
	{
	  if (prevailing)
	    {
	      error_at (DECL_SOURCE_LOCATION (e->decl),
			"%qD has already been defined", e->decl);
	      inform (DECL_SOURCE_LOCATION (prevailing->decl),
		      "previously defined here");
	    }
	  prevailing = e;
	}
    }
  if (prevailing)
    return prevailing;

  /* Do a second round choosing one from the replaceable prevailing decls.  */
  for (e = first; e; e = e->next_sharing_asm_name)
    {
      if (!lto_symtab_resolve_can_prevail_p (e))
	continue;

      /* Choose the first function that can prevail as prevailing.  */
      if (TREE_CODE (e->decl) == FUNCTION_DECL)
	{
	  prevailing = e;
	  break;
	}

      /* From variables that can prevail choose the largest one.  */
      if (!prevailing
	  || tree_int_cst_lt (DECL_SIZE (prevailing->decl),
			      DECL_SIZE (e->decl))
	  /* When variables are equivalent try to chose one that has useful
	     DECL_INITIAL.  This makes sense for keyed vtables that are
	     DECL_EXTERNAL but initialized.  In units that do not need them
	     we replace the initializer by error_mark_node to conserve
	     memory.

	     We know that the vtable is keyed outside the LTO unit - otherwise
	     the keyed instance would prevail.  We still can preserve useful
	     info in the initializer.  */
	  || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
	      && (DECL_INITIAL (e->decl)
		  && DECL_INITIAL (e->decl) != error_mark_node)
	      && (!DECL_INITIAL (prevailing->decl)
		  || DECL_INITIAL (prevailing->decl) == error_mark_node)))
	prevailing = e;
    }

  return prevailing;
}
Ejemplo n.º 8
0
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
   _DECLs if appropriate.  Arrange to call the __mf_register function
   now, and the __mf_unregister function later for each.  Return the
   gimple sequence after synthesis.  */
gimple_seq
mx_register_decls (tree decl, gimple_seq seq, gimple stmt, location_t location, bool func_args)
{
    gimple_seq finally_stmts = NULL;
    gimple_stmt_iterator initially_stmts = gsi_start (seq);
    bool sframe_inserted = false;
    size_t front_rz_size, rear_rz_size;
    tree fsize, rsize, size;
    gimple uninit_fncall_front, uninit_fncall_rear, init_fncall_front, \
        init_fncall_rear, init_assign_stmt;
    tree fncall_param_front, fncall_param_rear;
    int map_ret;

    while (decl != NULL_TREE)
    {
        if ((mf_decl_eligible_p (decl) || TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE)
                /* Not already processed.  */
                && ! mf_marked_p (decl)
                /* Automatic variable.  */
                && ! DECL_EXTERNAL (decl)
                && ! TREE_STATIC (decl)
                && get_name(decl))
        {
            DEBUGLOG("DEBUG Instrumenting %s is_complete_type %d\n", IDENTIFIER_POINTER(DECL_NAME(decl)), COMPLETE_TYPE_P(decl));

            /* construct a tree corresponding to the type struct{
               unsigned int rz_front[6U];
               original variable
               unsigned int rz_rear[6U];
               };
             */

            if (!sframe_inserted){
                gimple ensure_fn_call = gimple_build_call (lbc_ensure_sframe_bitmap_fndecl, 0);
                gimple_set_location (ensure_fn_call, location);
                gsi_insert_before (&initially_stmts, ensure_fn_call, GSI_SAME_STMT);

                sframe_inserted = true;
            }

            // Calculate the zone sizes
            size_t element_size = 0, request_size = 0;
            if (COMPLETE_TYPE_P(decl)){
                request_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(decl)));
                if (TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE)
                    element_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(TREE_TYPE(decl))));
                else
                    element_size = request_size;
            }
            calculate_zone_sizes(element_size, request_size, /*global*/ false, COMPLETE_TYPE_P(decl), &front_rz_size, &rear_rz_size);
            DEBUGLOG("DEBUG *SIZES* req_size %u, ele_size %u, fsize %u, rsize %u\n", request_size, element_size, front_rz_size, rear_rz_size);
			
            tree struct_type = create_struct_type(decl, front_rz_size, rear_rz_size);
            tree struct_var = create_struct_var(struct_type, decl, location);
            declare_vars(struct_var, stmt, 0);

			/* Inserting into hashtable */
            PWord_t PV;
            JSLI(PV, decl_map, mf_varname_tree(decl));
            gcc_assert(PV);
            *PV = (PWord_t) struct_var;

            fsize = convert (unsigned_type_node, size_int(front_rz_size));
            gcc_assert (is_gimple_val (fsize));

            tree rz_front = TYPE_FIELDS(struct_type);
            fncall_param_front = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_front),
                                                      struct_var, rz_front, NULL_TREE)));
            uninit_fncall_front = gimple_build_call (lbc_uninit_front_rz_fndecl, 2, fncall_param_front, fsize);
            init_fncall_front = gimple_build_call (lbc_init_front_rz_fndecl, 2, fncall_param_front, fsize);
            gimple_set_location (init_fncall_front, location);
            gimple_set_location (uninit_fncall_front, location);

            // In complete types have only a front red zone
            if (COMPLETE_TYPE_P(decl)){
                rsize = convert (unsigned_type_node, size_int(rear_rz_size));
                gcc_assert (is_gimple_val (rsize));

                tree rz_rear = DECL_CHAIN(DECL_CHAIN(TYPE_FIELDS (struct_type)));
                fncall_param_rear = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_rear),
                                struct_var, rz_rear, NULL_TREE)));
                init_fncall_rear = gimple_build_call (lbc_init_rear_rz_fndecl, 2, fncall_param_rear, rsize);
                uninit_fncall_rear = gimple_build_call (lbc_uninit_rear_rz_fndecl, 2, fncall_param_rear, rsize);
                gimple_set_location (init_fncall_rear, location);
                gimple_set_location (uninit_fncall_rear, location);
            }

            // TODO Do I need this?
#if 0
            if (DECL_INITIAL(decl) != NULL_TREE){
                // This code never seems to be getting executed for somehting like int i = 10;
                // I have no idea why? But looking at the tree dump, seems like its because
                // by the time it gets here, these kind of statements are split into two statements
                // as int i; and i = 10; respectively. I am leaving it in just in case.
                tree orig_var_type = DECL_CHAIN(TYPE_FIELDS (struct_type));
                tree orig_var_lval = mf_mark (build3 (COMPONENT_REF, TREE_TYPE(orig_var_type),
                                        struct_var, orig_var_type, NULL_TREE));
                init_assign_stmt = gimple_build_assign(orig_var_lval, DECL_INITIAL(decl));
                gimple_set_location (init_assign_stmt, location);
            }
#endif

            if (gsi_end_p (initially_stmts))
            {
                // TODO handle this
                if (!DECL_ARTIFICIAL (decl))
                    warning (OPT_Wmudflap,
                            "mudflap cannot track %qE in stub function",
                            DECL_NAME (decl));
            }
            else
            {
#if 0
                // Insert the declaration initializer
                if (DECL_INITIAL(decl) != NULL_TREE)
                    gsi_insert_before (&initially_stmts, init_assign_stmt, GSI_SAME_STMT);
#endif

                //gsi_insert_before (&initially_stmts, register_fncall, GSI_SAME_STMT);
                gsi_insert_before (&initially_stmts, init_fncall_front, GSI_SAME_STMT);
                if (COMPLETE_TYPE_P(decl))
                    gsi_insert_before (&initially_stmts, init_fncall_rear, GSI_SAME_STMT);

                /* Accumulate the FINALLY piece.  */
                //gimple_seq_add_stmt (&finally_stmts, unregister_fncall);
                gimple_seq_add_stmt (&finally_stmts, uninit_fncall_front);
                if (COMPLETE_TYPE_P(decl))
                    gimple_seq_add_stmt (&finally_stmts, uninit_fncall_rear);

            }
            mf_mark (decl);
        }

        decl = DECL_CHAIN (decl);
    }

    /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
    if (finally_stmts != NULL)
    {
        gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY);
        gimple_seq new_seq = gimple_seq_alloc ();

        gimple_seq_add_stmt (&new_seq, stmt);
        return new_seq;
    }
    else
        return seq;
}
Ejemplo n.º 9
0
static const char * 
mf_varname_tree (tree decl)
{
	static pretty_printer buf_rec;
	static int initialized = 0;
	pretty_printer *buf = & buf_rec;
	const char *buf_contents;
	tree result;

	gcc_assert (decl);

	if (!initialized)
	{
		pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
		initialized = 1;
	}
	pp_clear_output_area (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_string (buf, ":");
			pp_decimal_int (buf, sourceline);

			if (sourcecolumn != 0)
			{
				pp_string (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_string (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 = pp_base_formatted_text (buf);
	//DEBUGLOG("buf_contents : %s\n", buf_contents);
	result = mf_build_string (buf_contents);
	pp_clear_output_area (buf);

	//  return result;
	return buf_contents;
}
Ejemplo n.º 10
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 = current_binding_level->names;
  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.º 11
0
static unsigned int
tree_nrv (void)
{
  tree result = DECL_RESULT (current_function_decl);
  tree result_type = TREE_TYPE (result);
  tree found = NULL;
  basic_block bb;
  gimple_stmt_iterator gsi;
  struct nrv_data data;

  /* If this function does not return an aggregate type in memory, then
     there is nothing to do.  */
  if (!aggregate_value_p (result, current_function_decl))
    return 0;

  /* If a GIMPLE type is returned in memory, finalize_nrv_r might create
     non-GIMPLE.  */
  if (is_gimple_reg_type (result_type))
    return 0;

  /* Look through each block for assignments to the RESULT_DECL.  */
  FOR_EACH_BB (bb)
    {
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
	{
	  gimple stmt = gsi_stmt (gsi);
	  tree ret_val;

	  if (gimple_code (stmt) == GIMPLE_RETURN)
	    {
	      /* In a function with an aggregate return value, the
		 gimplifier has changed all non-empty RETURN_EXPRs to
		 return the RESULT_DECL.  */
	      ret_val = gimple_return_retval (stmt);
	      if (ret_val)
		gcc_assert (ret_val == result);
	    }
	  else if (is_gimple_assign (stmt)
		   && gimple_assign_lhs (stmt) == result)
	    {
              tree rhs;

	      if (!gimple_assign_copy_p (stmt))
		return 0;

	      rhs = gimple_assign_rhs1 (stmt);

	      /* Now verify that this return statement uses the same value
		 as any previously encountered return statement.  */
	      if (found != NULL)
		{
		  /* If we found a return statement using a different variable
		     than previous return statements, then we can not perform
		     NRV optimizations.  */
		  if (found != rhs)
		    return 0;
		}
	      else
		found = rhs;

	      /* The returned value must be a local automatic variable of the
		 same type and alignment as the function's result.  */
	      if (TREE_CODE (found) != VAR_DECL
		  || TREE_THIS_VOLATILE (found)
		  || DECL_CONTEXT (found) != current_function_decl
		  || TREE_STATIC (found)
		  || TREE_ADDRESSABLE (found)
		  || DECL_ALIGN (found) > DECL_ALIGN (result)
		  || !useless_type_conversion_p (result_type,
					        TREE_TYPE (found)))
		return 0;
	    }
	  else if (is_gimple_assign (stmt))
	    {
	      tree addr = get_base_address (gimple_assign_lhs (stmt));
	       /* If there's any MODIFY of component of RESULT, 
		  then bail out.  */
	      if (addr && addr == result)
		return 0;
	    }
	}
    }

  if (!found)
    return 0;

  /* If dumping details, then note once and only the NRV replacement.  */
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file, "NRV Replaced: ");
      print_generic_expr (dump_file, found, dump_flags);
      fprintf (dump_file, "  with: ");
      print_generic_expr (dump_file, result, dump_flags);
      fprintf (dump_file, "\n");
    }

  /* At this point we know that all the return statements return the
     same local which has suitable attributes for NRV.   Copy debugging
     information from FOUND to RESULT.  */
  DECL_NAME (result) = DECL_NAME (found);
  DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found);
  DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found);
  TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found);

  /* Now walk through the function changing all references to VAR to be
     RESULT.  */
  data.var = found;
  data.result = result;
  FOR_EACH_BB (bb)
    {
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
	{
	  gimple stmt = gsi_stmt (gsi);
	  /* If this is a copy from VAR to RESULT, remove it.  */
	  if (gimple_assign_copy_p (stmt)
	      && gimple_assign_lhs (stmt) == result
	      && gimple_assign_rhs1 (stmt) == found)
	    gsi_remove (&gsi, true);
	  else
	    {
	      struct walk_stmt_info wi;
	      memset (&wi, 0, sizeof (wi));
	      wi.info = &data;
	      walk_gimple_op (stmt, finalize_nrv_r, &wi);
	      gsi_next (&gsi);
	    }
	}
    }

  /* FOUND is no longer used.  Ensure it gets removed.  */
  var_ann (found)->used = 0;
  return 0;
}
Ejemplo n.º 12
0
void mchp_print_builtin_function (const_tree t)
{
  if (DECL_P(t))
    puts (IDENTIFIER_POINTER(DECL_NAME(t)));
}
Ejemplo n.º 13
0
tree
ubsan_type_descriptor (tree type)
{
  /* See through any typedefs.  */
  type = TYPE_MAIN_VARIANT (type);

  tree decl = decl_for_type_lookup (type);
  if (decl != NULL_TREE)
    return decl;

  tree dtype = ubsan_type_descriptor_type ();
  const char *tname;
  unsigned short tkind, tinfo;

  /* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work.
     ??? For e.g. type_unsigned_for (type), the TYPE_NAME would be NULL.  */
  if (TYPE_NAME (type) != NULL)
    tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
  else
    tname = "<unknown>";
  if (TREE_CODE (type) == INTEGER_TYPE)
    {
      /* For INTEGER_TYPE, this is 0x0000.  */
      tkind = 0x000;
      tinfo = get_ubsan_type_info_for_type (type);
    }
  else if (TREE_CODE (type) == REAL_TYPE)
    /* We don't have float support yet.  */
    gcc_unreachable ();
  else
    gcc_unreachable ();

  /* Create a new VAR_DECL of type descriptor.  */
  char tmp_name[32];
  static unsigned int type_var_id_num;
  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
			  dtype);
  TREE_STATIC (decl) = 1;
  TREE_PUBLIC (decl) = 0;
  DECL_ARTIFICIAL (decl) = 1;
  DECL_IGNORED_P (decl) = 1;
  DECL_EXTERNAL (decl) = 0;

  size_t len = strlen (tname);
  tree str = build_string (len + 1, tname);
  TREE_TYPE (str) = build_array_type (char_type_node,
				      build_index_type (size_int (len)));
  TREE_READONLY (str) = 1;
  TREE_STATIC (str) = 1;
  tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tkind), NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tinfo), NULL_TREE, str);
  TREE_CONSTANT (ctor) = 1;
  TREE_STATIC (ctor) = 1;
  DECL_INITIAL (decl) = ctor;
  rest_of_decl_compilation (decl, 1, 0);

  /* Save the address of the VAR_DECL into the pointer map.  */
  decl = build_fold_addr_expr (decl);
  decl_for_type_insert (type, decl);

  return decl;
}
Ejemplo n.º 14
0
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
   _DECLs if appropriate.  Arrange to call the __mf_register function
   now, and the __mf_unregister function later for each.  */
static void
mx_register_decls (tree decl, tree *stmt_list)
{
  tree finally_stmts = NULL_TREE;
  tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);

  while (decl != NULL_TREE)
    {
      if (mf_decl_eligible_p (decl) 
          /* Not already processed.  */
          && ! mf_marked_p (decl)
          /* Automatic variable.  */
          && ! DECL_EXTERNAL (decl)
          && ! TREE_STATIC (decl))
        {
          tree size = NULL_TREE, variable_name;
          tree unregister_fncall, unregister_fncall_params;
          tree register_fncall, register_fncall_params;

	  size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
          unregister_fncall_params =
            tree_cons (NULL_TREE,
                       convert (ptr_type_node,
                                mf_mark (build1 (ADDR_EXPR,
                                                 build_pointer_type (TREE_TYPE (decl)),
                                                 decl))),
                       tree_cons (NULL_TREE, 
                                  size,
                                  tree_cons (NULL_TREE,
					     /* __MF_TYPE_STACK */
                                             build_int_cst (NULL_TREE, 3),
                                             NULL_TREE)));
          /* __mf_unregister (...) */
          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
                                                        unregister_fncall_params);

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
          variable_name = mf_varname_tree (decl);
          register_fncall_params =
            tree_cons (NULL_TREE,
                   convert (ptr_type_node,
                            mf_mark (build1 (ADDR_EXPR,
                                             build_pointer_type (TREE_TYPE (decl)),
                                             decl))),
                       tree_cons (NULL_TREE,
                                  size,
                                  tree_cons (NULL_TREE,
					     /* __MF_TYPE_STACK */
                                             build_int_cst (NULL_TREE, 3),
                                             tree_cons (NULL_TREE,
                                                        variable_name,
                                                        NULL_TREE))));

          /* __mf_register (...) */
          register_fncall = build_function_call_expr (mf_register_fndecl,
                                                      register_fncall_params);

          /* Accumulate the two calls.  */
          /* ??? Set EXPR_LOCATION.  */
          gimplify_stmt (&register_fncall);
          gimplify_stmt (&unregister_fncall);

          /* Add the __mf_register call at the current appending point.  */
          if (tsi_end_p (initially_stmts))
	    warning (0, "mudflap cannot track %qs in stub function",
		     IDENTIFIER_POINTER (DECL_NAME (decl)));
	  else
	    {
	      tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);

	      /* Accumulate the FINALLY piece.  */
	      append_to_statement_list (unregister_fncall, &finally_stmts);
	    }
          mf_mark (decl);
        }

      decl = TREE_CHAIN (decl);
    }

  /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
  if (finally_stmts != NULL_TREE)
    {
      tree t = build2 (TRY_FINALLY_EXPR, void_type_node,
                       *stmt_list, finally_stmts);
      *stmt_list = NULL;
      append_to_statement_list (t, stmt_list);
    }
}
Ejemplo n.º 15
0
void
print_insn (char *buf, const_rtx x, int verbose)
{
  char t[BUF_LEN];
  const_rtx insn = x;

  switch (GET_CODE (x))
    {
    case INSN:
      print_pattern (t, PATTERN (x), verbose);
#ifdef INSN_SCHEDULING
      if (verbose && current_sched_info)
	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
		 t);
      else
#endif
	sprintf (buf, " %4d %s", INSN_UID (x), t);
      break;

    case DEBUG_INSN:
      {
	const char *name = "?";

	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
	  {
	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
	    char idbuf[32];
	    if (id)
	      name = IDENTIFIER_POINTER (id);
	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
		     == DEBUG_EXPR_DECL)
	      {
		sprintf (idbuf, "D#%i",
			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
		name = idbuf;
	      }
	    else
	      {
		sprintf (idbuf, "D.%i",
			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
		name = idbuf;
	      }
	  }
	if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)))
	  sprintf (buf, " %4d: debug %s optimized away", INSN_UID (insn), name);
	else
	  {
	    print_pattern (t, INSN_VAR_LOCATION_LOC (insn), verbose);
	    sprintf (buf, " %4d: debug %s => %s", INSN_UID (insn), name, t);
	  }
      }
      break;

    case JUMP_INSN:
      print_pattern (t, PATTERN (x), verbose);
#ifdef INSN_SCHEDULING
      if (verbose && current_sched_info)
	sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
		 t);
      else
#endif
	sprintf (buf, " %4d %s", INSN_UID (x), t);
      break;
    case CALL_INSN:
      x = PATTERN (insn);
      if (GET_CODE (x) == PARALLEL)
	{
	  x = XVECEXP (x, 0, 0);
	  print_pattern (t, x, verbose);
	}
      else
	strcpy (t, "call <...>");
#ifdef INSN_SCHEDULING
      if (verbose && current_sched_info)
	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (insn, 1), t);
      else
#endif
	sprintf (buf, " %4d %s", INSN_UID (insn), t);
      break;
    case CODE_LABEL:
      sprintf (buf, "L%d:", INSN_UID (x));
      break;
    case BARRIER:
      sprintf (buf, "i%4d: barrier", INSN_UID (x));
      break;
    case NOTE:
      sprintf (buf, " %4d %s", INSN_UID (x),
	       GET_NOTE_INSN_NAME (NOTE_KIND (x)));
      break;
    default:
      sprintf (buf, "i%4d  <What %s?>", INSN_UID (x),
	       GET_RTX_NAME (GET_CODE (x)));
    }
}				/* print_insn */
Ejemplo n.º 16
0
tree find_instr_node(tree temp)
{
	int ret = 0;
    tree decl_node;
    PWord_t PV;
    JSLG(PV, decl_map, mf_varname_tree(temp));
    if(PV){
        decl_node = ((tree) *PV);
        gcc_assert(decl_node != NULL_TREE);
        DEBUGLOG("[find_instr] Match found for %s --> %s\n",mf_varname_tree(temp), IDENTIFIER_POINTER(DECL_NAME(decl_node)));
        return decl_node;
    }else
        DEBUGLOG("[find_instr] Match not found for %s\n",mf_varname_tree(temp));
    return NULL_TREE;
}
Ejemplo n.º 17
0
tree
build_java_array_type (tree element_type, HOST_WIDE_INT length)
{
  tree sig, t, fld, atype, arfld;
  char buf[23]; /* 20 for the digits of a 64 bit number + "[]" + \0 */
  tree elsig = build_java_signature (element_type);
  tree el_name = element_type;
  buf[0] = '[';
  if (length >= 0)
    sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length);
  else
    buf[1] = '\0';
  sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig),
		     buf, 0, 0, "");
  t = IDENTIFIER_SIGNATURE_TYPE (sig);
  if (t != NULL_TREE)
    return TREE_TYPE (t);
  t = make_class ();
  IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t);
  TYPE_ARRAY_P (t) = 1;

  if (TREE_CODE (el_name) == POINTER_TYPE)
    el_name = TREE_TYPE (el_name);
  el_name = TYPE_NAME (el_name);
  if (TREE_CODE (el_name) == TYPE_DECL)
    el_name = DECL_NAME (el_name);
  {
    char suffix[23];
    if (length >= 0)
      sprintf (suffix, "[%d]", (int)length); 
    else
      strcpy (suffix, "[]");
    TYPE_NAME (t) 
      = TYPE_STUB_DECL (t)
      = build_decl (TYPE_DECL,
		    identifier_subst (el_name, "", '.', '.', suffix),
                             t);
    TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (t)) = true;
  }

  set_java_signature (t, sig);
  set_super_info (0, t, object_type_node, 0);
  if (TREE_CODE (element_type) == RECORD_TYPE)
    element_type = promote_type (element_type);
  TYPE_ARRAY_ELEMENT (t) = element_type;

  /* Add length pseudo-field. */
  fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node);
  TYPE_FIELDS (t) = fld;
  DECL_CONTEXT (fld) = t;
  FIELD_PUBLIC (fld) = 1;
  FIELD_FINAL (fld) = 1;
  TREE_READONLY (fld) = 1;

  atype = build_prim_array_type (element_type, length);
  arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype);
  DECL_CONTEXT (arfld) = t;
  TREE_CHAIN (fld) = arfld;
  DECL_ALIGN (arfld) = TYPE_ALIGN (element_type);

  /* We could layout_class, but that loads java.lang.Object prematurely.
   * This is called by the parser, and it is a bad idea to do load_class
   * in the middle of parsing, because of possible circularity problems. */
  push_super_field (t, object_type_node);
  layout_type (t);

  return t;
}
Ejemplo n.º 18
0
/* FN is a constructor or destructor, and there are FUNCTION_DECLs
   cloned from it nearby.  Instead of cloning this body, leave it
   alone and create tiny one-call bodies for the cloned
   FUNCTION_DECLs.  These clones are sibcall candidates, and their
   resulting code will be very thunk-esque.  */
static void
thunk_body (tree clone, tree fn, tree clone_to_call)
{
  tree bind, block, call, fn_parm, fn_parm_typelist;
  int parmno, vtt_parmno;
  tree clone_parm, parmlist;

  for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
       fn_parm;
       ++parmno, fn_parm = TREE_CHAIN (fn_parm))
    {
      if (DECL_ARTIFICIAL (fn_parm) && DECL_NAME (fn_parm) == vtt_parm_identifier)
	{
	  vtt_parmno = parmno;	/* Compensate for removed in_charge parameter.  */
	  break;
	}
    }
  /* Currently, we are not supposed to have a vtt argument. */
  gcc_assert(vtt_parmno == -1);

  /* Walk parameter lists together, creating parameter list for call to original function.  */
  for (parmno = 0,
	 parmlist = NULL,
	 fn_parm = DECL_ARGUMENTS (fn),
	 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
	 clone_parm = DECL_ARGUMENTS (clone);
       fn_parm;
       ++parmno,
	 fn_parm = TREE_CHAIN (fn_parm))
    {
      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
	{
	  tree typed_null_pointer_node = copy_node (null_pointer_node);
	  gcc_assert (fn_parm_typelist);
	  /* Clobber actual parameter with formal parameter type.  */
	  TREE_TYPE (typed_null_pointer_node) = TREE_VALUE (fn_parm_typelist);
	  parmlist = tree_cons (NULL, typed_null_pointer_node, parmlist);
	}
      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
	{
	  /* Just skip it. */
	}
      /* Map other parameters to their equivalents in the cloned
	 function.  */
      else
	{
	  gcc_assert (clone_parm);
	  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
	  parmlist = tree_cons (NULL, clone_parm, parmlist);
	  clone_parm = TREE_CHAIN (clone_parm);
	}
      if (fn_parm_typelist)
	fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
    }

    /* We built this list backwards; fix now.  */
    parmlist = nreverse (parmlist);

    TREE_USED (clone_to_call) = 1;
    call = build_cxx_call (clone_to_call, parmlist);

    for (parmlist = TREE_OPERAND (call, 1); parmlist; parmlist = TREE_CHAIN (parmlist))
      {
	fn_parm = TREE_VALUE (parmlist);
	/* Remove the EMPTY_CLASS_EXPR because it upsets estimate_num_insns().  */
	if (TREE_CODE (fn_parm) == COMPOUND_EXPR)
	  {
	    gcc_assert (TREE_CODE (TREE_OPERAND (fn_parm, 1)) == EMPTY_CLASS_EXPR);
	    TREE_VALUE (parmlist) = TREE_OPERAND (fn_parm, 0);
	  }
      }
    block = make_node (BLOCK);
    if (targetm.cxx.cdtor_returns_this ())
      {
	tree clone_result = DECL_RESULT (clone);
	tree modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result), clone_result, call);
	add_stmt (modify);
	BLOCK_VARS (block) = clone_result;
      }
    else
      {
	add_stmt (call);
      }
    bind = c_build_bind_expr (block, cur_stmt_list);
    DECL_SAVED_TREE (clone) = push_stmt_list ();
    add_stmt (bind);
}
Ejemplo n.º 19
0
const char *
lhd_decl_printable_name (tree decl, int ARG_UNUSED (verbosity))
{
  gcc_assert (decl && DECL_NAME (decl));
  return IDENTIFIER_POINTER (DECL_NAME (decl));
}
Ejemplo n.º 20
0
bool
maybe_clone_body (tree fn)
{
  tree clone;
  bool first = true;
/* APPLE LOCAL begin ARM structor thunks */
  tree clone_to_call;
  struct clone_info info;
/* APPLE LOCAL end ARM structor thunks */

  /* We only clone constructors and destructors.  */
  if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
      && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
    return 0;

  /* Emit the DWARF1 abstract instance.  */
  (*debug_hooks->deferred_inline_function) (fn);

/* APPLE LOCAL begin ARM structor thunks */
  /* Figure out whether we can use the 'thunk' implementation,
     and if so on which clones. */
  info.next_clone = 0;
  info.which_thunks_ok = compute_use_thunks (fn);
/* APPLE LOCAL end ARM structor thunks */

  /* We know that any clones immediately follow FN in the TYPE_METHODS
     list.  */
  push_to_top_level ();
  FOR_EACH_CLONE (clone, fn)
    {
      tree parm;
      tree clone_parm;
      int parmno;
      splay_tree decl_map;

      /* Update CLONE's source position information to match FN's.  */
      DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
      DECL_INLINE (clone) = DECL_INLINE (fn);
      DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
      /* LLVM LOCAL begin inlinehint attribute */
      DECL_EXPLICIT_INLINE_P (clone) = DECL_EXPLICIT_INLINE_P (fn);
      /* LLVM LOCAL end inlinehint attribute */
      DECL_COMDAT (clone) = DECL_COMDAT (fn);
      DECL_WEAK (clone) = DECL_WEAK (fn);
      DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn);
      DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
      DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
      DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
      DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
      DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
      TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
      DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
      DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);

      /* Adjust the parameter names and locations.  */
      parm = DECL_ARGUMENTS (fn);
      clone_parm = DECL_ARGUMENTS (clone);
      /* Update the `this' parameter, which is always first.  */
      update_cloned_parm (parm, clone_parm, first);
      parm = TREE_CHAIN (parm);
      clone_parm = TREE_CHAIN (clone_parm);
      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
	parm = TREE_CHAIN (parm);
      if (DECL_HAS_VTT_PARM_P (fn))
	parm = TREE_CHAIN (parm);
      if (DECL_HAS_VTT_PARM_P (clone))
	clone_parm = TREE_CHAIN (clone_parm);
      for (; parm;
	   parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
	/* Update this parameter.  */
	update_cloned_parm (parm, clone_parm, first);

      /* Start processing the function.  */
      start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);

      /* Remap the parameters.  */
      decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
      for (parmno = 0,
	     parm = DECL_ARGUMENTS (fn),
	     clone_parm = DECL_ARGUMENTS (clone);
	   parm;
	   ++parmno,
	     parm = TREE_CHAIN (parm))
	{
	  /* Map the in-charge parameter to an appropriate constant.  */
	  if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
	    {
	      tree in_charge;
	      in_charge = in_charge_arg_for_name (DECL_NAME (clone));
	      splay_tree_insert (decl_map,
				 (splay_tree_key) parm,
				 (splay_tree_value) in_charge);
	      /* APPLE LOCAL ARM structor thunks */
	      info.in_charge_value [info.next_clone] = in_charge;
	    }
	  else if (DECL_ARTIFICIAL (parm)
		   && DECL_NAME (parm) == vtt_parm_identifier)
	    {
	      /* For a subobject constructor or destructor, the next
		 argument is the VTT parameter.  Remap the VTT_PARM
		 from the CLONE to this parameter.  */
	      if (DECL_HAS_VTT_PARM_P (clone))
		{
		  DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
		  splay_tree_insert (decl_map,
				     (splay_tree_key) parm,
				     (splay_tree_value) clone_parm);
		  clone_parm = TREE_CHAIN (clone_parm);
		}
	      /* Otherwise, map the VTT parameter to `NULL'.  */
	      else
		{
		  splay_tree_insert (decl_map,
				     (splay_tree_key) parm,
				     (splay_tree_value) null_pointer_node);
		}
	    }
	  /* Map other parameters to their equivalents in the cloned
	     function.  */
	  else
	    {
	      splay_tree_insert (decl_map,
				 (splay_tree_key) parm,
				 (splay_tree_value) clone_parm);
	      clone_parm = TREE_CHAIN (clone_parm);
	    }
	}

      if (targetm.cxx.cdtor_returns_this ())
	{
	  parm = DECL_RESULT (fn);
	  clone_parm = DECL_RESULT (clone);
	  splay_tree_insert (decl_map, (splay_tree_key) parm,
			     (splay_tree_value) clone_parm);
	}
      /* APPLE LOCAL begin ARM structor thunks */
      clone_to_call = find_earlier_clone (&info);
      if (clone_to_call)
	/* Bodies are identical; replace later one with call to an
	   earlier one. */
	thunk_body (clone, fn, clone_to_call);
      else
	/* Clone the body.  */
	clone_body (clone, fn, decl_map);
      /* APPLE LOCAL end ARM structor thunks */

      /* The clone can throw iff the original function can throw.  */
      cp_function_chain->can_throw = !TREE_NOTHROW (fn);

      /* Now, expand this function into RTL, if appropriate.  */
      finish_function (0);
      BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
      expand_or_defer_fn (clone);
      first = false;
      /* APPLE LOCAL begin ARM structor thunks */
      info.clones [info.next_clone] = clone;
      info.next_clone++;
      /* APPLE LOCAL end ARM structor thunks */
    }
Ejemplo n.º 21
0
static void
dequeue_and_dump (dump_info_p di)
{
  dump_queue_p dq;
  splay_tree_node stn;
  dump_node_info_p dni;
  tree t;
  unsigned int index;
  enum tree_code code;
  enum tree_code_class code_class;
  const char* code_name;

  /* Get the next node from the queue.  */
  dq = di->queue;
  stn = dq->node;
  t = (tree) stn->key;
  dni = (dump_node_info_p) stn->value;
  index = dni->index;

  /* Remove the node from the queue, and put it on the free list.  */
  di->queue = dq->next;
  if (!di->queue)
    di->queue_end = 0;
  dq->next = di->free_list;
  di->free_list = dq;

  /* Print the node index.  */
  dump_index (di, index);
  /* And the type of node this is.  */
  if (dni->binfo_p)
    code_name = "binfo";
  else
    code_name = tree_code_name[(int) TREE_CODE (t)];
  fprintf (di->stream, "%-16s ", code_name);
  di->column = 25;

  /* Figure out what kind of node this is.  */
  code = TREE_CODE (t);
  code_class = TREE_CODE_CLASS (code);

  /* Although BINFOs are TREE_VECs, we dump them specially so as to be
     more informative.  */
  if (dni->binfo_p)
    {
      unsigned ix;
      tree base;
      vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (t);

      dump_child ("type", BINFO_TYPE (t));

      if (BINFO_VIRTUAL_P (t))
	dump_string_field (di, "spec", "virt");

      dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
      for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
	{
	  tree access = (accesses ? (*accesses)[ix] : access_public_node);
	  const char *string = NULL;

	  if (access == access_public_node)
	    string = "pub";
	  else if (access == access_protected_node)
	    string = "prot";
	  else if (access == access_private_node)
	    string = "priv";
	  else
	    gcc_unreachable ();

	  dump_string_field (di, "accs", string);
	  queue_and_dump_index (di, "binf", base, DUMP_BINFO);
	}

      goto done;
    }

  /* We can knock off a bunch of expression nodes in exactly the same
     way.  */
  if (IS_EXPR_CODE_CLASS (code_class))
    {
      /* If we're dumping children, dump them now.  */
      queue_and_dump_type (di, t);

      switch (code_class)
	{
	case tcc_unary:
	  dump_child ("op 0", TREE_OPERAND (t, 0));
	  break;

	case tcc_binary:
	case tcc_comparison:
	  dump_child ("op 0", TREE_OPERAND (t, 0));
	  dump_child ("op 1", TREE_OPERAND (t, 1));
	  break;

	case tcc_expression:
	case tcc_reference:
	case tcc_statement:
	case tcc_vl_exp:
	  /* These nodes are handled explicitly below.  */
	  break;

	default:
	  gcc_unreachable ();
	}
    }
  else if (DECL_P (t))
    {
      expanded_location xloc;
      /* All declarations have names.  */
      if (DECL_NAME (t))
	dump_child ("name", DECL_NAME (t));
      if (DECL_ASSEMBLER_NAME_SET_P (t)
	  && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
	dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
      if (DECL_ABSTRACT_ORIGIN (t))
        dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
      /* And types.  */
      queue_and_dump_type (di, t);
      dump_child ("scpe", DECL_CONTEXT (t));
      /* And a source position.  */
      xloc = expand_location (DECL_SOURCE_LOCATION (t));
      if (xloc.file)
	{
	  const char *filename = lbasename (xloc.file);

	  dump_maybe_newline (di);
	  fprintf (di->stream, "srcp: %s:%-6d ", filename,
		   xloc.line);
	  di->column += 6 + strlen (filename) + 8;
	}
      /* And any declaration can be compiler-generated.  */
      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
	  && DECL_ARTIFICIAL (t))
	dump_string_field (di, "note", "artificial");
      if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
	dump_child ("chain", DECL_CHAIN (t));
    }
  else if (code_class == tcc_type)
    {
      /* All types have qualifiers.  */
      int quals = lang_hooks.tree_dump.type_quals (t);

      if (quals != TYPE_UNQUALIFIED)
	{
	  fprintf (di->stream, "qual: %c%c%c     ",
		   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
		   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
	  di->column += 14;
	}

      /* All types have associated declarations.  */
      dump_child ("name", TYPE_NAME (t));

      /* All types have a main variant.  */
      if (TYPE_MAIN_VARIANT (t) != t)
	dump_child ("unql", TYPE_MAIN_VARIANT (t));

      /* And sizes.  */
      dump_child ("size", TYPE_SIZE (t));

      /* All types have alignments.  */
      dump_int (di, "algn", TYPE_ALIGN (t));
    }
  else if (code_class == tcc_constant)
    /* All constants can have types.  */
    queue_and_dump_type (di, t);

  /* Give the language-specific code a chance to print something.  If
     it's completely taken care of things, don't bother printing
     anything more ourselves.  */
  if (lang_hooks.tree_dump.dump_tree (di, t))
    goto done;

  /* Now handle the various kinds of nodes.  */
  switch (code)
    {
      int i;

    case IDENTIFIER_NODE:
      dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
      dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
      break;

    case TREE_LIST:
      dump_child ("purp", TREE_PURPOSE (t));
      dump_child ("valu", TREE_VALUE (t));
      dump_child ("chan", TREE_CHAIN (t));
      break;

    case STATEMENT_LIST:
      {
	tree_stmt_iterator it;
	for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
	  {
	    char buffer[32];
	    sprintf (buffer, "%u", i);
	    dump_child (buffer, tsi_stmt (it));
	  }
      }
      break;

    case TREE_VEC:
      dump_int (di, "lngt", TREE_VEC_LENGTH (t));
      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
	{
	  char buffer[32];
	  sprintf (buffer, "%u", i);
	  dump_child (buffer, TREE_VEC_ELT (t, i));
	}
      break;

    case INTEGER_TYPE:
    case ENUMERAL_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
      dump_child ("min", TYPE_MIN_VALUE (t));
      dump_child ("max", TYPE_MAX_VALUE (t));

      if (code == ENUMERAL_TYPE)
	dump_child ("csts", TYPE_VALUES (t));
      break;

    case REAL_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      break;

    case FIXED_POINT_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
      dump_string_field (di, "saturating",
			 TYPE_SATURATING (t) ? "saturating": "non-saturating");
      break;

    case POINTER_TYPE:
      dump_child ("ptd", TREE_TYPE (t));
      break;

    case REFERENCE_TYPE:
      dump_child ("refd", TREE_TYPE (t));
      break;

    case METHOD_TYPE:
      dump_child ("clas", TYPE_METHOD_BASETYPE (t));
      /* Fall through.  */

    case FUNCTION_TYPE:
      dump_child ("retn", TREE_TYPE (t));
      dump_child ("prms", TYPE_ARG_TYPES (t));
      break;

    case ARRAY_TYPE:
      dump_child ("elts", TREE_TYPE (t));
      dump_child ("domn", TYPE_DOMAIN (t));
      break;

    case RECORD_TYPE:
    case UNION_TYPE:
      if (TREE_CODE (t) == RECORD_TYPE)
	dump_string_field (di, "tag", "struct");
      else
	dump_string_field (di, "tag", "union");

      dump_child ("flds", TYPE_FIELDS (t));
      dump_child ("fncs", TYPE_METHODS (t));
      queue_and_dump_index (di, "binf", TYPE_BINFO (t),
			    DUMP_BINFO);
      break;

    case CONST_DECL:
      dump_child ("cnst", DECL_INITIAL (t));
      break;

    case DEBUG_EXPR_DECL:
      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
      /* Fall through.  */

    case VAR_DECL:
    case PARM_DECL:
    case FIELD_DECL:
    case RESULT_DECL:
      if (TREE_CODE (t) == PARM_DECL)
	dump_child ("argt", DECL_ARG_TYPE (t));
      else
	dump_child ("init", DECL_INITIAL (t));
      dump_child ("size", DECL_SIZE (t));
      dump_int (di, "algn", DECL_ALIGN (t));

      if (TREE_CODE (t) == FIELD_DECL)
	{
	  if (DECL_FIELD_OFFSET (t))
	    dump_child ("bpos", bit_position (t));
	}
      else if (TREE_CODE (t) == VAR_DECL
	       || TREE_CODE (t) == PARM_DECL)
	{
	  dump_int (di, "used", TREE_USED (t));
	  if (DECL_REGISTER (t))
	    dump_string_field (di, "spec", "register");
	}
      break;

    case FUNCTION_DECL:
      dump_child ("args", DECL_ARGUMENTS (t));
      if (DECL_EXTERNAL (t))
	dump_string_field (di, "body", "undefined");
      if (TREE_PUBLIC (t))
	dump_string_field (di, "link", "extern");
      else
	dump_string_field (di, "link", "static");
      if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
	dump_child ("body", DECL_SAVED_TREE (t));
      break;

    case INTEGER_CST:
      if (TREE_INT_CST_HIGH (t))
	dump_int (di, "high", TREE_INT_CST_HIGH (t));
      dump_int (di, "low", TREE_INT_CST_LOW (t));
      break;

    case STRING_CST:
      fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
      dump_int (di, "lngt", TREE_STRING_LENGTH (t));
      break;

    case REAL_CST:
      dump_real (di, "valu", TREE_REAL_CST_PTR (t));
      break;

    case FIXED_CST:
      dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
      break;

    case TRUTH_NOT_EXPR:
    case ADDR_EXPR:
    case INDIRECT_REF:
    case CLEANUP_POINT_EXPR:
    case SAVE_EXPR:
    case REALPART_EXPR:
    case IMAGPART_EXPR:
      /* These nodes are unary, but do not have code class `1'.  */
      dump_child ("op 0", TREE_OPERAND (t, 0));
      break;

    case TRUTH_ANDIF_EXPR:
    case TRUTH_ORIF_EXPR:
    case INIT_EXPR:
    case MODIFY_EXPR:
    case COMPOUND_EXPR:
    case PREDECREMENT_EXPR:
    case PREINCREMENT_EXPR:
    case POSTDECREMENT_EXPR:
    case POSTINCREMENT_EXPR:
      /* These nodes are binary, but do not have code class `2'.  */
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      break;

    case COMPONENT_REF:
    case BIT_FIELD_REF:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      break;

    case ARRAY_REF:
    case ARRAY_RANGE_REF:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      dump_child ("op 3", TREE_OPERAND (t, 3));
      break;

    case COND_EXPR:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      break;

    case TRY_FINALLY_EXPR:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      break;

    case CALL_EXPR:
      {
	int i = 0;
	tree arg;
	call_expr_arg_iterator iter;
	dump_child ("fn", CALL_EXPR_FN (t));
	FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
	  {
	    char buffer[32];
	    sprintf (buffer, "%u", i);
	    dump_child (buffer, arg);
	    i++;
	  }
      }
      break;

    case CONSTRUCTOR:
      {
	unsigned HOST_WIDE_INT cnt;
	tree index, value;
	dump_int (di, "lngt", vec_safe_length (CONSTRUCTOR_ELTS (t)));
	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
	  {
	    dump_child ("idx", index);
	    dump_child ("val", value);
	  }
      }
Ejemplo n.º 22
0
void
use_thunk (tree thunk_fndecl, bool emit_p)
{
    tree a, t, function, alias;
    tree virtual_offset;
    HOST_WIDE_INT fixed_offset, virtual_value;
    bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);

    /* We should have called finish_thunk to give it a name.  */
    gcc_assert (DECL_NAME (thunk_fndecl));

    /* We should never be using an alias, always refer to the
       aliased thunk.  */
    gcc_assert (!THUNK_ALIAS (thunk_fndecl));

    if (TREE_ASM_WRITTEN (thunk_fndecl))
        return;

    function = THUNK_TARGET (thunk_fndecl);
    if (DECL_RESULT (thunk_fndecl))
        /* We already turned this thunk into an ordinary function.
           There's no need to process this thunk again.  */
        return;

    if (DECL_THUNK_P (function))
        /* The target is itself a thunk, process it now.  */
        use_thunk (function, emit_p);

    /* Thunks are always addressable; they only appear in vtables.  */
    TREE_ADDRESSABLE (thunk_fndecl) = 1;

    /* Figure out what function is being thunked to.  It's referenced in
       this translation unit.  */
    TREE_ADDRESSABLE (function) = 1;
    mark_used (function);
    if (!emit_p)
        return;

    if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function))
        alias = make_alias_for_thunk (function);
    else
        alias = function;

    fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
    virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);

    if (virtual_offset)
    {
        if (!this_adjusting)
            virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
        virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
        gcc_assert (virtual_value);
    }
    else
        virtual_value = 0;

    /* And, if we need to emit the thunk, it's used.  */
    mark_used (thunk_fndecl);
    /* This thunk is actually defined.  */
    DECL_EXTERNAL (thunk_fndecl) = 0;
    /* The linkage of the function may have changed.  FIXME in linkage
       rewrite.  */
    TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
    DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
    DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
        = DECL_VISIBILITY_SPECIFIED (function);
    if (DECL_ONE_ONLY (function))
        make_decl_one_only (thunk_fndecl);

    if (flag_syntax_only)
    {
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
        return;
    }

    push_to_top_level ();

    if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)
            && targetm.have_named_sections)
    {
        resolve_unique_section (function, 0, flag_function_sections);

        if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function))
        {
            resolve_unique_section (thunk_fndecl, 0, flag_function_sections);

            /* Output the thunk into the same section as function.  */
            DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
        }
    }

    /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
       create one.  */
    DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);

    /* Set up cloned argument trees for the thunk.  */
    t = NULL_TREE;
    for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
    {
        tree x = copy_node (a);
        TREE_CHAIN (x) = t;
        DECL_CONTEXT (x) = thunk_fndecl;
        SET_DECL_RTL (x, NULL_RTX);
        DECL_HAS_VALUE_EXPR_P (x) = 0;
        t = x;
    }
    a = nreverse (t);
    DECL_ARGUMENTS (thunk_fndecl) = a;
    BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a;

    if (this_adjusting
            && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
                    virtual_value, alias))
    {
        const char *fnname;
        current_function_decl = thunk_fndecl;
        DECL_RESULT (thunk_fndecl)
            = build_decl (RESULT_DECL, 0, integer_type_node);
        fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
        init_function_start (thunk_fndecl);
        current_function_is_thunk = 1;
        assemble_start_function (thunk_fndecl, fnname);

        targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
                                         fixed_offset, virtual_value, alias);

        assemble_end_function (thunk_fndecl, fnname);
        init_insn_lengths ();
        current_function_decl = 0;
        cfun = 0;
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
    }
    else
    {
        /* If this is a covariant thunk, or we don't have the necessary
        code for efficient thunks, generate a thunk function that
         just makes a call to the real function.  Unfortunately, this
         doesn't work for varargs.  */

        if (varargs_function_p (function))
            error ("generic thunk code fails for method %q#D which uses %<...%>",
                   function);

        DECL_RESULT (thunk_fndecl) = NULL_TREE;

        start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
        /* We don't bother with a body block for thunks.  */

        /* There's no need to check accessibility inside the thunk body.  */
        push_deferring_access_checks (dk_no_check);

        t = a;
        if (this_adjusting)
            t = thunk_adjust (t, /*this_adjusting=*/1,
                              fixed_offset, virtual_offset);

        /* Build up the call to the real function.  */
        t = tree_cons (NULL_TREE, t, NULL_TREE);
        for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
            t = tree_cons (NULL_TREE, a, t);
        t = nreverse (t);
        t = build_call (alias, t);
        CALL_FROM_THUNK_P (t) = 1;

        if (VOID_TYPE_P (TREE_TYPE (t)))
            finish_expr_stmt (t);
        else
        {
            if (!this_adjusting)
            {
                tree cond = NULL_TREE;

                if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
                {
                    /* If the return type is a pointer, we need to
                       protect against NULL.  We know there will be an
                       adjustment, because that's why we're emitting a
                       thunk.  */
                    t = save_expr (t);
                    cond = cp_convert (boolean_type_node, t);
                }

                t = thunk_adjust (t, /*this_adjusting=*/0,
                                  fixed_offset, virtual_offset);
                if (cond)
                    t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
                                cp_convert (TREE_TYPE (t), integer_zero_node));
            }
            if (IS_AGGR_TYPE (TREE_TYPE (t)))
                t = build_cplus_new (TREE_TYPE (t), t);
            finish_return_stmt (t);
        }

        /* Since we want to emit the thunk, we explicitly mark its name as
        referenced.  */
        mark_decl_referenced (thunk_fndecl);

        /* But we don't want debugging information about it.  */
        DECL_IGNORED_P (thunk_fndecl) = 1;

        /* Re-enable access control.  */
        pop_deferring_access_checks ();

        thunk_fndecl = finish_function (0);
        tree_lowering_passes (thunk_fndecl);
        expand_body (thunk_fndecl);
    }

    pop_from_top_level ();
}
Ejemplo n.º 23
0
/* Return a tree expression for a call to the overloaded builtin
   function OB_FNDECL at LOC with arguments PASSED_ARGLIST.  */
tree
s390_resolve_overloaded_builtin (location_t loc,
				 tree ob_fndecl,
				 void *passed_arglist)
{
  vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
  unsigned int in_args_num = vec_safe_length (arglist);
  unsigned int ob_args_num = 0;
  unsigned int ob_fcode = DECL_FUNCTION_CODE (ob_fndecl);
  enum s390_overloaded_builtin_vars bindex;
  unsigned int i;
  int last_match_type = INT_MAX;
  int last_match_index = -1;
  unsigned int all_op_flags;
  const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
  int num_matches = 0;
  tree target_builtin_decl, b_arg_chain, return_type;
  enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;

  if (TARGET_DEBUG_ARG)
    fprintf (stderr,
      "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
      (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
     ob_fcode < S390_BUILTIN_MAX ? "not" : "");

  /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins.  */
  if (ob_fcode < S390_BUILTIN_MAX)
    {
      if (ob_flags & B_INT)
	{
	  error_at (loc,
		    "builtin %qF is for GCC internal use only.",
		    ob_fndecl);
	  return error_mark_node;
	}
      return NULL_TREE;
    }

  if (ob_flags & B_DEP)
    warning_at (loc, 0, "builtin %qF is deprecated.", ob_fndecl);

  if (!TARGET_VX && (ob_flags & B_VX))
    {
      error_at (loc, "%qF requires -mvx", ob_fndecl);
      return error_mark_node;
    }

  if (!TARGET_VXE && (ob_flags & B_VXE))
    {
      error_at (loc, "%qF requires z14 or higher", ob_fndecl);
      return error_mark_node;
    }

  ob_fcode -= S390_BUILTIN_MAX;

  for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
       !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
       b_arg_chain = TREE_CHAIN (b_arg_chain))
    ob_args_num++;

  if (ob_args_num != in_args_num)
    {
      error_at (loc,
		"mismatch in number of arguments for builtin %qF. "
		"Expected: %d got %d", ob_fndecl,
		ob_args_num, in_args_num);
      return error_mark_node;
    }

  for (i = 0; i < in_args_num; i++)
    if ((*arglist)[i] == error_mark_node)
      return error_mark_node;

  /* Overloaded builtins without any variants are directly expanded here.  */
  if (desc_start_for_overloaded_builtin[ob_fcode] ==
      S390_OVERLOADED_BUILTIN_VAR_MAX)
    return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);

  for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
       bindex <= desc_end_for_overloaded_builtin[ob_fcode];
       bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
  {
    int match_type;
    enum s390_builtin_ov_type_index type_index =
      type_for_overloaded_builtin_var[bindex];

    if (TARGET_DEBUG_ARG)
      fprintf (stderr, "checking variant number: %d", (int)bindex);

    match_type = s390_fn_types_compatible (type_index, arglist);

    if (match_type == INT_MAX)
      continue;

    if (TARGET_DEBUG_ARG)
      fprintf (stderr,
	       " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
	       match_type);

    if (match_type < last_match_type)
      {
	num_matches = 1;
	last_match_type = match_type;
	last_match_fntype_index = type_index;
	last_match_index = bindex;
      }
    else if (match_type == last_match_type)
      num_matches++;
  }

  if (last_match_type == INT_MAX)
    {
      error_at (loc, "invalid parameter combination for intrinsic %qs",
		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
      return error_mark_node;
    }
  else if (num_matches > 1)
    {
      error_at (loc, "ambiguous overload for intrinsic %qs",
		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
      return error_mark_node;
    }

  if (!TARGET_VXE
      && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
    {
      error_at (loc, "%qs matching variant requires z14 or higher",
		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
      return error_mark_node;
    }

  if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
    warning_at (loc, 0, "%qs matching variant is deprecated.",
		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));

  /* Overloaded variants which have MAX set as low level builtin are
     supposed to be replaced during expansion with something else.  */
  if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
    target_builtin_decl = ob_fndecl;
  else
    target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];

  all_op_flags = opflags_overloaded_builtin_var[last_match_index];
  return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];

  /* Check for the operand flags in the overloaded builtin variant.  */
  for (i = 0; i < ob_args_num; i++)
    {
      unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
      tree arg = (*arglist)[i];
      tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];

      all_op_flags = all_op_flags >> O_SHIFT;

      if (op_flags == O_ELEM)
	{
	  int n_elem = s390_vec_n_elem (target_builtin_decl);
	  gcc_assert (n_elem > 0);
	  gcc_assert (type == integer_type_node);
	  (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
				  fold_convert (integer_type_node, arg),
				  build_int_cst (NULL_TREE, n_elem - 1));
	}

      if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
	continue;

      if ((TYPE_UNSIGNED (type)
	   && !int_fits_type_p (arg, c_common_unsigned_type (type)))
	  || (!TYPE_UNSIGNED (type)
	      && !int_fits_type_p (arg, c_common_signed_type (type))))
	{
	  error("constant argument %d for builtin %qF is out "
		"of range for target type",
		i + 1, target_builtin_decl);
	  return error_mark_node;
	}

      if (TREE_CODE (arg) == INTEGER_CST
	  && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
	return error_mark_node;
    }

  /* Handle builtins we expand directly - without mapping it to a low
     level builtin.  */
  if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
    return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);

  s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);

  if (VOID_TYPE_P (return_type))
    return build_function_call_vec (loc, vNULL, target_builtin_decl,
				    arglist, NULL);
  else
    return fully_fold_convert (return_type,
			       build_function_call_vec (loc, vNULL, target_builtin_decl,
							arglist, NULL));
}
Ejemplo n.º 24
0
static void
do_build_copy_constructor (tree fndecl)
{
    tree parm = FUNCTION_FIRST_USER_PARM (fndecl);

    parm = convert_from_reference (parm);

    if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
            && is_empty_class (current_class_type))
        /* Don't copy the padding byte; it might not have been allocated
           if *this is a base subobject.  */;
    else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
    {
        tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
        finish_expr_stmt (t);
    }
    else
    {
        tree fields = TYPE_FIELDS (current_class_type);
        tree member_init_list = NULL_TREE;
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
        tree binfo, base_binfo;
        VEC(tree,gc) *vbases;

        /* Initialize all the base-classes with the parameter converted
        to their type so that we get their copy constructor and not
         another constructor that takes current_class_type.  We must
         deal with the binfo's directly as a direct base might be
         inaccessible due to ambiguity.  */
        for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
                VEC_iterate (tree, vbases, i, binfo); i++)
        {
            member_init_list
                = tree_cons (binfo,
                             build_tree_list (NULL_TREE,
                                              build_base_path (PLUS_EXPR, parm,
                                                      binfo, 1)),
                             member_init_list);
        }

        for (binfo = TYPE_BINFO (current_class_type), i = 0;
                BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
        {
            if (BINFO_VIRTUAL_P (base_binfo))
                continue;

            member_init_list
                = tree_cons (base_binfo,
                             build_tree_list (NULL_TREE,
                                              build_base_path (PLUS_EXPR, parm,
                                                      base_binfo, 1)),
                             member_init_list);
        }

        for (; fields; fields = TREE_CHAIN (fields))
        {
            tree init = parm;
            tree field = fields;
            tree expr_type;

            if (TREE_CODE (field) != FIELD_DECL)
                continue;

            expr_type = TREE_TYPE (field);
            if (DECL_NAME (field))
            {
                if (VFIELD_NAME_P (DECL_NAME (field)))
                    continue;
            }
            else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
                /* Just use the field; anonymous types can't have
                   nontrivial copy ctors or assignment ops.  */;
            else
                continue;

            /* Compute the type of "init->field".  If the copy-constructor
               parameter is, for example, "const S&", and the type of
               the field is "T", then the type will usually be "const
               T".  (There are no cv-qualified variants of reference
               types.)  */
            if (TREE_CODE (expr_type) != REFERENCE_TYPE)
            {
                int quals = cvquals;

                if (DECL_MUTABLE_P (field))
                    quals &= ~TYPE_QUAL_CONST;
                expr_type = cp_build_qualified_type (expr_type, quals);
            }

            init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
            init = build_tree_list (NULL_TREE, init);

            member_init_list = tree_cons (field, init, member_init_list);
        }
        finish_mem_initializers (member_init_list);
    }
}
Ejemplo n.º 25
0
static tree
get_non_ssa_expr (tree expr)
{
  if (!expr)
    return NULL_TREE;
  switch (TREE_CODE (expr))
    {
      case VAR_DECL:
      case PARM_DECL:
      case FIELD_DECL:
        {
          if (DECL_NAME (expr))
            return expr;
          else
            return NULL_TREE;
        }
      case COMPONENT_REF:
        {
          tree base, orig_base = TREE_OPERAND (expr, 0);
          tree component, orig_component = TREE_OPERAND (expr, 1);
          base = get_non_ssa_expr (orig_base);
          if (!base)
            return NULL_TREE;
          component = get_non_ssa_expr (orig_component);
          if (!component)
            return NULL_TREE;
          /* If either BASE or COMPONENT is converted, build a new
             component reference tree.  */
          if (base != orig_base || component != orig_component)
            return build3 (COMPONENT_REF, TREE_TYPE (component),
                           base, component, NULL_TREE);
          else
            return expr;
        }
      case MEM_REF:
        {
          tree orig_base = TREE_OPERAND (expr, 0);
	  if (TREE_CODE (orig_base) == SSA_NAME)
	    {
	      tree base = get_non_ssa_expr (orig_base);
	      if (!base)
		return NULL_TREE;
	      return fold_build2 (MEM_REF, TREE_TYPE (expr),
				  base, TREE_OPERAND (expr, 1));
	    }
	  return expr;
        }
      case ARRAY_REF:
        {
          tree array, orig_array = TREE_OPERAND (expr, 0);
          tree index, orig_index = TREE_OPERAND (expr, 1);
          array = get_non_ssa_expr (orig_array);
          if (!array)
            return NULL_TREE;
          index = get_non_ssa_expr (orig_index);
          if (!index)
            return NULL_TREE;
          /* If either ARRAY or INDEX is converted, build a new array
             reference tree.  */
          if (array != orig_array || index != orig_index)
            return build4 (ARRAY_REF, TREE_TYPE (expr), array, index,
                           TREE_OPERAND (expr, 2), TREE_OPERAND (expr, 3));
          else
            return expr;
        }
      case SSA_NAME:
        {
          tree vdecl = SSA_NAME_VAR (expr);
          if ((!vdecl || DECL_ARTIFICIAL (vdecl))
              && !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
            {
              gimple def_stmt = SSA_NAME_DEF_STMT (expr);
              if (gimple_assign_single_p (def_stmt))
                vdecl = gimple_assign_rhs1 (def_stmt);
            }
          return get_non_ssa_expr (vdecl);
        }
      case INTEGER_CST:
        return expr;
      default:
        /* Return NULL_TREE for any other kind of tree nodes.  */
        return NULL_TREE;
    }
}
Ejemplo n.º 26
0
static void
do_build_assign_ref (tree fndecl)
{
    tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
    tree compound_stmt;

    compound_stmt = begin_compound_stmt (0);
    parm = convert_from_reference (parm);

    if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
            && is_empty_class (current_class_type))
        /* Don't copy the padding byte; it might not have been allocated
           if *this is a base subobject.  */;
    else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
    {
        tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm);
        finish_expr_stmt (t);
    }
    else
    {
        tree fields;
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
        tree binfo, base_binfo;

        /* Assign to each of the direct base classes.  */
        for (binfo = TYPE_BINFO (current_class_type), i = 0;
                BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
        {
            tree converted_parm;

            /* We must convert PARM directly to the base class
               explicitly since the base class may be ambiguous.  */
            converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
            /* Call the base class assignment operator.  */
            finish_expr_stmt
            (build_special_member_call (current_class_ref,
                                        ansi_assopname (NOP_EXPR),
                                        build_tree_list (NULL_TREE,
                                                converted_parm),
                                        base_binfo,
                                        LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
        }

        /* Assign to each of the non-static data members.  */
        for (fields = TYPE_FIELDS (current_class_type);
                fields;
                fields = TREE_CHAIN (fields))
        {
            tree comp = current_class_ref;
            tree init = parm;
            tree field = fields;
            tree expr_type;
            int quals;

            if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
                continue;

            expr_type = TREE_TYPE (field);

            if (CP_TYPE_CONST_P (expr_type))
            {
                error ("non-static const member %q#D, can't use default "
                       "assignment operator", field);
                continue;
            }
            else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
            {
                error ("non-static reference member %q#D, can't use "
                       "default assignment operator", field);
                continue;
            }

            if (DECL_NAME (field))
            {
                if (VFIELD_NAME_P (DECL_NAME (field)))
                    continue;
            }
            else if (ANON_AGGR_TYPE_P (expr_type)
                     && TYPE_FIELDS (expr_type) != NULL_TREE)
                /* Just use the field; anonymous types can't have
                   nontrivial copy ctors or assignment ops.  */;
            else
                continue;

            comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);

            /* Compute the type of init->field  */
            quals = cvquals;
            if (DECL_MUTABLE_P (field))
                quals &= ~TYPE_QUAL_CONST;
            expr_type = cp_build_qualified_type (expr_type, quals);

            init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);

            if (DECL_NAME (field))
                init = build_modify_expr (comp, NOP_EXPR, init);
            else
                init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
            finish_expr_stmt (init);
        }
    }
    finish_return_stmt (current_class_ref);
    finish_compound_stmt (compound_stmt);
}
Ejemplo n.º 27
0
static void
sdbout_one_type (tree type)
{
  if (current_function_decl != NULL_TREE
      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
    ; /* Don't change section amid function.  */
  else
    text_section ();

  switch (TREE_CODE (type))
    {
    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE:
    case ENUMERAL_TYPE:
      type = TYPE_MAIN_VARIANT (type);
      /* Don't output a type twice.  */
      if (TREE_ASM_WRITTEN (type))
	/* James said test TREE_ASM_BEING_WRITTEN here.  */
	return;

      /* Output nothing if type is not yet defined.  */
      if (!COMPLETE_TYPE_P (type))
	return;

      TREE_ASM_WRITTEN (type) = 1;

      /* This is reputed to cause trouble with the following case,
	 but perhaps checking TYPE_SIZE above will fix it.  */

      /* Here is a testcase:

	struct foo {
	  struct badstr *bbb;
	} forwardref;

	typedef struct intermediate {
	  int aaaa;
	} intermediate_ref;

	typedef struct badstr {
	  int ccccc;
	} badtype;   */

      /* This change, which ought to make better output,
	 used to make the COFF assembler unhappy.
	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
      /* Before really doing anything, output types we want to refer to.  */
      /* Note that in version 1 the following two lines
	 are not used if forward references are in use.  */
      if (TREE_CODE (type) != ENUMERAL_TYPE)
	sdbout_field_types (type);

      /* Output a structure type.  */
      {
	int size = int_size_in_bytes (type);
	int member_scl = 0;
	tree tem;

	/* Record the type tag, but not in its permanent place just yet.  */
	sdbout_record_type_name (type);

	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));

	switch (TREE_CODE (type))
	  {
	  case UNION_TYPE:
	  case QUAL_UNION_TYPE:
	    PUT_SDB_SCL (C_UNTAG);
	    PUT_SDB_TYPE (T_UNION);
	    member_scl = C_MOU;
	    break;

	  case RECORD_TYPE:
	    PUT_SDB_SCL (C_STRTAG);
	    PUT_SDB_TYPE (T_STRUCT);
	    member_scl = C_MOS;
	    break;

	  case ENUMERAL_TYPE:
	    PUT_SDB_SCL (C_ENTAG);
	    PUT_SDB_TYPE (T_ENUM);
	    member_scl = C_MOE;
	    break;

	  default:
	    break;
	  }

	PUT_SDB_SIZE (size);
	PUT_SDB_ENDEF;

	/* Print out the base class information with fields
	   named after the types they hold.  */
	/* This is only relevant to aggregate types.  TYPE_BINFO is used
	   for other purposes in an ENUMERAL_TYPE, so we must exclude that
	   case.  */
	if (TREE_CODE (type) != ENUMERAL_TYPE && TYPE_BINFO (type))
	  {
	    int i;
	    tree binfo, child;

	    for (binfo = TYPE_BINFO (type), i = 0;
		 BINFO_BASE_ITERATE (binfo, i, child); i++)
	      {
		tree child_type = BINFO_TYPE (child);
		tree child_type_name;
		
		if (TYPE_NAME (child_type) == 0)
		  continue;
		if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
		  child_type_name = TYPE_NAME (child_type);
		else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
		  {
		    child_type_name = DECL_NAME (TYPE_NAME (child_type));
		    if (child_type_name && template_name_p (child_type_name))
		      child_type_name
			= DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
		  }
		else
		  continue;

		PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
		PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
		PUT_SDB_SCL (member_scl);
		sdbout_type (BINFO_TYPE (child));
		PUT_SDB_ENDEF;
	      }
	  }

	/* Output the individual fields.  */

	if (TREE_CODE (type) == ENUMERAL_TYPE)
	  {
	    for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
	      if (host_integerp (TREE_VALUE (tem), 0))
		{
		  PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
		  PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0));
		  PUT_SDB_SCL (C_MOE);
		  PUT_SDB_TYPE (T_MOE);
		  PUT_SDB_ENDEF;
		}
	  }
	else			/* record or union type */
	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
	    /* Output the name, type, position (in bits), size (in bits)
	       of each field.  */

	    /* Omit here the nameless fields that are used to skip bits.
	       Also omit fields with variable size or position.
	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
	    if (TREE_CODE (tem) == FIELD_DECL
		&& DECL_NAME (tem)
		&& DECL_SIZE (tem)
		&& host_integerp (DECL_SIZE (tem), 1)
		&& host_integerp (bit_position (tem), 0))
	      {
		const char *name;

		name = IDENTIFIER_POINTER (DECL_NAME (tem));
		PUT_SDB_DEF (name);
		if (DECL_BIT_FIELD_TYPE (tem))
		  {
		    PUT_SDB_INT_VAL (int_bit_position (tem));
		    PUT_SDB_SCL (C_FIELD);
		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
		    PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
		  }
		else
		  {
		    PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
		    PUT_SDB_SCL (member_scl);
		    sdbout_type (TREE_TYPE (tem));
		  }
		PUT_SDB_ENDEF;
	      }
	/* Output end of a structure,union, or enumeral definition.  */

	PUT_SDB_PLAIN_DEF ("eos");
	PUT_SDB_INT_VAL (size);
	PUT_SDB_SCL (C_EOS);
	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
	PUT_SDB_SIZE (size);
	PUT_SDB_ENDEF;
	break;

      default:
	break;
      }
    }
}
Ejemplo n.º 28
0
static void
tree_expand_cfg (void)
{
  basic_block bb, init_block;
  sbitmap blocks;

  /* Some backends want to know that we are expanding to RTL.  */
  currently_expanding_to_rtl = 1;

  /* Prepare the rtl middle end to start recording block changes.  */
  reset_block_changes ();

  /* Expand the variables recorded during gimple lowering.  */
  expand_used_vars ();

#ifdef KEY
  // Run expand_used_vars above to set DECL_SECTION_NAME.  Bug 10876.
  if (flag_spin_file)
    return;
#endif

  /* Set up parameters and prepare for return, for the function.  */
  expand_function_start (current_function_decl);

  /* If this function is `main', emit a call to `__main'
     to run global initializers, etc.  */
  if (DECL_NAME (current_function_decl)
      && MAIN_NAME_P (DECL_NAME (current_function_decl))
      && DECL_FILE_SCOPE_P (current_function_decl))
    expand_main_function ();

  /* Register rtl specific functions for cfg.  */
  rtl_register_cfg_hooks ();

  init_block = construct_init_block ();

  FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb)
    bb = expand_gimple_basic_block (bb, dump_file);

  construct_exit_block ();

  /* We're done expanding trees to RTL.  */
  currently_expanding_to_rtl = 0;

  /* Convert tree EH labels to RTL EH labels, and clean out any unreachable
     EH regions.  */
  convert_from_eh_region_ranges ();

  rebuild_jump_labels (get_insns ());
  find_exception_handler_labels ();

  blocks = sbitmap_alloc (last_basic_block);
  sbitmap_ones (blocks);
  find_many_sub_basic_blocks (blocks);
  purge_all_dead_edges (0);
  sbitmap_free (blocks);

  compact_blocks ();
#ifdef ENABLE_CHECKING
  verify_flow_info();
#endif

  /* There's no need to defer outputting this function any more; we
     know we want to output it.  */
  DECL_DEFER_OUTPUT (current_function_decl) = 0;

  /* Now that we're done expanding trees to RTL, we shouldn't have any
     more CONCATs anywhere.  */
  generating_concat_p = 0;

  finalize_block_changes ();

  if (dump_file)
    {
      fprintf (dump_file,
	       "\n\n;;\n;; Full RTL generated for this function:\n;;\n");
      /* And the pass manager will dump RTL for us.  */
    }
}
Ejemplo n.º 29
0
static int
plain_type_1 (tree type, int level)
{
  if (type == 0)
    type = void_type_node;
  else if (type == error_mark_node)
    type = integer_type_node;
  else
    type = TYPE_MAIN_VARIANT (type);

  switch (TREE_CODE (type))
    {
    case VOID_TYPE:
      return T_VOID;
    case BOOLEAN_TYPE:
    case INTEGER_TYPE:
      {
	int size = int_size_in_bytes (type) * BITS_PER_UNIT;

	/* Carefully distinguish all the standard types of C,
	   without messing up if the language is not C.
	   Note that we check only for the names that contain spaces;
	   other names might occur by coincidence in other languages.  */
	if (TYPE_NAME (type) != 0
	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
	    && DECL_NAME (TYPE_NAME (type)) != 0
	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
	  {
	    const char *const name
	      = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));

	    if (!strcmp (name, "char"))
	      return T_CHAR;
	    if (!strcmp (name, "unsigned char"))
	      return T_UCHAR;
	    if (!strcmp (name, "signed char"))
	      return T_CHAR;
	    if (!strcmp (name, "int"))
	      return T_INT;
	    if (!strcmp (name, "unsigned int"))
	      return T_UINT;
	    if (!strcmp (name, "short int"))
	      return T_SHORT;
	    if (!strcmp (name, "short unsigned int"))
	      return T_USHORT;
	    if (!strcmp (name, "long int"))
	      return T_LONG;
	    if (!strcmp (name, "long unsigned int"))
	      return T_ULONG;
	  }

	if (size == INT_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_UINT : T_INT);
	if (size == CHAR_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
	if (size == SHORT_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_USHORT : T_SHORT);
	if (size == LONG_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG);
	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
	  return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG);
	return 0;
      }

    case REAL_TYPE:
      {
	int precision = TYPE_PRECISION (type);
	if (precision == FLOAT_TYPE_SIZE)
	  return T_FLOAT;
	if (precision == DOUBLE_TYPE_SIZE)
	  return T_DOUBLE;
#ifdef EXTENDED_SDB_BASIC_TYPES
	if (precision == LONG_DOUBLE_TYPE_SIZE)
	  return T_LNGDBL;
#else
	if (precision == LONG_DOUBLE_TYPE_SIZE)
	  return T_DOUBLE;	/* better than nothing */
#endif
	return 0;
      }

    case ARRAY_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	if (sdb_n_dims < SDB_MAX_DIM)
	  sdb_dims[sdb_n_dims++]
	    = (TYPE_DOMAIN (type)
	       && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
	       && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
	       && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
	       ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
		  - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1)
	       : 0);

	return PUSH_DERIVED_LEVEL (DT_ARY, m);
      }

    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE:
    case ENUMERAL_TYPE:
      {
	char *tag;
#ifdef SDB_ALLOW_FORWARD_REFERENCES
	sdbout_record_type_name (type);
#endif
#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
#ifdef SDB_ALLOW_FORWARD_REFERENCES
	    || TYPE_MODE (type) != VOIDmode
#endif
	    )
#endif
	  {
	    /* Output the referenced structure tag name
	       only if the .def has already been finished.
	       At least on 386, the Unix assembler
	       cannot handle forward references to tags.  */
	    /* But the 88100, it requires them, sigh...  */
	    /* And the MIPS requires unknown refs as well...  */
	    tag = KNOWN_TYPE_TAG (type);
	    PUT_SDB_TAG (tag);
	    /* These 3 lines used to follow the close brace.
	       However, a size of 0 without a tag implies a tag of 0,
	       so if we don't know a tag, we can't mention the size.  */
	    sdb_type_size = int_size_in_bytes (type);
	    if (sdb_type_size < 0)
	      sdb_type_size = 0;
	  }
	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
		: T_ENUM);
      }
    case POINTER_TYPE:
    case REFERENCE_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	return PUSH_DERIVED_LEVEL (DT_PTR, m);
      }
    case FUNCTION_TYPE:
    case METHOD_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	return PUSH_DERIVED_LEVEL (DT_FCN, m);
      }
    default:
      return 0;
    }
}
Ejemplo n.º 30
0
void
print_node_brief (FILE *file, const char *prefix, const_tree node, int indent)
{
  enum tree_code_class tclass;

  if (node == 0)
    return;

  tclass = TREE_CODE_CLASS (TREE_CODE (node));

  /* Always print the slot this node is in, and its code, address and
     name if any.  */
  if (indent > 0)
    fprintf (file, " ");
  fprintf (file, "%s <%s", prefix, get_tree_code_name (TREE_CODE (node)));
  dump_addr (file, " ", node);

  if (tclass == tcc_declaration)
    {
      if (DECL_NAME (node))
	fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
      else if (TREE_CODE (node) == LABEL_DECL
	       && LABEL_DECL_UID (node) != -1)
	{
	  if (dump_flags & TDF_NOUID)
	    fprintf (file, " L.xxxx");
	  else
	    fprintf (file, " L.%d", (int) LABEL_DECL_UID (node));
	}
      else
	{
	  if (dump_flags & TDF_NOUID)
	    fprintf (file, " %c.xxxx",
		     TREE_CODE (node) == CONST_DECL ? 'C' : 'D');
	  else
	    fprintf (file, " %c.%u",
		     TREE_CODE (node) == CONST_DECL ? 'C' : 'D',
		     DECL_UID (node));
	}
    }
  else if (tclass == tcc_type)
    {
      if (TYPE_NAME (node))
	{
	  if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
	    fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));
	  else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
		   && DECL_NAME (TYPE_NAME (node)))
	    fprintf (file, " %s",
		     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
	}
      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
	fprintf (file, " address-space-%d", TYPE_ADDR_SPACE (node));
    }
  if (TREE_CODE (node) == IDENTIFIER_NODE)
    fprintf (file, " %s", IDENTIFIER_POINTER (node));

  /* We might as well always print the value of an integer or real.  */
  if (TREE_CODE (node) == INTEGER_CST)
    {
      if (TREE_OVERFLOW (node))
	fprintf (file, " overflow");

      fprintf (file, " ");
      print_dec (node, file, TYPE_SIGN (TREE_TYPE (node)));
    }
  if (TREE_CODE (node) == REAL_CST)
    {
      REAL_VALUE_TYPE d;

      if (TREE_OVERFLOW (node))
	fprintf (file, " overflow");

      d = TREE_REAL_CST (node);
      if (REAL_VALUE_ISINF (d))
	fprintf (file,  REAL_VALUE_NEGATIVE (d) ? " -Inf" : " Inf");
      else if (REAL_VALUE_ISNAN (d))
	fprintf (file, " Nan");
      else
	{
	  char string[60];
	  real_to_decimal (string, &d, sizeof (string), 0, 1);
	  fprintf (file, " %s", string);
	}
    }
  if (TREE_CODE (node) == FIXED_CST)
    {
      FIXED_VALUE_TYPE f;
      char string[60];

      if (TREE_OVERFLOW (node))
	fprintf (file, " overflow");

      f = TREE_FIXED_CST (node);
      fixed_to_decimal (string, &f, sizeof (string));
      fprintf (file, " %s", string);
    }

  fprintf (file, ">");
}