On Fri, 11 Jul 2014, Richard Biener wrote:
> On Fri, 11 Jul 2014, Jakub Jelinek wrote:
>
> > On Fri, Jul 11, 2014 at 10:00:01AM +0200, Richard Biener wrote:
> > > I started with adding an optional arg to native_encode_expr but then
> > > figured that all the current workers return failure if the entire
> > > expr doesn't fit within 'len'. But what I want is a native_encode_expr
> >
> > That is because the functions were written for VIEW_CONVERT_EXPR folding
> > where it is expected that both the types are the same size, and it doesn't
> > make sense to spend too much time on large stuff that doesn't fit into
> > the fold_view_convert_expr's fixed size buffer. Now, for your case
> > the sizes aren't the same and thus partial data is just fine, because
> > what native_interpret_expr will do is small fixed size.
> > So I don't see a problem with not returning NULL and instead handling the
> > partial store into buffer if you ask for it through optional argument
> > (doing it always would be fine for fold_view_convert_expr assuming nobody
> > feeds us different sized argument vs. VCE type, but e.g.
> > tree-loop-distribution.c certainly appreciates if we return NULL for large
> > things, because if it had just partial buffer, it would not be able to
> > verify what it is looking for).
>
> Yeah, if you pass 'offset' then 'len' suddenly changes semantics
> from specifying the buffer size to specifying the desired amount
> of encoded data ... (which the present interface computes for you,
> the caller doesn't even need to know how large it is).
>
> The question is also if I ask native_encode_expr to produce
> data for [offset, offset + len] but the object only contains
> part of it - thus the tail is 'undefined' - do we want to fail
> or simply feed (undefined) "garbage" to the following
> native_interpret_expr? (yes, native_encode_expr will of course
> return sth < len in this case)
Like the following (completely untested - lacks handling of
len < total_bytes - off as I just figured out). If off is -1
then it should behave as the current interface, else we encode
the part [off, off + MIN (len, total_bytes)] and return
MIN (len, total_bytes). Ah, a guard against off >= total_bytes
is also missing.
I wonder if it would be ok to start with gcc_assert (off == -1)
in all but native_encode_string.
Does the interface look sane?
Thanks,
Richard.
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 212449)
+++ gcc/fold-const.c (working copy)
@@ -7239,15 +7239,17 @@ fold_plusminus_mult_expr (location_t loc
upon failure. */
static int
-native_encode_int (const_tree expr, unsigned char *ptr, int len)
+native_encode_int (const_tree expr, unsigned char *ptr, int len, int off)
{
tree type = TREE_TYPE (expr);
int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
int byte, offset, word, words;
unsigned char value;
- if (total_bytes > len)
+ if (off == -1 && total_bytes > len)
return 0;
+ if (off == -1)
+ off = 0;
words = total_bytes / UNITS_PER_WORD;
for (byte = 0; byte < total_bytes; byte++)
@@ -7270,9 +7272,10 @@ native_encode_int (const_tree expr, unsi
}
else
offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte;
- ptr[offset] = value;
+ if (offset >= off)
+ ptr[offset - off] = value;
}
- return total_bytes;
+ return total_bytes - off;
}
@@ -7282,7 +7285,7 @@ native_encode_int (const_tree expr, unsi
upon failure. */
static int
-native_encode_fixed (const_tree expr, unsigned char *ptr, int len)
+native_encode_fixed (const_tree expr, unsigned char *ptr, int len, int off)
{
tree type = TREE_TYPE (expr);
enum machine_mode mode = TYPE_MODE (type);
@@ -7290,7 +7293,8 @@ native_encode_fixed (const_tree expr, un
FIXED_VALUE_TYPE value;
tree i_value, i_type;
- if (total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
+ if (off == -1
+ && total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
return 0;
i_type = lang_hooks.types.type_for_size (GET_MODE_BITSIZE (mode), 1);
@@ -7302,7 +7306,7 @@ native_encode_fixed (const_tree expr, un
value = TREE_FIXED_CST (expr);
i_value = double_int_to_tree (i_type, value.data);
- return native_encode_int (i_value, ptr, len);
+ return native_encode_int (i_value, ptr, len, off);
}
@@ -7312,7 +7316,7 @@ native_encode_fixed (const_tree expr, un
upon failure. */
static int
-native_encode_real (const_tree expr, unsigned char *ptr, int len)
+native_encode_real (const_tree expr, unsigned char *ptr, int len, int off)
{
tree type = TREE_TYPE (expr);
int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
@@ -7324,8 +7328,11 @@ native_encode_real (const_tree expr, uns
up to 192 bits. */
long tmp[6];
- if (total_bytes > len)
+ if (off == -1
+ && total_bytes > len)
return 0;
+ if (off == -1)
+ off = 0;
words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
real_to_target (tmp, TREE_REAL_CST_PTR (expr), TYPE_MODE (type));
@@ -7349,9 +7356,11 @@ native_encode_real (const_tree expr, uns
}
else
offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
- ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)] = value;
+ offset = offset + ((bitpos / BITS_PER_UNIT) & ~3);
+ if (offset >= off)
+ ptr[offset - off] = value;
}
- return total_bytes;
+ return total_bytes - off;
}
/* Subroutine of native_encode_expr. Encode the COMPLEX_CST
@@ -7360,18 +7369,21 @@ native_encode_real (const_tree expr, uns
upon failure. */
static int
-native_encode_complex (const_tree expr, unsigned char *ptr, int len)
+native_encode_complex (const_tree expr, unsigned char *ptr, int len, int off)
{
int rsize, isize;
tree part;
part = TREE_REALPART (expr);
- rsize = native_encode_expr (part, ptr, len);
+ rsize = native_encode_expr (part, ptr, len, off);
if (rsize == 0)
return 0;
part = TREE_IMAGPART (expr);
- isize = native_encode_expr (part, ptr+rsize, len-rsize);
- if (isize != rsize)
+ if (off != -1)
+ off = MAX (0, off - rsize);
+ isize = native_encode_expr (part, ptr+rsize, len-rsize, off);
+ if (off == -1
+ && isize != rsize)
return 0;
return rsize + isize;
}
@@ -7383,7 +7395,7 @@ native_encode_complex (const_tree expr,
upon failure. */
static int
-native_encode_vector (const_tree expr, unsigned char *ptr, int len)
+native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off)
{
unsigned i, count;
int size, offset;
@@ -7396,9 +7408,13 @@ native_encode_vector (const_tree expr, u
for (i = 0; i < count; i++)
{
elem = VECTOR_CST_ELT (expr, i);
- if (native_encode_expr (elem, ptr+offset, len-offset) != size)
+ int res = native_encode_expr (elem, ptr+offset, len-offset, off);
+ if (off == -1
+ && res != size)
return 0;
- offset += size;
+ offset += res;
+ if (off != -1)
+ off = MAX (0, off - res);
}
return offset;
}
@@ -7410,7 +7426,7 @@ native_encode_vector (const_tree expr, u
upon failure. */
static int
-native_encode_string (const_tree expr, unsigned char *ptr, int len)
+native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
{
tree type = TREE_TYPE (expr);
HOST_WIDE_INT total_bytes;
@@ -7421,17 +7437,21 @@ native_encode_string (const_tree expr, u
|| !tree_fits_shwi_p (TYPE_SIZE_UNIT (type)))
return 0;
total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (type));
- if (total_bytes > len)
+ if (off == -1 && total_bytes > len)
return 0;
+ if (off == -1)
+ off = 0;
if (TREE_STRING_LENGTH (expr) < total_bytes)
{
- memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr));
- memset (ptr + TREE_STRING_LENGTH (expr), 0,
- total_bytes - TREE_STRING_LENGTH (expr));
+ memcpy (ptr, TREE_STRING_POINTER (expr) + off,
+ TREE_STRING_LENGTH (expr) - off);
+ memset (ptr + TREE_STRING_LENGTH (expr) - off, 0,
+ MIN (total_bytes, len) - TREE_STRING_LENGTH (expr) + off);
}
else
- memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes);
- return total_bytes;
+ memcpy (ptr, TREE_STRING_POINTER (expr) + off,
+ MIN (total_bytes, len));
+ return MIN (total_bytes - off, len);
}
@@ -7441,27 +7461,27 @@ native_encode_string (const_tree expr, u
placed in the buffer, or zero upon failure. */
int
-native_encode_expr (const_tree expr, unsigned char *ptr, int len)
+native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off)
{
switch (TREE_CODE (expr))
{
case INTEGER_CST:
- return native_encode_int (expr, ptr, len);
+ return native_encode_int (expr, ptr, len, off);
case REAL_CST:
- return native_encode_real (expr, ptr, len);
+ return native_encode_real (expr, ptr, len, off);
case FIXED_CST:
- return native_encode_fixed (expr, ptr, len);
+ return native_encode_fixed (expr, ptr, len, off);
case COMPLEX_CST:
- return native_encode_complex (expr, ptr, len);
+ return native_encode_complex (expr, ptr, len, off);
case VECTOR_CST:
- return native_encode_vector (expr, ptr, len);
+ return native_encode_vector (expr, ptr, len, off);
case STRING_CST:
- return native_encode_string (expr, ptr, len);
+ return native_encode_string (expr, ptr, len, off);
default:
return 0;
Index: gcc/fold-const.h
===================================================================
--- gcc/fold-const.h (revision 212449)
+++ gcc/fold-const.h (working copy)
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3.
extern int folding_initializer;
/* Convert between trees and native memory representation. */
-extern int native_encode_expr (const_tree, unsigned char *, int);
+extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1);
extern tree native_interpret_expr (tree, const unsigned char *, int);
/* Fold constants as much as possible in an expression.