public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] c: Fix double evaluation of intcap expressions
@ 2022-06-01 13:16 Alex Coplan
0 siblings, 0 replies; only message in thread
From: Alex Coplan @ 2022-06-01 13:16 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:07cb14dd9017e450b3bf3459373405b494e1f05c
commit 07cb14dd9017e450b3bf3459373405b494e1f05c
Author: Alex Coplan <alex.coplan@arm.com>
Date: Wed May 25 18:57:53 2022 +0100
c: Fix double evaluation of intcap expressions
For an intcap c and address offset cv, the C FE would generate:
REPLACE_ADDRESS_VALUE (c, (long) c + cv)
but this is problematic if c cannot safely be evaluated twice (e.g.
for volatile variables, side-effecting function calls, etc.) as we end
up getting any side effects twice. This can be seen with the
intptr-eval.c test added with this patch, which was miscompiled on
purecap Morello.
To fix this, we need to use SAVE_EXPR on the intcap from which
provenance is carried when building the REPLACE_ADDRESS_VALUE in the FE,
so we get the tree:
REPLACE_ADDRESS_VALUE (SAVE_EXPR <c>, (long) SAVE_EXPR <c> + cv)
instead. This also means we need to make the provenance decision up
front, so we know which operand needs SAVE_EXPRs. We add a new helper
function, binary_op_get_intcap_provenance, to do this. We add this in
c-family/c-common.c in anticipation that the same code might be useful
in the C++ FE. Note that this change in how we make provenance decisions
renders c_build_replace_address_value_1 and its wrapper functions
redundant, so we remove these.
As well as binary operations, similar fixes are needed for
build_unary_op and its subroutine intcap_increment. In build_unary_op,
for TRUTH_NOT_EXPR, we allow the intcap to be handled directly by the
normal code (i.e. without dropping the capability): we don't want to
re-derive an intcap here, and intcaps can be handled just fine by
c_objc_common_truthvalue_conversion.
Adding these SAVE_EXPRs can prevent some folding of
REPLACE_ADDRESS_VALUE that we were getting before, thereby regressing
code quality. The SAVE_EXPRs have TREE_SIDE_EFFECTs set, so some folds
that were possible before are no longer possible. One such example is:
(long) RAV (c, cv) --> cv.
This transformation is only valid if c is free of side effects. In
particular, if c is a SAVE_EXPR, we can't do this transformation.
However, when this expression is gimplified, any SAVE_EXPRs will be
lowered. At this point we should be able to apply the transformation.
Hence, we add a match.pd rule for this that can be applied to the gimple
after the SAVE_EXPRs are lowered. This fixes a code quality regression
seen with nested binary ops such as:
__intcap f(__intcap x, long y) { return x + y + y; }
where (without the match.pd rule) we would end up generating two scvalue
instructions. Further issues with the folding have been identified as
part of this work, but are left to a follow-on patch to address.
One further adjustment we make is to save_expr, where we teach it to
push the save_expr inside REPLACE_ADDRESS_VALUE calls (down to the
operands). This allows the SAVE_EXPRs to be eliminated entirely in some
cases (e.g. when the operands are integer constants) and in general
improves our chances of being able to fold the resulting expressions.
gcc/c-family/ChangeLog:
* c-common.c (binary_op_get_intcap_provenance): New.
(unary_op_get_intcap_provenance): New.
* c-common.h (binary_op_get_intcap_provenance): New.
(unary_op_get_intcap_provenance): New.
gcc/c/ChangeLog:
* c-typeck.c (c_build_replace_address_value_1): Delete.
(c_build_replace_address_value): Delete.
(c_fold_build_replace_address_value): Delete.
(intcap_increment): Avoid evaluating any intcap side-effects
twice.
(build_unary_op): Likewise.
(build_binary_op_1): Likewise.
gcc/ChangeLog:
* match.pd (non-cap) RAV (c, cv) -> (non-cap) cv): New.
* tree.c (save_expr): Push save_expr inside
REPLACE_ADDRESS_VALUE operands.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/morello/intcap-semantics.c: Add SAVE_EXPRs
to some cases, following FE adjustments.
* gcc.c-torture/execute/intptr-eval.c: New test.
Diff:
---
gcc/c-family/c-common.c | 105 +++++++++++++++
gcc/c-family/c-common.h | 4 +
gcc/c/c-typeck.c | 142 +++++++--------------
gcc/match.pd | 12 ++
gcc/testsuite/gcc.c-torture/execute/intptr-eval.c | 35 +++++
.../gcc.target/aarch64/morello/intcap-semantics.c | 32 ++---
gcc/varasm.c | 10 +-
7 files changed, 226 insertions(+), 114 deletions(-)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 2175d8cf69f..5390d5779aa 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5183,6 +5183,111 @@ finish_label_address_expr (tree label, location_t loc)
}
\f
+/* Given operands OP0 and OP1 for a binary operation given by CODE,
+ return an operand of INTCAP_TYPE (if any) from which provenance
+ should be derived for the binary expression.
+
+ WARN_P should be set if we should warn when the provenance
+ is ambiguous. LOC is the location that will be used for the warning. */
+tree
+binary_op_get_intcap_provenance (location_t loc,
+ enum tree_code code,
+ tree op0, tree op1,
+ bool warn_p)
+{
+ tree type0 = TREE_TYPE (op0);
+ tree type1 = TREE_TYPE (op1);
+ bool ic0 = INTCAP_TYPE_P (type0);
+ bool ic1 = INTCAP_TYPE_P (type1);
+
+ if (!ic0 && !ic1)
+ return NULL_TREE;
+
+ /* Comparisons don't return capabilities. */
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ return NULL_TREE;
+
+ bool shift = false;
+
+ switch (code)
+ {
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ return NULL_TREE;
+ case RSHIFT_EXPR:
+ case LSHIFT_EXPR:
+ shift = true;
+ break;
+ default:
+ break;
+ }
+
+ bool need_ic0 = ic0 && (ic1 || INTEGRAL_TYPE_P (type1));
+ bool need_ic1 = ic1 && !shift && (ic0 || INTEGRAL_TYPE_P (type0));
+
+ if (!need_ic0 && !need_ic1)
+ return NULL_TREE;
+
+ static const char *cnp = "cheri_no_provenance";
+ bool prov0 = need_ic0 && !lookup_attribute (cnp, TYPE_ATTRIBUTES (type0));
+ bool prov1 = need_ic1 && !lookup_attribute (cnp, TYPE_ATTRIBUTES (type1));
+
+ if (prov0 && prov1 && warn_p)
+ {
+ warning_at (loc, OPT_Wcheri_provenance,
+ "binary expression on capability types %qT and %qT; "
+ "it is not clear which should be used as the source of provenance; "
+ "currently provenance is inherited from the left-hand side",
+ type0, type1);
+ }
+
+ if (prov0)
+ return op0;
+ if (prov1)
+ return op1;
+
+ /* MORELLO TODO: right now we don't propagate cheri_no_provenance
+ attributes, since this is what LLVM does, but it's actually
+ probably better to propagate these and avoid warning in cases where
+ the provenance is unambiguous (e.g. when all the operands of a
+ subexpression have cheri_no_provenance attributes). */
+ tree type;
+ if (need_ic0 && need_ic1)
+ type = common_type (type0, type1);
+ else
+ {
+ type = need_ic0 ? type0 : type1;
+ tree attrs = remove_attribute (cnp, TYPE_ATTRIBUTES (type));
+ type = build_type_attribute_variant (type, attrs);
+ }
+
+ return build_int_cst (type, 0);
+}
+
+tree
+unary_op_get_intcap_provenance (tree c)
+{
+ /* MORELLO TODO: right now we don't propagate cheri_no_provenance
+ attributes, since this is what LLVM does, but it's actually
+ probably better to propagate these and avoid warning in cases where
+ the provenance is unambiguous (e.g. when all the operands of a
+ subexpression have cheri_no_provenance attributes). */
+ tree type = TREE_TYPE (c);
+ tree attrs = TYPE_ATTRIBUTES (type);
+ static const char *cnp = "cheri_no_provenance";
+ if (lookup_attribute (cnp, attrs))
+ {
+ attrs = remove_attribute (cnp, attrs);
+ type = build_type_attribute_variant (type, attrs);
+ return build_int_cst (type, 0);
+ }
+
+ return c;
+}
+
/* Given a boolean expression ARG, return a tree representing an increment
or decrement (as indicated by CODE) of ARG. The front end must check for
invalid cases (e.g., decrement in C++). */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 88535e28feb..d7f74732e09 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1013,6 +1013,10 @@ extern tree common_type (tree, tree);
extern tree decl_constant_value (tree);
+extern tree binary_op_get_intcap_provenance (location_t,
+ enum tree_code, tree, tree, bool);
+extern tree unary_op_get_intcap_provenance (tree);
+
/* Handle increment and decrement of boolean types. */
extern tree boolean_increment (enum tree_code, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 04a0528d6e8..f572b0607be 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4353,52 +4353,28 @@ cas_loop:
return_old_p ? old : newval);
}
-static tree
-c_build_replace_address_value_1 (location_t loc, tree c, tree cv, bool fold)
-{
- tree type = TREE_TYPE (c);
- tree attrs = TYPE_ATTRIBUTES (type);
- static const char * const cnp = "cheri_no_provenance";
- if (lookup_attribute (cnp, attrs))
- {
- attrs = remove_attribute (cnp, attrs);
- type = build_type_attribute_variant (type, attrs);
- return c_common_cap_from_noncap (type, cv);
- }
-
- return fold
- ? fold_build_replace_address_value_loc (loc, c, cv)
- : build_replace_address_value_loc (loc, c, cv);
-}
-
-static tree
-c_build_replace_address_value (location_t loc, tree c, tree cv)
-{
- return c_build_replace_address_value_1 (loc, c, cv, false);
-}
-
-static tree
-c_fold_build_replace_address_value (location_t loc, tree c, tree cv)
-{
- return c_build_replace_address_value_1 (loc, c, cv, true);
-}
-
static tree
intcap_increment (location_t loc, tree_code code, tree arg)
{
- tree t, cv;
+ tree t, cv, intcap, lval;
- arg = stabilize_reference (arg);
+ arg = lval = stabilize_reference (arg);
+ intcap = unary_op_get_intcap_provenance (arg);
+ if (intcap == arg)
+ /* This save_expr is needed to avoid evaluating
+ the intcap twice when we compute the REPLACE_ADDRESS_VALUE. */
+ intcap = arg = save_expr (intcap);
cv = drop_capability (arg);
int dir = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) ? 1 : -1;
t = build_int_cst (TREE_TYPE (cv), dir);
t = build2 (PLUS_EXPR, TREE_TYPE (cv), cv, t);
- t = c_build_replace_address_value (loc, arg, t);
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), arg, t);
+ t = build_replace_address_value_loc (loc, intcap, t);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), lval, t);
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
{
+ /* This save_expr is needed to remember the original value. */
arg = save_expr (arg);
t = build2 (COMPOUND_EXPR, TREE_TYPE (t), t, arg);
t = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
@@ -4440,6 +4416,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
if (!ADDR_EXPR_CODE_P (code))
arg = require_complete_type (location, arg);
+ tree intcap = NULL_TREE;
if (TREE_CODE (TREE_TYPE (arg)) == INTCAP_TYPE)
{
switch (code)
@@ -4450,8 +4427,12 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ case TRUTH_NOT_EXPR:
break;
default:
+ intcap = unary_op_get_intcap_provenance (arg);
+ if (arg == intcap)
+ intcap = arg = save_expr (arg);
arg = drop_capability (arg);
}
}
@@ -4584,7 +4565,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
- && typecode != COMPLEX_TYPE)
+ && typecode != COMPLEX_TYPE && typecode != INTCAP_TYPE)
{
error_at (location,
"wrong type argument to unary exclamation mark");
@@ -4959,9 +4940,8 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
else
ret = build1 (code, argtype, arg);
- if (TREE_CODE (TREE_TYPE (xarg)) == INTCAP_TYPE
- && !capability_type_p (TREE_TYPE (ret)))
- ret = c_fold_build_replace_address_value (location, xarg, ret);
+ if (intcap)
+ ret = fold_build_replace_address_value_loc (location, intcap, ret);
return_build_unary_op:
gcc_assert (ret != error_mark_node);
@@ -12022,6 +12002,20 @@ build_binary_op_1 (location_t location, enum tree_code code,
orig_type0 = TREE_TYPE (op0);
orig_type1 = TREE_TYPE (op1);
+ tree intcap = binary_op_get_intcap_provenance (location, code, op0, op1,
+ !op0_provenance_p);
+
+ /* If we will derive an intcap from either the LHS or the RHS,
+ wrap it with save_expr. This will prevent us re-evaluating
+ any side effects of the intcap which will appear twice
+ in the resulting expression. E.g. for
+ c + cv --> REPLACE_ADDRESS_VALUE (c, (non-cap type) c + cv)
+ we need to avoid evaluating c twice. */
+ if (intcap == op0)
+ intcap = op0 = save_expr (op0);
+ else if (intcap == op1)
+ intcap = op1 = save_expr (op1);
+
if (TREE_CODE (orig_type0) == INTCAP_TYPE)
op0 = drop_capability (op0);
if (TREE_CODE (orig_type1) == INTCAP_TYPE)
@@ -13106,65 +13100,19 @@ build_binary_op_1 (location_t location, enum tree_code code,
/* For INTCAP_TYPEs, we dropped the capabilities early on and now need
- to work out where the provenance (if any) should come from. */
- if (!capability_type_p (TREE_TYPE (ret))
- && TREE_CODE_CLASS (code) != tcc_comparison
- && !boolean_op)
- {
- bool ic0 = TREE_CODE (orig_type0) == INTCAP_TYPE;
- bool ic1 = TREE_CODE (orig_type1) == INTCAP_TYPE;
-
- /* These flags are set if we need an intcap result type because of
- either the left or right operand respectively. */
- bool need_ic0 = ic0 && code1 == INTEGER_TYPE;
- bool need_ic1 = ic1 && !doing_shift && code0 == INTEGER_TYPE;
-
- static const char * const cnp = "cheri_no_provenance";
- bool prov0 = need_ic0
- && !lookup_attribute (cnp,
- TYPE_ATTRIBUTES (orig_type0));
- bool prov1 = need_ic1
- && !lookup_attribute (cnp,
- TYPE_ATTRIBUTES (orig_type1));
-
- tree intcap = NULL;
- if (prov0)
- intcap = orig_op0;
- else if (prov1)
- intcap = orig_op1;
- else if (need_ic0 || need_ic1)
- {
- tree type;
- if (need_ic0 && need_ic1)
- type = c_common_type (orig_type0, orig_type1);
- else
- {
- type = need_ic0 ? orig_type0 : orig_type1;
- tree attrs = remove_attribute (cnp, TYPE_ATTRIBUTES (type));
- type = build_type_attribute_variant (type, attrs);
- }
- intcap = build_int_cst (type, 0);
- }
-
- if (intcap)
- {
- tree ic_type = c_common_type (TREE_TYPE (intcap), TREE_TYPE (ret));
- gcc_assert (TREE_TYPE (ret) == noncapability_type (ic_type));
- intcap = convert (ic_type, intcap);
-
- /* We can't fold inside REPLACE_ADDRESS_VALUE calls, so ensure
- we've folded the operands. */
- ret = c_fully_fold (ret, false, NULL);
- intcap = c_fully_fold (intcap, false, NULL);
- ret = fold_build_replace_address_value_loc (location, intcap, ret);
- }
-
- if (prov0 && prov1 && !op0_provenance_p)
- warning_at (location, OPT_Wcheri_provenance,
- "binary expression on capability types %qT and %qT; "
- "it is not clear which should be used as the source of provenance; "
- "currently provenance is inherited from the left-hand side",
- orig_type0, orig_type1);
+ to derive the final intcap expression. */
+ if (intcap)
+ {
+ gcc_assert (!capability_type_p (TREE_TYPE (ret)));
+ tree ic_type = c_common_type (TREE_TYPE (intcap), TREE_TYPE (ret));
+ gcc_assert (TREE_TYPE (ret) == noncapability_type (ic_type));
+ intcap = convert (ic_type, intcap);
+
+ /* We can't fold inside REPLACE_ADDRESS_VALUE calls, so ensure
+ we've folded the operands. */
+ ret = c_fully_fold (ret, false, NULL);
+ intcap = c_fully_fold (intcap, false, NULL);
+ ret = fold_build_replace_address_value_loc (location, intcap, ret);
}
return_build_binary_op:
diff --git a/gcc/match.pd b/gcc/match.pd
index 200afaa0ef3..34eb9d2a92e 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6571,3 +6571,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
to the number of trailing zeroes. */
(match (ctz_table_index @1 @2 @3)
(rshift (mult (bit_and:c (negate @1) @1) INTEGER_CST@2) INTEGER_CST@3))
+
+#if GIMPLE
+
+/* (non-cap) RAV (c, cv) -> (non-cap) cv. */
+(simplify
+ (convert
+ (IFN_REPLACE_ADDRESS_VALUE @0 @1))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)))
+ (convert @1)))
+
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/intptr-eval.c b/gcc/testsuite/gcc.c-torture/execute/intptr-eval.c
new file mode 100644
index 00000000000..dd7a13ced83
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/intptr-eval.c
@@ -0,0 +1,35 @@
+/* This was being miscompiled on capability targets since we were
+ incorrectly evaluating intcap operands twice: once to get the
+ capability, and again to get the capability value. */
+
+int i;
+__INTPTR_TYPE__ f() { i++; return 1; }
+__INTPTR_TYPE__ bin() { return f() + 1; }
+__INTPTR_TYPE__ un() { return -f(); }
+
+__INTPTR_TYPE__ x;
+__INTPTR_TYPE__ *get_ptr() { i++; return &x; }
+__INTPTR_TYPE__ preinc() { return ++get_ptr()[0]; }
+__INTPTR_TYPE__ postinc() { return get_ptr()[0]++; }
+
+int main(void)
+{
+ if (bin() != 2)
+ __builtin_abort ();
+ if (i != 1)
+ __builtin_abort ();
+ if (un() != -1)
+ __builtin_abort ();
+ if (i != 2)
+ __builtin_abort ();
+ if (preinc() != 1)
+ __builtin_abort ();
+ if (i != 3)
+ __builtin_abort ();
+ if (postinc() != 1)
+ __builtin_abort ();
+ if (i != 4)
+ __builtin_abort ();
+ if (x != 2)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/intcap-semantics.c b/gcc/testsuite/gcc.target/aarch64/morello/intcap-semantics.c
index 6f83dd91383..4104ae16179 100644
--- a/gcc/testsuite/gcc.target/aarch64/morello/intcap-semantics.c
+++ b/gcc/testsuite/gcc.target/aarch64/morello/intcap-semantics.c
@@ -7,43 +7,43 @@ __intcap f1(__intcap x1, long y1)
{
return x1 + y1;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x1, \(long int\) x1 \+ y1\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x1>, \(long int\) SAVE_EXPR <x1> \+ y1\)} 1 "original" } } */
__intcap f2(__intcap x2, int y2)
{
return x2 + y2;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x2, \(long int\) x2 \+ \(long int\) y2\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x2>, \(long int\) SAVE_EXPR <x2> \+ \(long int\) y2\)} 1 "original" } } */
__intcap f3(__intcap x3, short y3)
{
return x3 + y3;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x3, \(long int\) x3 \+ \(long int\) y3\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x3>, \(long int\) SAVE_EXPR <x3> \+ \(long int\) y3\)} 1 "original" } } */
__intcap f4(__intcap x4, unsigned int y4)
{
return x4 + y4;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x4, \(long int\) x4 \+ \(long int\) y4\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x4>, \(long int\) SAVE_EXPR <x4> \+ \(long int\) y4\)} 1 "original" } } */
unsigned __intcap f5(__intcap x5, unsigned long y5)
{
return x5 + y5;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(\(unsigned __intcap\) x5, \(long unsigned int\) x5 \+ y5\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(\(unsigned __intcap\) SAVE_EXPR <x5>, \(long unsigned int\) SAVE_EXPR <x5> \+ y5\)} 1 "original" } } */
unsigned __intcap f6(unsigned __intcap x6, unsigned long y6)
{
return x6 + y6;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x6, \(long unsigned int\) x6 \+ y6\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x6>, \(long unsigned int\) SAVE_EXPR <x6> \+ y6\)} 1 "original" } } */
unsigned __intcap f7(unsigned __intcap x7, long y7)
{
return x7 + y7;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x7, \(long unsigned int\) x7 \+ \(long unsigned int\) y7\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x7>, \(long unsigned int\) SAVE_EXPR <x7> \+ \(long unsigned int\) y7\)} 1 "original" } } */
_Bool f8(__intcap x8, __intcap y8)
{
@@ -85,13 +85,13 @@ __intcap f14(__intcap x14)
{
return -x14;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x14, * -\(long int\) x14\);} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x14>, -\(long int\) SAVE_EXPR <x14>\);} 1 "original" } } */
__intcap f15(__intcap x15)
{
return ~x15;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x15, * ~\(long int\) x15\);} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x15>, ~\(long int\) SAVE_EXPR <x15>\);} 1 "original" } } */
_Bool f16(__intcap x16)
{
@@ -110,14 +110,14 @@ __intcap f18 (__intcap x18 __attribute__((cheri_no_provenance)), __intcap y18)
{
return x18 + y18;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(y18, \(long int\) x18 \+ \(long int\) y18\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <y18>, \(long int\) x18 \+ \(long int\) SAVE_EXPR <y18>\)} 1 "original" } } */
__intcap f19 (__intcap x19,
__intcap y19 __attribute__((cheri_no_provenance)))
{
return x19 + y19;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x19, \(long int\) x19 \+ \(long int\) y19\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x19>, \(long int\) SAVE_EXPR <x19> \+ \(long int\) y19\)} 1 "original" } } */
__intcap f20 (__intcap x20 __attribute__((cheri_no_provenance)),
__intcap y20 __attribute__((cheri_no_provenance)))
@@ -168,13 +168,13 @@ __intcap x26;
__intcap f26(void) {
return x26++;
}
-/* { dg-final { scan-tree-dump-times {return SAVE_EXPR <x26>;, x26 = \.REPLACE_ADDRESS_VALUE \(x26, \(long int\) x26 \+ 1\);, SAVE_EXPR <x26>;;} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return SAVE_EXPR <x26>;, x26 = \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x26>, \(long int\) SAVE_EXPR <x26> \+ 1\);, SAVE_EXPR <x26>;;} 1 "original" } } */
__intcap x27;
__intcap f27(void) {
return ++x27;
}
-/* { dg-final { scan-tree-dump-times {return x27 = \.REPLACE_ADDRESS_VALUE \(x27, \(long int\) x27 \+ 1\);} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return x27 = \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x27>, \(long int\) SAVE_EXPR <x27> \+ 1\);} 1 "original" } } */
__intcap x28 __attribute__((cheri_no_provenance));
__intcap f28(void) {
@@ -194,20 +194,20 @@ __intcap f30(__intcap x30,
{
return x30 + y30; /* { dg-warning "it is not clear which should be used as the source of provenance" } */
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x30, \(long int\) x30 \+ \(long int\) y30\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x30>, \(long int\) SAVE_EXPR <x30> \+ \(long int\) y30\)} 1 "original" } } */
__intcap x31, y31;
void f31(void)
{
x31 += y31;
}
-/* { dg-final { scan-tree-dump-times {x31 = \.REPLACE_ADDRESS_VALUE \(x31, \(long int\) x31 \+ \(long int\) y31\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {x31 = \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x31>, \(long int\) SAVE_EXPR <x31> \+ \(long int\) y31\)} 1 "original" } } */
__intcap f32 (__intcap x32, __intcap y32)
{
return x32 << y32;
}
-/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(x32, \(long int\) x32 << \(long int\) y32\)} 1 "original" } } */
+/* { dg-final { scan-tree-dump-times {return \.REPLACE_ADDRESS_VALUE \(SAVE_EXPR <x32>, \(long int\) SAVE_EXPR <x32> << \(long int\) y32\)} 1 "original" } } */
int f33 (__intcap x33, __intcap y33)
{
diff --git a/gcc/varasm.c b/gcc/varasm.c
index d680f01690d..a35048676d2 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4613,10 +4613,16 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
cleared metadata).
That should ensure we don't start handling capabilities with non-zero
- metadata without knowing why & where it comes from. */
+ metadata without knowing why & where it comes from.
+
+ Returns NULL_TREE if T cannot be a valid base capability for an
+ initializer constant. */
inline const_tree
tree_innermost_capability (const_tree t)
{
+ if (TREE_SIDE_EFFECTS (t))
+ return NULL_TREE;
+
switch (TREE_CODE (t))
{
case INTEGER_CST:
@@ -4666,6 +4672,8 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
break;
const_tree base_cap = tree_innermost_capability (ptr);
+ if (!base_cap)
+ break;
tree ptr_ret = initializer_constant_valid_p_1 (ptr, endtype, cache);
tree addrval_ret = initializer_constant_valid_p_1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-06-01 13:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-01 13:16 [gcc(refs/vendors/ARM/heads/morello)] c: Fix double evaluation of intcap expressions Alex Coplan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).