示例#1
0
static unsigned int
execute_mudflap_function_decls (void)
{
  struct gimplify_ctx gctx;

  /* Don't instrument functions such as the synthetic constructor
     built during mudflap_finish_file.  */
  if (mf_marked_p (current_function_decl)
      || mf_artificial (current_function_decl))
    return 0;

  push_gimplify_context (&gctx);

  mf_xform_decls (gimple_body (current_function_decl),
                  DECL_ARGUMENTS (current_function_decl));

  pop_gimplify_context (NULL);
  return 0;
}
示例#2
0
static unsigned int
execute_mudflap_function_decls (void)
{
	struct gimplify_ctx gctx;
	DEBUGLOG("Zahed: entering LBC pass1\n");

	/* Don't instrument functions such as the synthetic constructor
	   built during mudflap_finish_file.  */
	if (mf_marked_p (current_function_decl) ||
			DECL_ARTIFICIAL (current_function_decl))
		return 0;

	push_gimplify_context (&gctx);

	mf_xform_decls (gimple_body (current_function_decl),
			DECL_ARGUMENTS (current_function_decl));

	pop_gimplify_context (NULL);
	return 0;
}
示例#3
0
static void
test_gimplification ()
{
  tree fndecl = build_trivial_generic_function ();

  /* Convert to gimple: */
  gimplify_function_tree (fndecl);

  /* Verify that we got gimple out of it.  */

  /* The function is now in GIMPLE form but the CFG has not been
     built yet.  */

  /* We should have a struct function for the decl.  */
  function *fun = DECL_STRUCT_FUNCTION (fndecl);
  ASSERT_TRUE (fun != NULL);
  ASSERT_EQ (fndecl, fun->decl);

  /* We expect a GIMPLE_BIND, with two gimple statements within it:
       tmp = 42;
       return tmp;  */

  gimple_seq seq_fn_body = gimple_body (fndecl);
  ASSERT_TRUE (seq_fn_body != NULL);
  gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
  ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
  ASSERT_EQ (NULL, bind_stmt->next);

  gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));

  /* Verify that we have the 2 statements we expect.  */
  ASSERT_TRUE (seq_bind_body != NULL);
  gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
  ASSERT_TRUE (stmt1 != NULL);
  ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
  gimple *stmt2 = stmt1->next;
  ASSERT_TRUE (stmt2 != NULL);
  ASSERT_EQ (stmt1, stmt2->prev);
  ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
}
示例#4
0
/* Return true when FNDECL has Gimple body either in unlowered
   or CFG form.  */
