Skip to content
This repository has been archived by the owner on Jun 20, 2019. It is now read-only.

Add build_unary_op, use it instead of stabilize_expr for various unary ops #658

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions gcc/d/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2018-05-01 Iain Buclaw <ibuclaw@gdcproject.org>

* d-codegen.cc (build_unary_op): New function.
(build_nop): Use build_unary_op.
(build_address): Move expression handling to build_unary_op.

2018-04-02 Iain Buclaw <ibuclaw@gdcproject.org>

* d-lang.cc (doing_semantic_analysis_p): New variable.
Expand Down
168 changes: 123 additions & 45 deletions gcc/d/d-codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,100 @@ d_save_expr (tree exp)
return exp;
}

/* Adjust EXPR so that it is a valid lvalue, and can be evaluated multiple times
if it has any side effects. */

static tree
compound_lvalue (tree expr)
{
const tree_code code = TREE_CODE (expr);

if (code == MODIFY_EXPR || code == PREINCREMENT_EXPR
|| code == PREDECREMENT_EXPR)
{
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
expr = build2 (TREE_CODE (expr), TREE_TYPE (expr),
stabilize_reference (TREE_OPERAND (expr, 0)),
TREE_OPERAND (expr, 1));

return compound_expr (expr, TREE_OPERAND (expr, 0));
}

return expr;
}

/* Build an unary op CODE to the expression ARG. If the expression can be
broken down so that the operation is applied only to the part whose value we
care about, then handle lowering to keep lvalues trivial. */

static tree
build_unary_op (tree_code code, tree type, tree arg)
{
/* Given ((e1, ...), eN), treat the last RHS 'eN' expression as the
lvalue part. */
if (TREE_CODE (arg) == COMPOUND_EXPR)
{
tree result = build_unary_op (code, type, TREE_OPERAND (arg, 1));
return compound_expr (TREE_OPERAND (arg, 0), result);
}

arg = compound_lvalue (arg);

if (code == ADDR_EXPR)
{
/* Can't take the address of a manifest constant, get the real value of
the decl instead. */
if (TREE_CODE (arg) == CONST_DECL)
arg = DECL_INITIAL (arg);

/* Some expression lowering may request an address of a compile-time
constant. Make sure it is assigned to a location we can reference. */
if (CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != STRING_CST)
arg = force_target_expr (arg);

d_mark_addressable (arg);
tree result = build_fold_addr_expr_with_type_loc (input_location, arg,
type);
if (TREE_CODE (result) == ADDR_EXPR)
TREE_NO_TRAMPOLINE (result) = 1;

return result;
}

return fold_build1_loc (input_location, code, type, arg);
}

/* VALUEP is an expression we want to pre-evaluate or perform a computation on.
The expression returned by this function is the part whose value we don't
care about, storing the value in VALUEP. Callers must ensure that the
returned expression is evaluated before VALUEP. */

tree
stabilize_expr2 (tree *valuep)
{
tree expr = *valuep;

/* No side effects or expression has no value. */
if (!TREE_SIDE_EFFECTS (expr) || TREE_CODE (expr) == SAVE_EXPR
|| VOID_TYPE_P (TREE_TYPE (expr)))
return NULL_TREE;

/* Stabilize only the right hand side of compound expressions. */
if (TREE_CODE (expr) == COMPOUND_EXPR)
{
tree lhs = TREE_OPERAND (expr, 0);
tree rhs = TREE_OPERAND (expr, 1);
lhs = compound_expr (lhs, stabilize_expr2 (&rhs));
*valuep = rhs;
return lhs;
}

tree init = force_target_expr (expr);
*valuep = TARGET_EXPR_SLOT (init);

return init;
}

tree
stabilize_expr (tree *valuep)
{
Expand Down Expand Up @@ -606,25 +695,7 @@ build_address (tree exp)
else
ptrtype = build_pointer_type (type);

/* Maybe rewrite: &(e1, e2) => (e1, &e2). */
tree init = stabilize_expr (&exp);

/* Can't take the address of a manifest constant, instead use its value. */
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);

/* Some expression lowering may request an address of a compile-time constant.
Make sure it is assigned to a location we can reference. */
if (CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
exp = force_target_expr (exp);

d_mark_addressable (exp);
exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype);

if (TREE_CODE (exp) == ADDR_EXPR)
TREE_NO_TRAMPOLINE (exp) = 1;

return compound_expr (init, exp);
return build_unary_op (ADDR_EXPR, ptrtype, exp);
}

/* Mark EXP saying that we need to be able to take the
Expand Down Expand Up @@ -876,13 +947,10 @@ build_struct_comparison (tree_code code, StructDeclaration *sd,
return build_boolop (code, integer_zero_node, integer_zero_node);

/* Make temporaries to prevent multiple evaluations. */
tree t1init = stabilize_expr (&t1);
tree t2init = stabilize_expr (&t2);
tree t1init = stabilize_expr2 (&t1);
tree t2init = stabilize_expr2 (&t2);
tree result;

t1 = d_save_expr (t1);
t2 = d_save_expr (t2);

