Newer
Older
/* Tree lowering pass. This pass converts the GENERIC functions-as-trees
tree representation into the GIMPLE form.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
Andrew Pinski
committed
Free Software Foundation, Inc.
Major work done by Sebastian Pop <s.pop@laposte.net>,
Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "varray.h"
#include "gimple.h"
#include "tree-iterator.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "tree-flow.h"
#include "cgraph.h"
#include "timevar.h"
#include "except.h"
#include "hashtab.h"
#include "flags.h"
#include "real.h"
#include "function.h"
#include "output.h"
#include "expr.h"
#include "ggc.h"
Kaveh R. Ghazi
committed
#include "toplev.h"
#include "vec.h"
#include "gimple.h"
enum gimplify_omp_var_data
{
GOVD_SEEN = 1,
GOVD_EXPLICIT = 2,
GOVD_SHARED = 4,
GOVD_PRIVATE = 8,
GOVD_FIRSTPRIVATE = 16,
GOVD_LASTPRIVATE = 32,
GOVD_REDUCTION = 64,
GOVD_LOCAL = 128,
GOVD_DEBUG_PRIVATE = 256,
GOVD_PRIVATE_OUTER_REF = 512,
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LOCAL)
};
enum omp_region_type
{
ORT_WORKSHARE = 0,
ORT_TASK = 1,
ORT_PARALLEL = 2,
ORT_COMBINED_PARALLEL = 3
};
struct gimplify_omp_ctx *outer_context;
splay_tree variables;
struct pointer_set_t *privatized_types;
location_t location;
enum omp_clause_default_kind default_kind;
enum omp_region_type region_type;
};
static struct gimplify_ctx *gimplify_ctxp;
static struct gimplify_omp_ctx *gimplify_omp_ctxp;
/* Formal (expression) temporary table handling: Multiple occurrences of
the same scalar expression are evaluated into the same temporary. */
typedef struct gimple_temp_hash_elt
{
tree val; /* Key */
tree temp; /* Value */
} elt_t;
/* Forward declarations. */
static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
/* Mark X addressable. Unlike the langhook we expect X to be in gimple
form and we don't do any syntax checking. */
static void
mark_addressable (tree x)
{
while (handled_component_p (x))
x = TREE_OPERAND (x, 0);
if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL)
return ;
TREE_ADDRESSABLE (x) = 1;
}
/* Return a hash value for a formal temporary table entry. */
static hashval_t
gimple_tree_hash (const void *p)
{
return iterative_hash_expr (t, 0);
}
/* Compare two formal temporary table entries. */
static int
gimple_tree_eq (const void *p1, const void *p2)
{
tree t1 = ((const elt_t *) p1)->val;
tree t2 = ((const elt_t *) p2)->val;
enum tree_code code = TREE_CODE (t1);
if (TREE_CODE (t2) != code
|| TREE_TYPE (t1) != TREE_TYPE (t2))
return 0;
if (!operand_equal_p (t1, t2, 0))
return 0;
/* Only allow them to compare equal if they also hash equal; otherwise
results are nondeterminate, and we fail bootstrap comparison. */
gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* Link gimple statement GS to the end of the sequence *SEQ_P. If
*SEQ_P is NULL, a new sequence is allocated. This function is
similar to gimple_seq_add_stmt, but does not scan the operands.
During gimplification, we need to manipulate statement sequences
before the def/use vectors have been constructed. */
static void
gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
{
gimple_stmt_iterator si;
if (gs == NULL)
return;
if (*seq_p == NULL)
*seq_p = gimple_seq_alloc ();
si = gsi_last (*seq_p);
gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
}
/* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
NULL, a new sequence is allocated. This function is
similar to gimple_seq_add_seq, but does not scan the operands.
During gimplification, we need to manipulate statement sequences
before the def/use vectors have been constructed. */
static void
gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
{
gimple_stmt_iterator si;
if (src == NULL)
return;
if (*dst_p == NULL)
*dst_p = gimple_seq_alloc ();
si = gsi_last (*dst_p);
gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
}
/* Set up a context for the gimplifier. */
void
push_gimplify_context (struct gimplify_ctx *c)
memset (c, '\0', sizeof (*c));
c->prev_context = gimplify_ctxp;
gimplify_ctxp = c;
}
/* Tear down a context for the gimplifier. If BODY is non-null, then
put the temporaries into the outer BIND_EXPR. Otherwise, put them
in the local_decls.
BODY is not a sequence, but the first tuple in a sequence. */
pop_gimplify_context (gimple body)
gcc_assert (c && (c->bind_expr_stack == NULL
|| VEC_empty (gimple, c->bind_expr_stack)));
VEC_free (gimple, heap, c->bind_expr_stack);
DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
declare_vars (c->temps, body, false);
if (c->temp_htab)
gimple_push_bind_expr (gimple gimple_bind)
if (gimplify_ctxp->bind_expr_stack == NULL)
gimplify_ctxp->bind_expr_stack = VEC_alloc (gimple, heap, 8);
VEC_safe_push (gimple, heap, gimplify_ctxp->bind_expr_stack, gimple_bind);
gimple_pop_bind_expr (void)
{
VEC_pop (gimple, gimplify_ctxp->bind_expr_stack);
gimple
gimple_current_bind_expr (void)
{
return VEC_last (gimple, gimplify_ctxp->bind_expr_stack);
}
/* Return the stack GIMPLE_BINDs created during gimplification. */
VEC(gimple, heap) *
gimple_bind_expr_stack (void)
{
return gimplify_ctxp->bind_expr_stack;
}
/* Returns true iff there is a COND_EXPR between us and the innermost
CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
static bool
gimple_conditional_context (void)
{
return gimplify_ctxp->conditions > 0;
}
/* Note that we've entered a COND_EXPR. */
static void
gimple_push_condition (void)
{
#ifdef ENABLE_GIMPLE_CHECKING
Andrew Pinski
committed
if (gimplify_ctxp->conditions == 0)
gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
Andrew Pinski
committed
#endif
++(gimplify_ctxp->conditions);
}
/* Note that we've left a COND_EXPR. If we're back at unconditional scope
now, add any conditional cleanups we've seen to the prequeue. */
static void
gimple_pop_condition (gimple_seq *pre_p)
{
int conds = --(gimplify_ctxp->conditions);
gcc_assert (conds >= 0);
gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
gimplify_ctxp->conditional_cleanups = NULL;
/* A stable comparison routine for use with splay trees and DECLs. */
static int
splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
{
tree a = (tree) xa;
tree b = (tree) xb;
return DECL_UID (a) - DECL_UID (b);
}
/* Create a new omp construct that deals with variable remapping. */
static struct gimplify_omp_ctx *
new_omp_context (enum omp_region_type region_type)
{
struct gimplify_omp_ctx *c;
c = XCNEW (struct gimplify_omp_ctx);
c->outer_context = gimplify_omp_ctxp;
c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
c->privatized_types = pointer_set_create ();
c->location = input_location;
c->region_type = region_type;
if (region_type != ORT_TASK)
c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
else
c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
return c;
}
/* Destroy an omp construct that deals with variable remapping. */
static void
delete_omp_context (struct gimplify_omp_ctx *c)
{
splay_tree_delete (c->variables);
pointer_set_destroy (c->privatized_types);
XDELETE (c);
}
static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
/* A subroutine of append_to_statement_list{,_force}. T is not NULL. */
append_to_statement_list_1 (tree t, tree *list_p)
{
tree list = *list_p;
tree_stmt_iterator i;
if (!list)
{
if (t && TREE_CODE (t) == STATEMENT_LIST)
{
*list_p = t;
return;
}
*list_p = list = alloc_stmt_list ();
}
i = tsi_last (list);
tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
}
/* Add T to the end of the list container pointed to by LIST_P.
If T is an expression with no effects, it is ignored. */
void
append_to_statement_list (tree t, tree *list_p)
{
if (t && TREE_SIDE_EFFECTS (t))
append_to_statement_list_1 (t, list_p);
}
/* Similar, but the statement is always added, regardless of side effects. */
void
append_to_statement_list_force (tree t, tree *list_p)
{
if (t != NULL_TREE)
append_to_statement_list_1 (t, list_p);
/* Both gimplify the statement T and append it to *SEQ_P. This function
behaves exactly as gimplify_stmt, but you don't have to pass T as a
reference. */
gimplify_and_add (tree t, gimple_seq *seq_p)
{
gimplify_stmt (&t, seq_p);
}
/* Gimplify statement T into sequence *SEQ_P, and return the first
tuple in the sequence of generated tuples for this statement.
Return NULL if gimplifying T produced no tuples. */
static gimple
gimplify_and_return_first (tree t, gimple_seq *seq_p)
gimple_stmt_iterator last = gsi_last (*seq_p);
gimplify_and_add (t, seq_p);
if (!gsi_end_p (last))
{
gsi_next (&last);
return gsi_stmt (last);
}
else
return gimple_seq_first_stmt (*seq_p);
/* Strip off a legitimate source ending from the input string NAME of
length LEN. Rather than having to know the names used by all of
our front ends, we strip off an ending of a period followed by
up to five characters. (Java uses ".class".) */
static inline void
remove_suffix (char *name, int len)
{
int i;
for (i = 2; i < 8 && len > i; i++)
{
if (name[len - i] == '.')
{
name[len - i] = '\0';
break;
}
}
}
/* Subroutine for find_single_pointer_decl. */
static tree
find_single_pointer_decl_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data)
{
tree *pdecl = (tree *) data;
Ian Lance Taylor
committed
/* We are only looking for pointers at the same level as the
original tree; we must not look through any indirections.
Returning anything other than NULL_TREE will cause the caller to
not find a base. */
if (REFERENCE_CLASS_P (*tp))
return *tp;
if (DECL_P (*tp) && POINTER_TYPE_P (TREE_TYPE (*tp)))
{
if (*pdecl)
{
/* We already found a pointer decl; return anything other
than NULL_TREE to unwind from walk_tree signalling that
we have a duplicate. */
return *tp;
}
*pdecl = *tp;
}
return NULL_TREE;
}
Ian Lance Taylor
committed
/* Find the single DECL of pointer type in the tree T, used directly
rather than via an indirection, and return it. If there are zero
or more than one such DECLs, return NULL. */
static tree
find_single_pointer_decl (tree t)
{
tree decl = NULL_TREE;
if (walk_tree (&t, find_single_pointer_decl_1, &decl, NULL))
{
/* find_single_pointer_decl_1 returns a nonzero value, causing
walk_tree to return a nonzero value, to indicate that it
Ian Lance Taylor
committed
found more than one pointer DECL or that it found an
indirection. */
return NULL_TREE;
}
return decl;
}
/* Create a new temporary name with PREFIX. Returns an identifier. */
static GTY(()) unsigned int tmp_var_id_num;
Richard Henderson
committed
tree
create_tmp_var_name (const char *prefix)
{
char *tmp_name;
if (prefix)
{
char *preftmp = ASTRDUP (prefix);
remove_suffix (preftmp, strlen (preftmp));
prefix = preftmp;
}
ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "T", tmp_var_id_num++);
return get_identifier (tmp_name);
}
/* Create a new temporary variable declaration of type TYPE.
Does NOT push it into the current binding. */
tree
create_tmp_var_raw (tree type, const char *prefix)
{
tree tmp_var;
tree new_type;
/* Make the type of the variable writable. */
new_type = build_type_variant (type, 0, 0);
TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
Geoffrey Keating
committed
tmp_var = build_decl (VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
type);
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
/* The variable was declared by the compiler. */
DECL_ARTIFICIAL (tmp_var) = 1;
/* And we don't want debug info for it. */
DECL_IGNORED_P (tmp_var) = 1;
/* Make the variable writable. */
TREE_READONLY (tmp_var) = 0;
DECL_EXTERNAL (tmp_var) = 0;
TREE_STATIC (tmp_var) = 0;
TREE_USED (tmp_var) = 1;
return tmp_var;
}
/* Create a new temporary variable declaration of type TYPE. DOES push the
variable into the current binding. Further, assume that this is called
only from gimplification or optimization, at which point the creation of
certain types are bugs. */
tree
create_tmp_var (tree type, const char *prefix)
{
tree tmp_var;
/* We don't allow types that are addressable (meaning we can't make copies),
Olivier Hainque
committed
or incomplete. We also used to reject every variable size objects here,
but now support those for which a constant upper bound can be obtained.
The processing for variable sizes is performed in gimple_add_tmp_var,
point at which it really matters and possibly reached via paths not going
through this function, e.g. after direct calls to create_tmp_var_raw. */
gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
tmp_var = create_tmp_var_raw (type, prefix);
gimple_add_tmp_var (tmp_var);
return tmp_var;
}
/* Create a temporary with a name derived from VAL. Subroutine of
lookup_tmp_var; nobody else should call this function. */
static inline tree
create_tmp_from_val (tree val)
{
return create_tmp_var (TREE_TYPE (val), get_name (val));
}
/* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
an existing expression temporary. */
static tree
lookup_tmp_var (tree val, bool is_formal)
{
/* If not optimizing, never really reuse a temporary. local-alloc
won't allocate any variable that is used in more than one basic
block, which means it will go into memory, causing much extra
work in reload and final and poorer code generation, outweighing
the extra memory allocation here. */
if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
ret = create_tmp_from_val (val);
else
{
elt_t elt, *elt_p;
void **slot;
elt.val = val;
if (gimplify_ctxp->temp_htab == NULL)
gimplify_ctxp->temp_htab
= htab_create (1000, gimple_tree_hash, gimple_tree_eq, free);
slot = htab_find_slot (gimplify_ctxp->temp_htab, (void *)&elt, INSERT);
if (*slot == NULL)
{
elt_p->temp = ret = create_tmp_from_val (val);
*slot = (void *) elt_p;
{
elt_p = (elt_t *) *slot;
ret = elt_p->temp;
}
if (is_formal)
DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
return ret;
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
/* Return true if T is a CALL_EXPR or an expression that can be
assignmed to a temporary. Note that this predicate should only be
used during gimplification. See the rationale for this in
gimplify_modify_expr. */
static bool
is_gimple_formal_tmp_or_call_rhs (tree t)
{
return TREE_CODE (t) == CALL_EXPR || is_gimple_formal_tmp_rhs (t);
}
/* Returns true iff T is a valid RHS for an assignment to a renamed
user -- or front-end generated artificial -- variable. */
static bool
is_gimple_reg_or_call_rhs (tree t)
{
/* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
and the LHS is a user variable, then we need to introduce a formal
temporary. This way the optimizers can determine that the user
variable is only modified if evaluation of the RHS does not throw.
Don't force a temp of a non-renamable type; the copy could be
arbitrarily expensive. Instead we will generate a VDEF for
the assignment. */
if (is_gimple_reg_type (TREE_TYPE (t))
&& ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
|| tree_could_throw_p (t)))
return false;
return is_gimple_formal_tmp_or_call_rhs (t);
}
/* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
this predicate should only be used during gimplification. See the
rationale for this in gimplify_modify_expr. */
static bool
is_gimple_mem_or_call_rhs (tree t)
{
/* If we're dealing with a renamable type, either source or dest must be
a renamed variable. Also force a temporary if the type doesn't need
to be stored in memory, since it's cheap and prevents erroneous
tailcalls (PR 17526). */
if (is_gimple_reg_type (TREE_TYPE (t))
|| (TYPE_MODE (TREE_TYPE (t)) != BLKmode
&& (TREE_CODE (t) != CALL_EXPR
|| ! aggregate_value_p (t, t))))
return is_gimple_val (t);
else
return is_gimple_formal_tmp_or_call_rhs (t);
}
/* Returns a formal temporary variable initialized with VAL. PRE_P is as
in gimplify_expr. Only use this function if:
1) The value of the unfactored expression represented by VAL will not
change between the initialization and use of the temporary, and
2) The temporary will not be otherwise modified.
For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
and #2 means it is inappropriate for && temps.
For other cases, use get_initialized_tmp_var instead. */
static tree
internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
bool is_formal)
/* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_or_call_rhs,
fb_rvalue);
t = lookup_tmp_var (val, is_formal);
if (is_formal)
{
tree u = find_single_pointer_decl (val);
if (u && TREE_CODE (u) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (u))
u = DECL_GET_RESTRICT_BASE (u);
if (u && TYPE_RESTRICT (TREE_TYPE (u)))
{
if (DECL_BASED_ON_RESTRICT_P (t))
gcc_assert (u == DECL_GET_RESTRICT_BASE (t));
else
{
DECL_BASED_ON_RESTRICT_P (t) = 1;
SET_DECL_RESTRICT_BASE (t, u);
}
}
}
Andrew Pinski
committed
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (t) = 1;
Richard Henderson
committed
Jan Hubicka
committed
mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
if (EXPR_HAS_LOCATION (val))
SET_EXPR_LOCUS (mod, EXPR_LOCUS (val));
else
SET_EXPR_LOCATION (mod, input_location);
/* gimplify_modify_expr might want to reduce this further. */
gimplify_and_add (mod, pre_p);
ggc_free (mod);
/* If we're gimplifying into ssa, gimplify_modify_expr will have
given our temporary an SSA name. Find and return it. */
{
gimple last = gimple_seq_last_stmt (*pre_p);
t = gimple_get_lhs (last);
}
/* Returns a formal temporary variable initialized with VAL. PRE_P
points to a sequence where side-effects needed to compute VAL should be
stored. */
get_formal_tmp_var (tree val, gimple_seq *pre_p)
{
return internal_get_tmp_var (val, pre_p, NULL, true);
}
/* Returns a temporary variable initialized with VAL. PRE_P and POST_P
are as in gimplify_expr. */
tree
get_initialized_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p)
{
return internal_get_tmp_var (val, pre_p, post_p, false);
}
/* Declares all the variables in VARS in SCOPE. If DEBUG_INFO is
true, generate debug info for them; otherwise don't. */
declare_vars (tree vars, gimple scope, bool debug_info)
{
tree last = vars;
if (last)
{
tree temps, block;
gcc_assert (gimple_code (scope) == GIMPLE_BIND);
temps = nreverse (last);
Jakub Jelinek
committed
block = gimple_bind_block (scope);
gcc_assert (!block || TREE_CODE (block) == BLOCK);
if (!block || !debug_info)
{
TREE_CHAIN (last) = gimple_bind_vars (scope);
gimple_bind_set_vars (scope, temps);
}
else
{
/* We need to attach the nodes both to the BIND_EXPR and to its
associated BLOCK for debugging purposes. The key point here
is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
if (BLOCK_VARS (block))
BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
else
{
gimple_bind_set_vars (scope,
chainon (gimple_bind_vars (scope), temps));
BLOCK_VARS (block) = temps;
}
}
Olivier Hainque
committed
/* For VAR a VAR_DECL of variable size, try to find a constant upper bound
for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
no such upper bound can be obtained. */
static void
force_constant_size (tree var)
{
/* The only attempt we make is by querying the maximum size of objects
of the variable's type. */
HOST_WIDE_INT max_size;
gcc_assert (TREE_CODE (var) == VAR_DECL);
max_size = max_int_size_in_bytes (TREE_TYPE (var));
gcc_assert (max_size >= 0);
DECL_SIZE_UNIT (var)
= build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
DECL_SIZE (var)
= build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
}
void
gimple_add_tmp_var (tree tmp)
{
gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
Olivier Hainque
committed
/* Later processing assumes that the object size is constant, which might
not be true at this point. Force the use of a constant upper bound in
this case. */
if (!host_integerp (DECL_SIZE_UNIT (tmp), 1))
force_constant_size (tmp);
DECL_CONTEXT (tmp) = current_function_decl;
DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
if (gimplify_ctxp)
{
TREE_CHAIN (tmp) = gimplify_ctxp->temps;
gimplify_ctxp->temps = tmp;
/* Mark temporaries local within the nearest enclosing parallel. */
if (gimplify_omp_ctxp)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
while (ctx && ctx->region_type == ORT_WORKSHARE)
ctx = ctx->outer_context;
if (ctx)
omp_add_variable (ctx, tmp, GOVD_LOCAL | GOVD_SEEN);
}
}
else if (cfun)
record_vars (tmp);
else
{
gimple_seq body_seq;
/* This case is for nested functions. We need to expose the locals
they create. */
body_seq = gimple_body (current_function_decl);
declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
}
}
/* Determines whether to assign a location to the statement GS. */
static bool
should_carry_location_p (gimple gs)
{
/* Don't emit a line note for a label. We particularly don't want to
emit one for the break label, since it doesn't actually correspond
to the beginning of the loop/switch. */
if (gimple_code (gs) == GIMPLE_LABEL)
return false;
return true;
/* Same, but for a tree. */
tree_should_carry_location_p (const_tree stmt)
{
/* Don't emit a line note for a label. We particularly don't want to
emit one for the break label, since it doesn't actually correspond
to the beginning of the loop/switch. */
if (TREE_CODE (stmt) == LABEL_EXPR)
return false;
/* Do not annotate empty statements, since it confuses gcov. */
if (!TREE_SIDE_EFFECTS (stmt))
return false;
return true;
}
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
/* Return true if a location should not be emitted for this statement
by annotate_one_with_location. */
static inline bool
gimple_do_not_emit_location_p (gimple g)
{
return gimple_plf (g, GF_PLF_1);
}
/* Mark statement G so a location will not be emitted by
annotate_one_with_location. */
static inline void
gimple_set_do_not_emit_location (gimple g)
{
/* The PLF flags are initialized to 0 when a new tuple is created,
so no need to initialize it anywhere. */
gimple_set_plf (g, GF_PLF_1, true);
}
/* Set the location for gimple statement GS to LOCUS. */
static void
annotate_one_with_location (gimple gs, location_t location)
{
if (!gimple_has_location (gs)
&& !gimple_do_not_emit_location_p (gs)
&& should_carry_location_p (gs))
gimple_set_location (gs, location);
}
/* Same, but for tree T. */
tree_annotate_one_with_location (tree t, location_t location)
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
&& ! EXPR_HAS_LOCATION (t) && tree_should_carry_location_p (t))
SET_EXPR_LOCATION (t, location);
}
/* Set LOCATION for all the statements after iterator GSI in sequence
SEQ. If GSI is pointing to the end of the sequence, start with the
first statement in SEQ. */
static void
annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi,
location_t location)
{
if (gsi_end_p (gsi))
gsi = gsi_start (seq);
else
gsi_next (&gsi);
for (; !gsi_end_p (gsi); gsi_next (&gsi))
annotate_one_with_location (gsi_stmt (gsi), location);
}
/* Set the location for all the statements in a sequence STMT_P to LOCUS. */
void
annotate_all_with_location (gimple_seq stmt_p, location_t location)
{
gimple_stmt_iterator i;
if (gimple_seq_empty_p (stmt_p))
return;
for (i = gsi_start (stmt_p); !gsi_end_p (i); gsi_next (&i))
{
gimple gs = gsi_stmt (i);
annotate_one_with_location (gs, location);
}
/* Same, but for statement or statement list in *STMT_P. */
tree_annotate_all_with_location (tree *stmt_p, location_t location)
{
tree_stmt_iterator i;
if (!*stmt_p)
return;
for (i = tsi_start (*stmt_p); !tsi_end_p (i); tsi_next (&i))
{
tree t = tsi_stmt (i);
/* Assuming we've already been gimplified, we shouldn't
see nested chaining constructs anymore. */
gcc_assert (TREE_CODE (t) != STATEMENT_LIST
&& TREE_CODE (t) != COMPOUND_EXPR);
tree_annotate_one_with_location (t, location);
/* Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes.
These nodes model computations that should only be done once. If we