bool
gimple_has_body_p (tree fndecl)
{
  struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
  return (gimple_body (fndecl) || (fn && fn->cfg));
}
示例#5
0
文件: gimple-low.c 项目: hnaik/gcc
static unsigned int
lower_function_body (void)
{
  struct lower_data data;
  gimple_seq body = gimple_body (current_function_decl);
  gimple_seq lowered_body;
  gimple_stmt_iterator i;
  gimple bind;
  tree t;
  gimple x;

  /* The gimplifier should've left a body of exactly one statement,
     namely a GIMPLE_BIND.  */
  gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
	      && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND);

  memset (&data, 0, sizeof (data));
  data.block = DECL_INITIAL (current_function_decl);
  BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
  BLOCK_CHAIN (data.block) = NULL_TREE;
  TREE_ASM_WRITTEN (data.block) = 1;
  data.return_statements.create (8);

  bind = gimple_seq_first_stmt (body);
  lowered_body = NULL;
  gimple_seq_add_stmt (&lowered_body, bind);
  i = gsi_start (lowered_body);
  lower_gimple_bind (&i, &data);

  i = gsi_last (lowered_body);

  /* If the function falls off the end, we need a null return statement.
     If we've already got one in the return_statements vector, we don't
     need to do anything special.  Otherwise build one by hand.  */
  if (gimple_seq_may_fallthru (lowered_body)
      && (data.return_statements.is_empty ()
	  || gimple_return_retval (data.return_statements.last().stmt) != NULL))
    {
      x = gimple_build_return (NULL);
      gimple_set_location (x, cfun->function_end_locus);
      gimple_set_block (x, DECL_INITIAL (current_function_decl));
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
    }

  /* If we lowered any return statements, emit the representative
     at the end of the function.  */
  while (!data.return_statements.is_empty ())
    {
      return_statements_t t = data.return_statements.pop ();
      x = gimple_build_label (t.label);
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
      gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING);
    }

  /* If the function calls __builtin_setjmp, we need to emit the computed
     goto that will serve as the unique dispatcher for all the receivers.  */
  if (data.calls_builtin_setjmp)
    {
      tree disp_label, disp_var, arg;

      /* Build 'DISP_LABEL:' and insert.  */
      disp_label = create_artificial_label (cfun->function_end_locus);
      /* This mark will create forward edges from every call site.  */
      DECL_NONLOCAL (disp_label) = 1;
      cfun->has_nonlocal_label = 1;
      x = gimple_build_label (disp_label);
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);

      /* Build 'DISP_VAR = __builtin_setjmp_dispatcher (DISP_LABEL);'
	 and insert.  */
      disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
      arg = build_addr (disp_label, current_function_decl);
      t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
      x = gimple_build_call (t, 1, arg);
      gimple_call_set_lhs (x, disp_var);

      /* Build 'goto DISP_VAR;' and insert.  */
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
      x = gimple_build_goto (disp_var);
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
    }

  /* Once the old body has been lowered, replace it with the new
     lowered sequence.  */
  gimple_set_body (current_function_decl, lowered_body);

  gcc_assert (data.block == DECL_INITIAL (current_function_decl));
  BLOCK_SUBBLOCKS (data.block)
    = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));

  clear_block_marks (data.block);
  data.return_statements.release ();
  return 0;
}
static unsigned int
lower_function_body (void)
{
  struct lower_data data;
  gimple_seq body = gimple_body (current_function_decl);
  gimple_seq lowered_body;
  gimple_stmt_iterator i;
  gimple bind;
  gimple x;

  /* The gimplifier should've left a body of exactly one statement,
     namely a GIMPLE_BIND.  */
  gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
	      && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND);

  memset (&data, 0, sizeof (data));
  data.block = DECL_INITIAL (current_function_decl);
  BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
  BLOCK_CHAIN (data.block) = NULL_TREE;
  TREE_ASM_WRITTEN (data.block) = 1;
  data.return_statements.create (8);

  bind = gimple_seq_first_stmt (body);
  lowered_body = NULL;
  gimple_seq_add_stmt (&lowered_body, bind);
  i = gsi_start (lowered_body);
  lower_gimple_bind (&i, &data);

  i = gsi_last (lowered_body);

  /* If the function falls off the end, we need a null return statement.
     If we've already got one in the return_statements vector, we don't
     need to do anything special.  Otherwise build one by hand.  */
  if (gimple_seq_may_fallthru (lowered_body)
      && (data.return_statements.is_empty ()
	  || (gimple_return_retval (data.return_statements.last().stmt)
	      != NULL)))
    {
      x = gimple_build_return (NULL);
      gimple_set_location (x, cfun->function_end_locus);
      gimple_set_block (x, DECL_INITIAL (current_function_decl));
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
    }

  /* If we lowered any return statements, emit the representative
     at the end of the function.  */
  while (!data.return_statements.is_empty ())
    {
      return_statements_t t = data.return_statements.pop ();
      x = gimple_build_label (t.label);
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
      gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING);
    }

  /* Once the old body has been lowered, replace it with the new
     lowered sequence.  */
  gimple_set_body (current_function_decl, lowered_body);

  gcc_assert (data.block == DECL_INITIAL (current_function_decl));
  BLOCK_SUBBLOCKS (data.block)
    = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));

  clear_block_marks (data.block);
  data.return_statements.release ();
  return 0;
}
示例#7
0
static unsigned int
execute_trace ()
{
    gimple_seq body, body_bind_body, inner_cleanup, outer_cleanup;
    gimple inner_try, outer_try;
    tree record_type, func_start_decl, func_end_decl, var_decl,
         function_name_decl, constructor_clobber;
    gimple call_func_start;
    gimple_stmt_iterator gsi;

    // build record type
    record_type = build_type ();
    // build start & end function decl
    func_start_decl = build_function_decl ("__start_ctrace__", record_type);
    func_end_decl = build_function_decl ("__end_ctrace__", record_type);
    // init variables of current body
    body = gimple_body (current_function_decl);

    var_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
                           get_identifier ("__ctrace_var__"), record_type);
    DECL_CONTEXT (var_decl) = current_function_decl;
    TREE_ADDRESSABLE (var_decl) = 1;
    declare_vars (var_decl, body, false);
    TREE_USED (var_decl) = 1;
    // mimic __FUNCTION__ builtin.
    function_name_decl = make_fname_decl ();
    declare_vars (function_name_decl, body, false);
    // construct inner try
    // init calls
    call_func_start = gimple_build_call (
                          func_start_decl, 2,
                          build1 (ADDR_EXPR, build_pointer_type (record_type), var_decl),
                          build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (function_name_decl)),
                                  function_name_decl));
    // make inner clean up
    inner_cleanup = gimple_build_call (
                        func_end_decl, 2,
                        build1 (ADDR_EXPR, build_pointer_type (record_type), var_decl),
                        build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (function_name_decl)),
                                function_name_decl));
    // update inner try
    body_bind_body = gimple_bind_body (body);
    inner_try
        = gimple_build_try (body_bind_body, inner_cleanup, GIMPLE_TRY_FINALLY);
    gsi = gsi_start (inner_try);
    gsi_insert_before (&gsi, call_func_start, GSI_NEW_STMT);
    // construct outer try
    constructor_clobber = make_node (CONSTRUCTOR);
    TREE_THIS_VOLATILE (constructor_clobber) = 1;
    TREE_TYPE (constructor_clobber) = TREE_TYPE (var_decl);
    outer_cleanup = gimple_build_assign (var_decl, constructor_clobber);
    // update outer try
    outer_try
        = gimple_build_try (call_func_start, outer_cleanup, GIMPLE_TRY_FINALLY);
    // update body bind body
    gimple_bind_set_body (body, outer_try);
    if (dump_file)
    {
        dump_function_to_file (current_function_decl, dump_file,
                               TDF_TREE | TDF_BLOCKS | TDF_VERBOSE);
    }
    // exit (0);
    return 0;
}
示例#8
0
static unsigned int
lower_function_body (void)
{
  struct lower_data data;
  gimple_seq body = gimple_body (current_function_decl);
  gimple_seq lowered_body;
  gimple_stmt_iterator i;
  gimple *bind;
  gimple *x;

  /* The gimplifier should've left a body of exactly one statement,
     namely a GIMPLE_BIND.  */
  gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
	      && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND);

  memset (&data, 0, sizeof (data));
  data.block = DECL_INITIAL (current_function_decl);
  BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
  BLOCK_CHAIN (data.block) = NULL_TREE;
  TREE_ASM_WRITTEN (data.block) = 1;
  data.return_statements.create (8);

  bind = gimple_seq_first_stmt (body);
  lowered_body = NULL;
  gimple_seq_add_stmt (&lowered_body, bind);
  i = gsi_start (lowered_body);
  lower_gimple_bind (&i, &data);

  i = gsi_last (lowered_body);

  /* If we had begin stmt markers from e.g. PCH, but this compilation
     doesn't want them, lower_stmt will have cleaned them up; we can
     now clear the flag that indicates we had them.  */
  if (!MAY_HAVE_DEBUG_MARKER_STMTS && cfun->debug_nonbind_markers)
    {
      /* This counter needs not be exact, but before lowering it will
	 most certainly be.  */
      gcc_assert (cfun->debug_marker_count == 0);
      cfun->debug_nonbind_markers = false;
    }

  /* If the function falls off the end, we need a null return statement.
     If we've already got one in the return_statements vector, we don't
     need to do anything special.  Otherwise build one by hand.  */
  bool may_fallthru = gimple_seq_may_fallthru (lowered_body);
  if (may_fallthru
      && (data.return_statements.is_empty ()
	  || (gimple_return_retval (data.return_statements.last().stmt)
	      != NULL)))
    {
      x = gimple_build_return (NULL);
      gimple_set_location (x, cfun->function_end_locus);
      gimple_set_block (x, DECL_INITIAL (current_function_decl));
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
      may_fallthru = false;
    }

  /* If we lowered any return statements, emit the representative
     at the end of the function.  */
  while (!data.return_statements.is_empty ())
    {
      return_statements_t t = data.return_statements.pop ();
      x = gimple_build_label (t.label);
      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
      gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING);
      if (may_fallthru)
	{
	  /* Remove the line number from the representative return statement.
	     It now fills in for the fallthru too.  Failure to remove this
	     will result in incorrect results for coverage analysis.  */
	  gimple_set_location (t.stmt, UNKNOWN_LOCATION);
	  may_fallthru = false;
	}
    }

  /* Once the old body has been lowered, replace it with the new
     lowered sequence.  */
  gimple_set_body (current_function_decl, lowered_body);

  gcc_assert (data.block == DECL_INITIAL (current_function_decl));
  BLOCK_SUBBLOCKS (data.block)
    = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));

  clear_block_marks (data.block);
  data.return_statements.release ();
  return 0;
}