/* Bitwise comparison of structs not returned in memory may not work
due to data holes loosing its zero padding upon return.
As a heuristic, small structs are not compared using memcmp either. */
Expand Down Expand Up @@ -1172,6 +1240,7 @@ find_aggregate_field (tree type, tree ident, tree offset)

return NULL_TREE;
}

/* Return a constructor that matches the layout of the class expression EXP. */

tree
Expand Down Expand Up @@ -1283,10 +1352,13 @@ component_ref (tree object, tree field)
if (error_operand_p (object) || error_operand_p (field))
return error_mark_node;

gcc_assert (TREE_CODE (field) == FIELD_DECL);
if (TREE_CODE (object) == COMPOUND_EXPR)
{
tree result = component_ref (TREE_OPERAND (object, 1), field);
return compound_expr (TREE_OPERAND (object, 0), result);
}

/* Maybe rewrite: (e1, e2).field => (e1, e2.field) */
tree init = stabilize_expr (&object);
gcc_assert (TREE_CODE (field) == FIELD_DECL);

/* If the FIELD is from an anonymous aggregate, generate a reference
to the anonymous data member, and recur to find FIELD. */
Expand All @@ -1297,10 +1369,8 @@ component_ref (tree object, tree field)
object = component_ref (object, anonymous_field);
}

tree result = fold_build3_loc (input_location, COMPONENT_REF,
TREE_TYPE (field), object, field, NULL_TREE);

return compound_expr (init, result);
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
object, field, NULL_TREE);
}

/* Build an assignment expression of lvalue LHS from value RHS.
Expand All @@ -1310,8 +1380,14 @@ component_ref (tree object, tree field)
tree
build_assign (tree_code code, tree lhs, tree rhs)
{
tree init = stabilize_expr (&lhs);
init = compound_expr (init, stabilize_expr (&rhs));
/* Handle control structure constructs used as lvalues. */
if (TREE_CODE (lhs) == COMPOUND_EXPR)
{
tree result = build_assign (code, TREE_OPERAND (lhs, 1), rhs);
return compound_expr (TREE_OPERAND (lhs, 0), result);
}

lhs = compound_lvalue (lhs);

/* If initializing the LHS using a function that returns via NRVO. */
if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR
Expand Down Expand Up @@ -1339,9 +1415,7 @@ build_assign (tree_code code, tree lhs, tree rhs)
}
}

tree result = fold_build2_loc (input_location, code,
TREE_TYPE (lhs), lhs, rhs);
return compound_expr (init, result);
return fold_build2_loc (input_location, code, TREE_TYPE (lhs), lhs, rhs);
}

/* Build an assignment expression of lvalue LHS from value RHS. */
Expand All @@ -1360,11 +1434,7 @@ build_nop (tree type, tree exp)
if (error_operand_p (exp))
return exp;

/* Maybe rewrite: cast(TYPE)(e1, e2) => (e1, cast(TYPE) e2) */
tree init = stabilize_expr (&exp);
exp = fold_build1_loc (input_location, NOP_EXPR, type, exp);

return compound_expr (init, exp);
return build_unary_op (NOP_EXPR, type, exp);
}

/* Return EXP to be viewed as being another type TYPE. Same as build_nop,
Expand Down Expand Up @@ -1513,7 +1583,11 @@ indirect_ref (tree type, tree exp)
return exp;

/* Maybe rewrite: *(e1, e2) => (e1, *e2) */
tree init = stabilize_expr (&exp);
if (TREE_CODE (exp) == COMPOUND_EXPR)
{
tree result = indirect_ref (type, TREE_OPERAND (exp, 1));
return compound_expr (TREE_OPERAND (exp, 0), result);
}

if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE)
exp = fold_build1 (INDIRECT_REF, type, exp);
Expand All @@ -1523,7 +1597,7 @@ indirect_ref (tree type, tree exp)
exp = build_deref (exp);
}

return compound_expr (init, exp);
return exp;
}

/* Returns indirect reference of EXP, which must be a pointer type. */
Expand All @@ -1535,7 +1609,11 @@ build_deref (tree exp)
return exp;

/* Maybe rewrite: *(e1, e2) => (e1, *e2) */
tree init = stabilize_expr (&exp);
if (TREE_CODE (exp) == COMPOUND_EXPR)
{
tree result = build_deref (TREE_OPERAND (exp, 1));
return compound_expr (TREE_OPERAND (exp, 0), result);
}

gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));

Expand All @@ -1544,7 +1622,7 @@ build_deref (tree exp)
else
exp = build_fold_indirect_ref (exp);

return compound_expr (init, exp);
return exp;
}

/* Builds pointer offset expression PTR[INDEX]. */
Expand Down
1 change: 1 addition & 0 deletions gcc/d/d-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ extern void extract_from_method_call (tree, tree &, tree &);
extern tree build_vindex_ref (tree, tree, size_t);
extern tree d_save_expr (tree);
extern tree stabilize_expr (tree *);
extern tree stabilize_expr2 (tree *);
extern tree build_target_expr (tree, tree);
extern tree force_target_expr (tree);
extern tree build_address (tree);
Expand Down