aboutsummaryrefslogtreecommitdiff
path: root/libiberty/pexecute.txh
blob: c3e40385631918d08fb9054d246e4b87c8b1d68a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
@c -*- mode: texinfo -*-
@deftypefn Extension {struct pex_obj *} pex_init (int @var{flags}, @
  const char *@var{pname}, const char *@var{tempbase})

Prepare to execute one or more programs, with standard output of each
program fed to standard input of the next.  This is a system
independent interface to execute a pipeline.

@var{flags} is a bitwise combination of the following:

@table @code

@vindex PEX_RECORD_TIMES
@item PEX_RECORD_TIMES
Record subprocess times if possible.

@vindex PEX_USE_PIPES
@item PEX_USE_PIPES
Use pipes for communication between processes, if possible.

@vindex PEX_SAVE_TEMPS
@item PEX_SAVE_TEMPS
Don't delete temporary files used for communication between
processes.

@end table

@var{pname} is the name of program to be executed, used in error
messages.  @var{tempbase} is a base name to use for any required
temporary files; it may be @code{NULL} to use a randomly chosen name.

@end deftypefn

@deftypefn Extension {const char *} pex_run (struct pex_obj *@var{obj}, @
  int @var{flags}, const char *@var{executable}, char * const *@var{argv}, @
  const char *@var{outname}, const char *@var{errname}, int *@var{err})

Execute one program in a pipeline.  On success this returns
@code{NULL}.  On failure it returns an error message, a statically
allocated string.

@var{obj} is returned by a previous call to @code{pex_init}.

@var{flags} is a bitwise combination of the following:

@table @code

@vindex PEX_LAST
@item PEX_LAST
This must be set on the last program in the pipeline.  In particular,
it should be set when executing a single program.  The standard output
of the program will be sent to @var{outname}, or, if @var{outname} is
@code{NULL}, to the standard output of the calling program.  Do @emph{not}
set this bit if you want to call @code{pex_read_output}
(described below).  After a call to @code{pex_run} with this bit set,
@var{pex_run} may no longer be called with the same @var{obj}.

@vindex PEX_SEARCH
@item PEX_SEARCH
Search for the program using the user's executable search path.

@vindex PEX_SUFFIX
@item PEX_SUFFIX
@var{outname} is a suffix.  See the description of @var{outname},
below.

@vindex PEX_STDERR_TO_STDOUT
@item PEX_STDERR_TO_STDOUT
Send the program's standard error to standard output, if possible.

@vindex PEX_BINARY_INPUT
@vindex PEX_BINARY_OUTPUT
@vindex PEX_BINARY_ERROR
@item PEX_BINARY_INPUT
@itemx PEX_BINARY_OUTPUT
@itemx PEX_BINARY_ERROR
The standard input (output or error) of the program should be read (written) in
binary mode rather than text mode.  These flags are ignored on systems
which do not distinguish binary mode and text mode, such as Unix.  For
proper behavior these flags should match appropriately---a call to
@code{pex_run} using @code{PEX_BINARY_OUTPUT} should be followed by a
call using @code{PEX_BINARY_INPUT}.

@vindex PEX_STDERR_TO_PIPE
@item PEX_STDERR_TO_PIPE
Send the program's standard error to a pipe, if possible.  This flag
cannot be specified together with @code{PEX_STDERR_TO_STDOUT}.  This
flag can be specified only on the last program in pipeline.

@end table

@var{executable} is the program to execute.  @var{argv} is the set of
arguments to pass to the program; normally @code{@var{argv}[0]} will
be a copy of @var{executable}.

@var{outname} is used to set the name of the file to use for standard
output.  There are two cases in which no output file will be used:

@enumerate
@item
if @code{PEX_LAST} is not set in @var{flags}, and @code{PEX_USE_PIPES}
was set in the call to @code{pex_init}, and the system supports pipes

@item
if @code{PEX_LAST} is set in @var{flags}, and @var{outname} is
@code{NULL}
@end enumerate

@noindent
Otherwise the code will use a file to hold standard
output.  If @code{PEX_LAST} is not set, this file is considered to be
a temporary file, and it will be removed when no longer needed, unless
@code{PEX_SAVE_TEMPS} was set in the call to @code{pex_init}.

There are two cases to consider when setting the name of the file to
hold standard output.

@enumerate
@item
@code{PEX_SUFFIX} is set in @var{flags}.  In this case
@var{outname} may not be @code{NULL}.  If the @var{tempbase} parameter
to @code{pex_init} was not @code{NULL}, then the output file name is
the concatenation of @var{tempbase} and @var{outname}.  If
@var{tempbase} was @code{NULL}, then the output file name is a random
file name ending in @var{outname}.

@item
@code{PEX_SUFFIX} was not set in @var{flags}.  In this
case, if @var{outname} is not @code{NULL}, it is used as the output
file name.  If @var{outname} is @code{NULL}, and @var{tempbase} was
not NULL, the output file name is randomly chosen using
@var{tempbase}.  Otherwise the output file name is chosen completely
at random.
@end enumerate

@var{errname} is the file name to use for standard error output.  If
it is @code{NULL}, standard error is the same as the caller's.
Otherwise, standard error is written to the named file.

On an error return, the code sets @code{*@var{err}} to an @code{errno}
value, or to 0 if there is no relevant @code{errno}.

@end deftypefn

@deftypefn Extension {const char *} pex_run_in_environment (struct pex_obj *@var{obj}, @
  int @var{flags}, const char *@var{executable}, char * const *@var{argv}, @
  char * const *@var{env}, int @var{env_size}, const char *@var{outname}, @
  const char *@var{errname}, int *@var{err})

Execute one program in a pipeline, permitting the environment for the
program to be specified.  Behaviour and parameters not listed below are
as for @code{pex_run}.

@var{env} is the environment for the child process, specified as an array of
character pointers.  Each element of the array should point to a string of the
form @code{VAR=VALUE}, with the exception of the last element that must be
@code{NULL}.

@end deftypefn

@deftypefn Extension {FILE *} pex_input_file (struct pex_obj *@var{obj}, @
  int @var{flags}, const char *@var{in_name})

Return a stream for a temporary file to pass to the first program in
the pipeline as input.

The name of the input file is chosen according to the same rules
@code{pex_run} uses to choose output file names, based on
@var{in_name}, @var{obj} and the @code{PEX_SUFFIX} bit in @var{flags}.

Don't call @code{fclose} on the returned stream; the first call to
@code{pex_run} closes it automatically.

If @var{flags} includes @code{PEX_BINARY_OUTPUT}, open the stream in
binary mode; otherwise, open it in the default mode.  Including
@code{PEX_BINARY_OUTPUT} in @var{flags} has no effect on Unix.
@end deftypefn

@deftypefn Extension {FILE *} pex_input_pipe (struct pex_obj *@var{obj}, @
  int @var{binary})

Return a stream @var{fp} for a pipe connected to the standard input of
the first program in the pipeline; @var{fp} is opened for writing.
You must have passed @code{PEX_USE_PIPES} to the @code{pex_init} call
that returned @var{obj}.

You must close @var{fp} using @code{fclose} yourself when you have
finished writing data to the pipeline.

The file descriptor underlying @var{fp} is marked not to be inherited
by child processes.

On systems that do not support pipes, this function returns
@code{NULL}, and sets @code{errno} to @code{EINVAL}.  If you would
like to write code that is portable to all systems the @code{pex}
functions support, consider using @code{pex_input_file} instead.

There are two opportunities for deadlock using
@code{pex_input_pipe}:

@itemize @bullet
@item
Most systems' pipes can buffer only a fixed amount of data; a process
that writes to a full pipe blocks.  Thus, if you write to @file{fp}
before starting the first process, you run the risk of blocking when
there is no child process yet to read the data and allow you to
continue.  @code{pex_input_pipe} makes no promises about the
size of the pipe's buffer, so if you need to write any data at all
before starting the first process in the pipeline, consider using
@code{pex_input_file} instead.

@item
Using @code{pex_input_pipe} and @code{pex_read_output} together
may also cause deadlock.  If the output pipe fills up, so that each
program in the pipeline is waiting for the next to read more data, and
you fill the input pipe by writing more data to @var{fp}, then there
is no way to make progress: the only process that could read data from
the output pipe is you, but you are blocked on the input pipe.

@end itemize

@end deftypefn

@deftypefn Extension {FILE *} pex_read_output (struct pex_obj *@var{obj}, @
  int @var{binary})

Returns a @code{FILE} pointer which may be used to read the standard
output of the last program in the pipeline.  When this is used,
@code{PEX_LAST} should not be used in a call to @code{pex_run}.  After
this is called, @code{pex_run} may no longer be called with the same
@var{obj}.  @var{binary} should be non-zero if the file should be
opened in binary mode.  Don't call @code{fclose} on the returned file;
it will be closed by @code{pex_free}.

@end deftypefn

@deftypefn Extension {FILE *} pex_read_err (struct pex_obj *@var{obj}, @
  int @var{binary})

Returns a @code{FILE} pointer which may be used to read the standard
error of the last program in the pipeline.  When this is used,
@code{PEX_LAST} should not be used in a call to @code{pex_run}.  After
this is called, @code{pex_run} may no longer be called with the same
@var{obj}.  @var{binary} should be non-zero if the file should be
opened in binary mode.  Don't call @code{fclose} on the returned file;
it will be closed by @code{pex_free}.

@end deftypefn


@deftypefn Extension int pex_get_status (struct pex_obj *@var{obj}, @
  int @var{count}, int *@var{vector})

Returns the exit status of all programs run using @var{obj}.
@var{count} is the number of results expected.  The results will be
placed into @var{vector}.  The results are in the order of the calls
to @code{pex_run}.  Returns 0 on error, 1 on success.

@end deftypefn

@deftypefn Extension int pex_get_times (struct pex_obj *@var{obj}, @
  int @var{count}, struct pex_time *@var{vector})

Returns the process execution times of all programs run using
@var{obj}.  @var{count} is the number of results expected.  The
results will be placed into @var{vector}.  The results are in the
order of the calls to @code{pex_run}.  Returns 0 on error, 1 on
success.

@code{struct pex_time} has the following fields of the type
@code{unsigned long}: @code{user_seconds},
@code{user_microseconds}, @code{system_seconds},
@code{system_microseconds}.  On systems which do not support reporting
process times, all the fields will be set to @code{0}.

@end deftypefn

@deftypefn Extension void pex_free (struct pex_obj @var{obj})

Clean up and free all data associated with @var{obj}.  If you have not
yet called @code{pex_get_times} or @code{pex_get_status}, this will
try to kill the subprocesses.

@end deftypefn

@deftypefn Extension {const char *} pex_one (int @var{flags}, @
  const char *@var{executable}, char * const *@var{argv}, @
  const char *@var{pname}, const char *@var{outname}, const char *@var{errname}, @
  int *@var{status}, int *@var{err})

An interface to permit the easy execution of a
single program.  The return value and most of the parameters are as
for a call to @code{pex_run}.  @var{flags} is restricted to a
combination of @code{PEX_SEARCH}, @code{PEX_STDERR_TO_STDOUT}, and
@code{PEX_BINARY_OUTPUT}.  @var{outname} is interpreted as if
@code{PEX_LAST} were set.  On a successful return, @code{*@var{status}} will
be set to the exit status of the program.

@end deftypefn

@deftypefn Extension int pexecute (const char *@var{program}, @
  char * const *@var{argv}, const char *@var{this_pname}, @
  const char *@var{temp_base}, char **@var{errmsg_fmt}, @
  char **@var{errmsg_arg}, int @var{flags})

This is the old interface to execute one or more programs.  It is
still supported for compatibility purposes, but is no longer
documented.

@end deftypefn

@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})

Another part of the old execution interface.

@end deftypefn
href='#n1462'>1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
/* Operations with long integers.
   Copyright (C) 2006-2017 Free Software Foundation, Inc.

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"			/* For BITS_PER_UNIT and *_BIG_ENDIAN.  */
#include "tree.h"

static int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
				 unsigned HOST_WIDE_INT, HOST_WIDE_INT,
				 unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
				 bool);

#define add_double(l1,h1,l2,h2,lv,hv) \
  add_double_with_sign (l1, h1, l2, h2, lv, hv, false)

static int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
		       unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);

static int mul_double_wide_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
				      unsigned HOST_WIDE_INT, HOST_WIDE_INT,
				      unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
				      unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
				      bool);

#define mul_double(l1,h1,l2,h2,lv,hv) \
  mul_double_wide_with_sign (l1, h1, l2, h2, lv, hv, NULL, NULL, false)

static int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT,
				 HOST_WIDE_INT, unsigned HOST_WIDE_INT,
				 HOST_WIDE_INT, unsigned HOST_WIDE_INT *,
				 HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
				 HOST_WIDE_INT *);

/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
   overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
   and SUM1.  Then this yields nonzero if overflow occurred during the
   addition.

   Overflow occurs if A and B have the same sign, but A and SUM differ in
   sign.  Use `^' to test whether signs differ, and `< 0' to isolate the
   sign.  */
#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)

/* To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
   We do that by representing the two-word integer in 4 words, with only
   HOST_BITS_PER_WIDE_INT / 2 bits stored in each word, as a positive
   number.  The value of the word is LOWPART + HIGHPART * BASE.  */

#define LOWPART(x) \
  ((x) & ((HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
#define HIGHPART(x) \
  ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)
#define BASE (HOST_WIDE_INT_1U << HOST_BITS_PER_WIDE_INT / 2)

/* Unpack a two-word integer into 4 words.
   LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
   WORDS points to the array of HOST_WIDE_INTs.  */

static void
encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
{
  words[0] = LOWPART (low);
  words[1] = HIGHPART (low);
  words[2] = LOWPART (hi);
  words[3] = HIGHPART (hi);
}

/* Pack an array of 4 words into a two-word integer.
   WORDS points to the array of words.
   The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces.  */

static void
decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
	HOST_WIDE_INT *hi)
{
  *low = words[0] + words[1] * BASE;
  *hi = words[2] + words[3] * BASE;
}

/* Add two doubleword integers with doubleword result.
   Return nonzero if the operation overflows according to UNSIGNED_P.
   Each argument is given as two `HOST_WIDE_INT' pieces.
   One argument is L1 and H1; the other, L2 and H2.
   The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */

static int
add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
		      unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
		      unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
		      bool unsigned_p)
{
  unsigned HOST_WIDE_INT l;
  HOST_WIDE_INT h;

  l = l1 + l2;
  h = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) h1
		       + (unsigned HOST_WIDE_INT) h2
		       + (l < l1));

  *lv = l;
  *hv = h;

  if (unsigned_p)
    return ((unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1
	    || (h == h1
		&& l < l1));
  else
    return OVERFLOW_SUM_SIGN (h1, h2, h);
}

/* Negate a doubleword integer with doubleword result.
   Return nonzero if the operation overflows, assuming it's signed.
   The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
   The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */

static int
neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
	    unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
{
  if (l1 == 0)
    {
      *lv = 0;
      *hv = - (unsigned HOST_WIDE_INT) h1;
      return (*hv & h1) < 0;
    }
  else
    {
      *lv = -l1;
      *hv = ~h1;
      return 0;
    }
}

/* Multiply two doubleword integers with quadword result.
   Return nonzero if the operation overflows according to UNSIGNED_P.
   Each argument is given as two `HOST_WIDE_INT' pieces.
   One argument is L1 and H1; the other, L2 and H2.
   The value is stored as four `HOST_WIDE_INT' pieces in *LV and *HV,
   *LW and *HW.
   If lw is NULL then only the low part and no overflow is computed.  */

static int
mul_double_wide_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
			   unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
			   unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
			   unsigned HOST_WIDE_INT *lw, HOST_WIDE_INT *hw,
			   bool unsigned_p)
{
  HOST_WIDE_INT arg1[4];
  HOST_WIDE_INT arg2[4];
  HOST_WIDE_INT prod[4 * 2];
  unsigned HOST_WIDE_INT carry;
  int i, j, k;
  unsigned HOST_WIDE_INT neglow;
  HOST_WIDE_INT neghigh;

  encode (arg1, l1, h1);
  encode (arg2, l2, h2);

  memset (prod, 0, sizeof prod);

  for (i = 0; i < 4; i++)
    {
      carry = 0;
      for (j = 0; j < 4; j++)
	{
	  k = i + j;
	  /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000.  */
	  carry += (unsigned HOST_WIDE_INT) arg1[i] * arg2[j];
	  /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF.  */
	  carry += prod[k];
	  prod[k] = LOWPART (carry);
	  carry = HIGHPART (carry);
	}
      prod[i + 4] = carry;
    }

  decode (prod, lv, hv);

  /* We are not interested in the wide part nor in overflow.  */
  if (lw == NULL)
    return 0;

  decode (prod + 4, lw, hw);

  /* Unsigned overflow is immediate.  */
  if (unsigned_p)
    return (*lw | *hw) != 0;

  /* Check for signed overflow by calculating the signed representation of the
     top half of the result; it should agree with the low half's sign bit.  */
  if (h1 < 0)
    {
      neg_double (l2, h2, &neglow, &neghigh);
      add_double (neglow, neghigh, *lw, *hw, lw, hw);
    }
  if (h2 < 0)
    {
      neg_double (l1, h1, &neglow, &neghigh);
      add_double (neglow, neghigh, *lw, *hw, lw, hw);
    }
  return (*hv < 0 ? ~(*lw & *hw) : *lw | *hw) != 0;
}

/* Shift the doubleword integer in L1, H1 right by COUNT places
   keeping only PREC bits of result.  ARITH nonzero specifies
   arithmetic shifting; otherwise use logical shift.
   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */

static void
rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
	       unsigned HOST_WIDE_INT count, unsigned int prec,
	       unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
	       bool arith)
{
  unsigned HOST_WIDE_INT signmask;

  signmask = (arith
	      ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
	      : 0);

  if (count >= HOST_BITS_PER_DOUBLE_INT)
    {
      /* Shifting by the host word size is undefined according to the
	 ANSI standard, so we must handle this as a special case.  */
      *hv = 0;
      *lv = 0;
    }
  else if (count >= HOST_BITS_PER_WIDE_INT)
    {
      *hv = 0;
      *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
    }
  else
    {
      *hv = (unsigned HOST_WIDE_INT) h1 >> count;
      *lv = ((l1 >> count)
	     | ((unsigned HOST_WIDE_INT) h1
		<< (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
    }

  /* Zero / sign extend all bits that are beyond the precision.  */

  if (count >= prec)
    {
      *hv = signmask;
      *lv = signmask;
    }
  else if ((prec - count) >= HOST_BITS_PER_DOUBLE_INT)
    ;
  else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
    {
      *hv &= ~(HOST_WIDE_INT_M1U << (prec - count - HOST_BITS_PER_WIDE_INT));
      *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
    }
  else
    {
      *hv = signmask;
      *lv &= ~(HOST_WIDE_INT_M1U << (prec - count));
      *lv |= signmask << (prec - count);
    }
}

/* Shift the doubleword integer in L1, H1 left by COUNT places
   keeping only PREC bits of result.
   Shift right if COUNT is negative.
   ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */

static void
lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
	       unsigned HOST_WIDE_INT count, unsigned int prec,
	       unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
{
  unsigned HOST_WIDE_INT signmask;

  if (count >= HOST_BITS_PER_DOUBLE_INT)
    {
      /* Shifting by the host word size is undefined according to the
	 ANSI standard, so we must handle this as a special case.  */
      *hv = 0;
      *lv = 0;
    }
  else if (count >= HOST_BITS_PER_WIDE_INT)
    {
      *hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
      *lv = 0;
    }
  else
    {
      *hv = (((unsigned HOST_WIDE_INT) h1 << count)
	     | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
      *lv = l1 << count;
    }

  /* Sign extend all bits that are beyond the precision.  */

  signmask = -((prec > HOST_BITS_PER_WIDE_INT
		? ((unsigned HOST_WIDE_INT) *hv
		   >> (prec - HOST_BITS_PER_WIDE_INT - 1))
		: (*lv >> (prec - 1))) & 1);

  if (prec >= HOST_BITS_PER_DOUBLE_INT)
    ;
  else if (prec >= HOST_BITS_PER_WIDE_INT)
    {
      *hv &= ~(HOST_WIDE_INT_M1U << (prec - HOST_BITS_PER_WIDE_INT));
      *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
    }
  else
    {
      *hv = signmask;
      *lv &= ~(HOST_WIDE_INT_M1U << prec);
      *lv |= signmask << prec;
    }
}

/* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
   for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
   CODE is a tree code for a kind of division, one of
   TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
   or EXACT_DIV_EXPR
   It controls how the quotient is rounded to an integer.
   Return nonzero if the operation overflows.
   UNS nonzero says do unsigned division.  */

static int
div_and_round_double (unsigned code, int uns,
		      /* num == numerator == dividend */
		      unsigned HOST_WIDE_INT lnum_orig,
		      HOST_WIDE_INT hnum_orig,
		      /* den == denominator == divisor */
		      unsigned HOST_WIDE_INT lden_orig,
		      HOST_WIDE_INT hden_orig,
		      unsigned HOST_WIDE_INT *lquo,
		      HOST_WIDE_INT *hquo, unsigned HOST_WIDE_INT *lrem,
		      HOST_WIDE_INT *hrem)
{
  int quo_neg = 0;
  HOST_WIDE_INT num[4 + 1];	/* extra element for scaling.  */
  HOST_WIDE_INT den[4], quo[4];
  int i, j;
  unsigned HOST_WIDE_INT work;
  unsigned HOST_WIDE_INT carry = 0;
  unsigned HOST_WIDE_INT lnum = lnum_orig;
  HOST_WIDE_INT hnum = hnum_orig;
  unsigned HOST_WIDE_INT lden = lden_orig;
  HOST_WIDE_INT hden = hden_orig;
  int overflow = 0;

  if (hden == 0 && lden == 0)
    overflow = 1, lden = 1;

  /* Calculate quotient sign and convert operands to unsigned.  */
  if (!uns)
    {
      if (hnum < 0)
	{
	  quo_neg = ~ quo_neg;
	  /* (minimum integer) / (-1) is the only overflow case.  */
	  if (neg_double (lnum, hnum, &lnum, &hnum)
	      && ((HOST_WIDE_INT) lden & hden) == -1)
	    overflow = 1;
	}
      if (hden < 0)
	{
	  quo_neg = ~ quo_neg;
	  neg_double (lden, hden, &lden, &hden);
	}
    }

  if (hnum == 0 && hden == 0)
    {				/* single precision */
      *hquo = *hrem = 0;
      /* This unsigned division rounds toward zero.  */
      *lquo = lnum / lden;
      goto finish_up;
    }

  if (hnum == 0)
    {				/* trivial case: dividend < divisor */
      /* hden != 0 already checked.  */
      *hquo = *lquo = 0;
      *hrem = hnum;
      *lrem = lnum;
      goto finish_up;
    }

  memset (quo, 0, sizeof quo);

  memset (num, 0, sizeof num);	/* to zero 9th element */
  memset (den, 0, sizeof den);

  encode (num, lnum, hnum);
  encode (den, lden, hden);

  /* Special code for when the divisor < BASE.  */
  if (hden == 0 && lden < (unsigned HOST_WIDE_INT) BASE)
    {
      /* hnum != 0 already checked.  */
      for (i = 4 - 1; i >= 0; i--)
	{
	  work = num[i] + carry * BASE;
	  quo[i] = work / lden;
	  carry = work % lden;
	}
    }
  else
    {
      /* Full double precision division,
	 with thanks to Don Knuth's "Seminumerical Algorithms".  */
      int num_hi_sig, den_hi_sig;
      unsigned HOST_WIDE_INT quo_est, scale;

      /* Find the highest nonzero divisor digit.  */
      for (i = 4 - 1;; i--)
	if (den[i] != 0)
	  {
	    den_hi_sig = i;
	    break;
	  }

      /* Insure that the first digit of the divisor is at least BASE/2.
	 This is required by the quotient digit estimation algorithm.  */

      scale = BASE / (den[den_hi_sig] + 1);
      if (scale > 1)
	{		/* scale divisor and dividend */
	  carry = 0;
	  for (i = 0; i <= 4 - 1; i++)
	    {
	      work = (num[i] * scale) + carry;
	      num[i] = LOWPART (work);
	      carry = HIGHPART (work);
	    }

	  num[4] = carry;
	  carry = 0;
	  for (i = 0; i <= 4 - 1; i++)
	    {
	      work = (den[i] * scale) + carry;
	      den[i] = LOWPART (work);
	      carry = HIGHPART (work);
	      if (den[i] != 0) den_hi_sig = i;
	    }
	}

      num_hi_sig = 4;

      /* Main loop */
      for (i = num_hi_sig - den_hi_sig - 1; i >= 0; i--)
	{
	  /* Guess the next quotient digit, quo_est, by dividing the first
	     two remaining dividend digits by the high order quotient digit.
	     quo_est is never low and is at most 2 high.  */
	  unsigned HOST_WIDE_INT tmp;

	  num_hi_sig = i + den_hi_sig + 1;
	  work = num[num_hi_sig] * BASE + num[num_hi_sig - 1];
	  if (num[num_hi_sig] != den[den_hi_sig])
	    quo_est = work / den[den_hi_sig];
	  else
	    quo_est = BASE - 1;

	  /* Refine quo_est so it's usually correct, and at most one high.  */
	  tmp = work - quo_est * den[den_hi_sig];
	  if (tmp < BASE
	      && (den[den_hi_sig - 1] * quo_est
		  > (tmp * BASE + num[num_hi_sig - 2])))
	    quo_est--;

	  /* Try QUO_EST as the quotient digit, by multiplying the
	     divisor by QUO_EST and subtracting from the remaining dividend.
	     Keep in mind that QUO_EST is the I - 1st digit.  */

	  carry = 0;
	  for (j = 0; j <= den_hi_sig; j++)
	    {
	      work = quo_est * den[j] + carry;
	      carry = HIGHPART (work);
	      work = num[i + j] - LOWPART (work);
	      num[i + j] = LOWPART (work);
	      carry += HIGHPART (work) != 0;
	    }

	  /* If quo_est was high by one, then num[i] went negative and
	     we need to correct things.  */
	  if (num[num_hi_sig] < (HOST_WIDE_INT) carry)
	    {
	      quo_est--;
	      carry = 0;		/* add divisor back in */
	      for (j = 0; j <= den_hi_sig; j++)
		{
		  work = num[i + j] + den[j] + carry;
		  carry = HIGHPART (work);
		  num[i + j] = LOWPART (work);
		}

	      num [num_hi_sig] += carry;
	    }

	  /* Store the quotient digit.  */
	  quo[i] = quo_est;
	}
    }

  decode (quo, lquo, hquo);

 finish_up:
  /* If result is negative, make it so.  */
  if (quo_neg)
    neg_double (*lquo, *hquo, lquo, hquo);

  /* Compute trial remainder:  rem = num - (quo * den)  */
  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
  neg_double (*lrem, *hrem, lrem, hrem);
  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);

  switch (code)
    {
    case TRUNC_DIV_EXPR:
    case TRUNC_MOD_EXPR:	/* round toward zero */
    case EXACT_DIV_EXPR:	/* for this one, it shouldn't matter */
      return overflow;

    case FLOOR_DIV_EXPR:
    case FLOOR_MOD_EXPR:	/* round toward negative infinity */
      if (quo_neg && (*lrem != 0 || *hrem != 0))   /* ratio < 0 && rem != 0 */
	{
	  /* quo = quo - 1;  */
	  add_double (*lquo, *hquo, HOST_WIDE_INT_M1, HOST_WIDE_INT_M1,
		      lquo, hquo);
	}
      else
	return overflow;
      break;

    case CEIL_DIV_EXPR:
    case CEIL_MOD_EXPR:		/* round toward positive infinity */
      if (!quo_neg && (*lrem != 0 || *hrem != 0))  /* ratio > 0 && rem != 0 */
	{
	  add_double (*lquo, *hquo, HOST_WIDE_INT_1, HOST_WIDE_INT_0,
		      lquo, hquo);
	}
      else
	return overflow;
      break;

    case ROUND_DIV_EXPR:
    case ROUND_MOD_EXPR:	/* round to closest integer */
      {
	unsigned HOST_WIDE_INT labs_rem = *lrem;
	HOST_WIDE_INT habs_rem = *hrem;
	unsigned HOST_WIDE_INT labs_den = lden, lnegabs_rem, ldiff;
	HOST_WIDE_INT habs_den = hden, hnegabs_rem, hdiff;

	/* Get absolute values.  */
	if (!uns && *hrem < 0)
	  neg_double (*lrem, *hrem, &labs_rem, &habs_rem);
	if (!uns && hden < 0)
	  neg_double (lden, hden, &labs_den, &habs_den);

	/* If abs(rem) >= abs(den) - abs(rem), adjust the quotient.  */
	neg_double (labs_rem, habs_rem, &lnegabs_rem, &hnegabs_rem);
	add_double (labs_den, habs_den, lnegabs_rem, hnegabs_rem,
		    &ldiff, &hdiff);

	if (((unsigned HOST_WIDE_INT) habs_rem
	     > (unsigned HOST_WIDE_INT) hdiff)
	    || (habs_rem == hdiff && labs_rem >= ldiff))
	  {
	    if (quo_neg)
	      /* quo = quo - 1;  */
	      add_double (*lquo, *hquo,
			  HOST_WIDE_INT_M1, HOST_WIDE_INT_M1, lquo, hquo);
	    else
	      /* quo = quo + 1; */
	      add_double (*lquo, *hquo, HOST_WIDE_INT_1, HOST_WIDE_INT_0,
			  lquo, hquo);
	  }
	else
	  return overflow;
      }
      break;

    default:
      gcc_unreachable ();
    }

  /* Compute true remainder:  rem = num - (quo * den)  */
  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
  neg_double (*lrem, *hrem, lrem, hrem);
  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
  return overflow;
}


/* Construct from a buffer of length LEN.  BUFFER will be read according
   to byte endianness and word endianness.  Only the lower LEN bytes
   of the result are set; the remaining high bytes are cleared.  */

double_int
double_int::from_buffer (const unsigned char *buffer, int len)
{
  double_int result = double_int_zero;
  int words = len / UNITS_PER_WORD;

  gcc_assert (len * BITS_PER_UNIT <= HOST_BITS_PER_DOUBLE_INT);

  for (int byte = 0; byte < len; byte++)
    {
      int offset;
      int bitpos = byte * BITS_PER_UNIT;
      unsigned HOST_WIDE_INT value;

      if (len > UNITS_PER_WORD)
	{
	  int word = byte / UNITS_PER_WORD;

	  if (WORDS_BIG_ENDIAN)
	    word = (words - 1) - word;

	  offset = word * UNITS_PER_WORD;

	  if (BYTES_BIG_ENDIAN)
	    offset += (UNITS_PER_WORD - 1) - (byte % UNITS_PER_WORD);
	  else
	    offset += byte % UNITS_PER_WORD;
	}
      else
	offset = BYTES_BIG_ENDIAN ? (len - 1) - byte : byte;

      value = (unsigned HOST_WIDE_INT) buffer[offset];

      if (bitpos < HOST_BITS_PER_WIDE_INT)
	result.low |= value << bitpos;
      else
	result.high |= value << (bitpos - HOST_BITS_PER_WIDE_INT);
    }

  return result;
}


/* Returns mask for PREC bits.  */

double_int
double_int::mask (unsigned prec)
{
  unsigned HOST_WIDE_INT m;
  double_int mask;

  if (prec > HOST_BITS_PER_WIDE_INT)
    {
      prec -= HOST_BITS_PER_WIDE_INT;
      m = ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1;
      mask.high = (HOST_WIDE_INT) m;
      mask.low = ALL_ONES;
    }
  else
    {
      mask.high = 0;
      mask.low = prec ? ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1 : 0;
    }

  return mask;
}

/* Returns a maximum value for signed or unsigned integer
   of precision PREC.  */

double_int
double_int::max_value (unsigned int prec, bool uns)
{
  return double_int::mask (prec - (uns ? 0 : 1));
}

/* Returns a minimum value for signed or unsigned integer
   of precision PREC.  */

double_int
double_int::min_value (unsigned int prec, bool uns)
{
  if (uns)
    return double_int_zero;
  return double_int_one.lshift (prec - 1, prec, false);
}

/* Clears the bits of CST over the precision PREC.  If UNS is false, the bits
   outside of the precision are set to the sign bit (i.e., the PREC-th one),
   otherwise they are set to zero.

   This corresponds to returning the value represented by PREC lowermost bits
   of CST, with the given signedness.  */

double_int
double_int::ext (unsigned prec, bool uns) const
{
  if (uns)
    return this->zext (prec);
  else
    return this->sext (prec);
}

/* The same as double_int::ext with UNS = true.  */

double_int
double_int::zext (unsigned prec) const
{
  const double_int &cst = *this;
  double_int mask = double_int::mask (prec);
  double_int r;

  r.low = cst.low & mask.low;
  r.high = cst.high & mask.high;

  return r;
}

/* The same as double_int::ext with UNS = false.  */

double_int
double_int::sext (unsigned prec) const
{
  const double_int &cst = *this;
  double_int mask = double_int::mask (prec);
  double_int r;
  unsigned HOST_WIDE_INT snum;

  if (prec <= HOST_BITS_PER_WIDE_INT)
    snum = cst.low;
  else
    {
      prec -= HOST_BITS_PER_WIDE_INT;
      snum = (unsigned HOST_WIDE_INT) cst.high;
    }
  if (((snum >> (prec - 1)) & 1) == 1)
    {
      r.low = cst.low | ~mask.low;
      r.high = cst.high | ~mask.high;
    }
  else
    {
      r.low = cst.low & mask.low;
      r.high = cst.high & mask.high;
    }

  return r;
}

/* Returns true if CST fits in signed HOST_WIDE_INT.  */

bool
double_int::fits_shwi () const
{
  const double_int &cst = *this;
  if (cst.high == 0)
    return (HOST_WIDE_INT) cst.low >= 0;
  else if (cst.high == -1)
    return (HOST_WIDE_INT) cst.low < 0;
  else
    return false;
}

/* Returns true if CST fits in HOST_WIDE_INT if UNS is false, or in
   unsigned HOST_WIDE_INT if UNS is true.  */

bool
double_int::fits_hwi (bool uns) const
{
  if (uns)
    return this->fits_uhwi ();
  else
    return this->fits_shwi ();
}

/* Returns A * B.  */

double_int
double_int::operator * (double_int b) const
{
  const double_int &a = *this;
  double_int ret;
  mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
  return ret;
}

/* Multiplies *this with B and returns a reference to *this.  */

double_int &
double_int::operator *= (double_int b)
{
  mul_double (low, high, b.low, b.high, &low, &high);
  return *this;
}

/* Returns A * B. If the operation overflows according to UNSIGNED_P,
   *OVERFLOW is set to nonzero.  */

double_int
double_int::mul_with_sign (double_int b, bool unsigned_p, bool *overflow) const
{
  const double_int &a = *this;
  double_int ret, tem;
  *overflow = mul_double_wide_with_sign (a.low, a.high, b.low, b.high,
					 &ret.low, &ret.high,
					 &tem.low, &tem.high, unsigned_p);
  return ret;
}

double_int
double_int::wide_mul_with_sign (double_int b, bool unsigned_p,
				double_int *higher, bool *overflow) const

{
  double_int lower;
  *overflow = mul_double_wide_with_sign (low, high, b.low, b.high,
					 &lower.low, &lower.high,
					 &higher->low, &higher->high,
					 unsigned_p);
  return lower;
}

/* Returns A + B.  */

double_int
double_int::operator + (double_int b) const
{
  const double_int &a = *this;
  double_int ret;
  add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
  return ret;
}

/* Adds B to *this and returns a reference to *this.  */

double_int &
double_int::operator += (double_int b)
{
  add_double (low, high, b.low, b.high, &low, &high);
  return *this;
}


/* Returns A + B. If the operation overflows according to UNSIGNED_P,
   *OVERFLOW is set to nonzero.  */

double_int
double_int::add_with_sign (double_int b, bool unsigned_p, bool *overflow) const
{
  const double_int &a = *this;
  double_int ret;
  *overflow = add_double_with_sign (a.low, a.high, b.low, b.high,
                                    &ret.low, &ret.high, unsigned_p);
  return ret;
}

/* Returns A - B.  */

double_int
double_int::operator - (double_int b) const
{
  const double_int &a = *this;
  double_int ret;
  neg_double (b.low, b.high, &b.low, &b.high);
  add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
  return ret;
}

/* Subtracts B from *this and returns a reference to *this.  */

double_int &
double_int::operator -= (double_int b)
{
  neg_double (b.low, b.high, &b.low, &b.high);
  add_double (low, high, b.low, b.high, &low, &high);
  return *this;
}


/* Returns A - B. If the operation overflows via inconsistent sign bits,
   *OVERFLOW is set to nonzero.  */

double_int
double_int::sub_with_overflow (double_int b, bool *overflow) const
{
  double_int ret;
  neg_double (b.low, b.high, &ret.low, &ret.high);
  add_double (low, high, ret.low, ret.high, &ret.low, &ret.high);
  *overflow = OVERFLOW_SUM_SIGN (ret.high, b.high, high);
  return ret;
}

/* Returns -A.  */

double_int
double_int::operator - () const
{
  const double_int &a = *this;
  double_int ret;
  neg_double (a.low, a.high, &ret.low, &ret.high);
  return ret;
}

double_int
double_int::neg_with_overflow (bool *overflow) const
{
  double_int ret;
  *overflow = neg_double (low, high, &ret.low, &ret.high);
  return ret;
}

/* Returns A / B (computed as unsigned depending on UNS, and rounded as
   specified by CODE).  CODE is enum tree_code in fact, but double_int.h
   must be included before tree.h.  The remainder after the division is
   stored to MOD.  */

double_int
double_int::divmod_with_overflow (double_int b, bool uns, unsigned code,
				  double_int *mod, bool *overflow) const
{
  const double_int &a = *this;
  double_int ret;

  *overflow = div_and_round_double (code, uns, a.low, a.high,
				    b.low, b.high, &ret.low, &ret.high,
				    &mod->low, &mod->high);
  return ret;
}

double_int
double_int::divmod (double_int b, bool uns, unsigned code,
		    double_int *mod) const
{
  const double_int &a = *this;
  double_int ret;

  div_and_round_double (code, uns, a.low, a.high,
			b.low, b.high, &ret.low, &ret.high,
			&mod->low, &mod->high);
  return ret;
}

/* The same as double_int::divmod with UNS = false.  */

double_int
double_int::sdivmod (double_int b, unsigned code, double_int *mod) const
{
  return this->divmod (b, false, code, mod);
}

/* The same as double_int::divmod with UNS = true.  */

double_int
double_int::udivmod (double_int b, unsigned code, double_int *mod) const
{
  return this->divmod (b, true, code, mod);
}

/* Returns A / B (computed as unsigned depending on UNS, and rounded as
   specified by CODE).  CODE is enum tree_code in fact, but double_int.h
   must be included before tree.h.  */

double_int
double_int::div (double_int b, bool uns, unsigned code) const
{
  double_int mod;

  return this->divmod (b, uns, code, &mod);
}

/* The same as double_int::div with UNS = false.  */

double_int
double_int::sdiv (double_int b, unsigned code) const
{
  return this->div (b, false, code);
}

/* The same as double_int::div with UNS = true.  */

double_int
double_int::udiv (double_int b, unsigned code) const
{
  return this->div (b, true, code);
}

/* Returns A % B (computed as unsigned depending on UNS, and rounded as
   specified by CODE).  CODE is enum tree_code in fact, but double_int.h
   must be included before tree.h.  */

double_int
double_int::mod (double_int b, bool uns, unsigned code) const
{
  double_int mod;

  this->divmod (b, uns, code, &mod);
  return mod;
}

/* The same as double_int::mod with UNS = false.  */

double_int
double_int::smod (double_int b, unsigned code) const
{
  return this->mod (b, false, code);
}

/* The same as double_int::mod with UNS = true.  */

double_int
double_int::umod (double_int b, unsigned code) const
{
  return this->mod (b, true, code);
}

/* Return TRUE iff PRODUCT is an integral multiple of FACTOR, and return
   the multiple in *MULTIPLE.  Otherwise return FALSE and leave *MULTIPLE
   unchanged.  */

bool
double_int::multiple_of (double_int factor,
			 bool unsigned_p, double_int *multiple) const
{
  double_int remainder;
  double_int quotient = this->divmod (factor, unsigned_p,
					   TRUNC_DIV_EXPR, &remainder);
  if (remainder.is_zero ())
    {
      *multiple = quotient;
      return true;
    }

  return false;
}

/* Set BITPOS bit in A.  */
double_int
double_int::set_bit (unsigned bitpos) const
{
  double_int a = *this;
  if (bitpos < HOST_BITS_PER_WIDE_INT)
    a.low |= HOST_WIDE_INT_1U << bitpos;
  else
    a.high |= HOST_WIDE_INT_1 <<  (bitpos - HOST_BITS_PER_WIDE_INT);
 
  return a;
}

/* Count trailing zeros in A.  */
int
double_int::trailing_zeros () const
{
  const double_int &a = *this;
  unsigned HOST_WIDE_INT w = a.low ? a.low : (unsigned HOST_WIDE_INT) a.high;
  unsigned bits = a.low ? 0 : HOST_BITS_PER_WIDE_INT;
  if (!w)
    return HOST_BITS_PER_DOUBLE_INT;
  bits += ctz_hwi (w);
  return bits;
}

/* Shift A left by COUNT places.  */

double_int
double_int::lshift (HOST_WIDE_INT count) const
{
  double_int ret;

  gcc_checking_assert (count >= 0);

  if (count >= HOST_BITS_PER_DOUBLE_INT)
    {
      /* Shifting by the host word size is undefined according to the
	 ANSI standard, so we must handle this as a special case.  */
      ret.high = 0;
      ret.low = 0;
    }
  else if (count >= HOST_BITS_PER_WIDE_INT)
    {
      ret.high = low << (count - HOST_BITS_PER_WIDE_INT);
      ret.low = 0;
    }
  else
    {
      ret.high = (((unsigned HOST_WIDE_INT) high << count)
	     | (low >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
      ret.low = low << count;
    }

  return ret;
}

/* Shift A right by COUNT places.  */

double_int
double_int::rshift (HOST_WIDE_INT count) const
{
  double_int ret;

  gcc_checking_assert (count >= 0);

  if (count >= HOST_BITS_PER_DOUBLE_INT)
    {
      /* Shifting by the host word size is undefined according to the
	 ANSI standard, so we must handle this as a special case.  */
      ret.high = 0;
      ret.low = 0;
    }
  else if (count >= HOST_BITS_PER_WIDE_INT)
    {
      ret.high = 0;
      ret.low
	= (unsigned HOST_WIDE_INT) (high >> (count - HOST_BITS_PER_WIDE_INT));
    }
  else
    {
      ret.high = high >> count;
      ret.low = ((low >> count)
		 | ((unsigned HOST_WIDE_INT) high
		    << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
    }

  return ret;
}

/* Shift A left by COUNT places keeping only PREC bits of result.  Shift
   right if COUNT is negative.  ARITH true specifies arithmetic shifting;
   otherwise use logical shift.  */

double_int
double_int::lshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const
{
  double_int ret;
  if (count > 0)
    lshift_double (low, high, count, prec, &ret.low, &ret.high);
  else
    rshift_double (low, high, absu_hwi (count), prec, &ret.low, &ret.high, arith);
  return ret;
}

/* Shift A right by COUNT places keeping only PREC bits of result.  Shift
   left if COUNT is negative.  ARITH true specifies arithmetic shifting;
   otherwise use logical shift.  */

double_int
double_int::rshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const
{
  double_int ret;
  if (count > 0)
    rshift_double (low, high, count, prec, &ret.low, &ret.high, arith);
  else
    lshift_double (low, high, absu_hwi (count), prec, &ret.low, &ret.high);
  return ret;
}

/* Arithmetic shift A left by COUNT places keeping only PREC bits of result.
   Shift right if COUNT is negative.  */

double_int
double_int::alshift (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int r;
  if (count > 0)
    lshift_double (low, high, count, prec, &r.low, &r.high);
  else
    rshift_double (low, high, absu_hwi (count), prec, &r.low, &r.high, true);
  return r;
}

/* Arithmetic shift A right by COUNT places keeping only PREC bits of result.
   Shift left if COUNT is negative.  */

double_int
double_int::arshift (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int r;
  if (count > 0)
    rshift_double (low, high, count, prec, &r.low, &r.high, true);
  else
    lshift_double (low, high, absu_hwi (count), prec, &r.low, &r.high);
  return r;
}

/* Logical shift A left by COUNT places keeping only PREC bits of result.
   Shift right if COUNT is negative.  */

double_int
double_int::llshift (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int r;
  if (count > 0)
    lshift_double (low, high, count, prec, &r.low, &r.high);
  else
    rshift_double (low, high, absu_hwi (count), prec, &r.low, &r.high, false);
  return r;
}

/* Logical shift A right by COUNT places keeping only PREC bits of result.
   Shift left if COUNT is negative.  */

double_int
double_int::lrshift (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int r;
  if (count > 0)
    rshift_double (low, high, count, prec, &r.low, &r.high, false);
  else
    lshift_double (low, high, absu_hwi (count), prec, &r.low, &r.high);
  return r;
}

/* Rotate  A left by COUNT places keeping only PREC bits of result.
   Rotate right if COUNT is negative.  */

double_int
double_int::lrotate (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int t1, t2;

  count %= prec;
  if (count < 0)
    count += prec;

  t1 = this->llshift (count, prec);
  t2 = this->lrshift (prec - count, prec);

  return t1 | t2;
}

/* Rotate A rigth by COUNT places keeping only PREC bits of result.
   Rotate right if COUNT is negative.  */

double_int
double_int::rrotate (HOST_WIDE_INT count, unsigned int prec) const
{
  double_int t1, t2;

  count %= prec;
  if (count < 0)
    count += prec;

  t1 = this->lrshift (count, prec);
  t2 = this->llshift (prec - count, prec);

  return t1 | t2;
}

/* Returns -1 if A < B, 0 if A == B and 1 if A > B.  Signedness of the
   comparison is given by UNS.  */

int
double_int::cmp (double_int b, bool uns) const
{
  if (uns)
    return this->ucmp (b);
  else
    return this->scmp (b);
}

/* Compares two unsigned values A and B.  Returns -1 if A < B, 0 if A == B,
   and 1 if A > B.  */

int
double_int::ucmp (double_int b) const
{
  const double_int &a = *this;
  if ((unsigned HOST_WIDE_INT) a.high < (unsigned HOST_WIDE_INT) b.high)
    return -1;
  if ((unsigned HOST_WIDE_INT) a.high > (unsigned HOST_WIDE_INT) b.high)
    return 1;
  if (a.low < b.low)
    return -1;
  if (a.low > b.low)
    return 1;

  return 0;
}

/* Compares two signed values A and B.  Returns -1 if A < B, 0 if A == B,
   and 1 if A > B.  */

int
double_int::scmp (double_int b) const
{
  const double_int &a = *this;
  if (a.high < b.high)
    return -1;
  if (a.high > b.high)
    return 1;
  if (a.low < b.low)
    return -1;
  if (a.low > b.low)
    return 1;

  return 0;
}

/* Compares two unsigned values A and B for less-than.  */

bool
double_int::ult (double_int b) const
{
  if ((unsigned HOST_WIDE_INT) high < (unsigned HOST_WIDE_INT) b.high)
    return true;
  if ((unsigned HOST_WIDE_INT) high > (unsigned HOST_WIDE_INT) b.high)
    return false;
  if (low < b.low)
    return true;
  return false;
}

/* Compares two unsigned values A and B for less-than or equal-to.  */

bool
double_int::ule (double_int b) const
{
  if ((unsigned HOST_WIDE_INT) high < (unsigned HOST_WIDE_INT) b.high)
    return true;
  if ((unsigned HOST_WIDE_INT) high > (unsigned HOST_WIDE_INT) b.high)
    return false;
  if (low <= b.low)
    return true;
  return false;
}

/* Compares two unsigned values A and B for greater-than.  */

bool
double_int::ugt (double_int b) const
{
  if ((unsigned HOST_WIDE_INT) high > (unsigned HOST_WIDE_INT) b.high)
    return true;
  if ((unsigned HOST_WIDE_INT) high < (unsigned HOST_WIDE_INT) b.high)
    return false;
  if (low > b.low)
    return true;
  return false;
}

/* Compares two signed values A and B for less-than.  */

bool
double_int::slt (double_int b) const
{
  if (high < b.high)
    return true;
  if (high > b.high)
    return false;
  if (low < b.low)
    return true;
  return false;
}

/* Compares two signed values A and B for less-than or equal-to.  */

bool
double_int::sle (double_int b) const
{
  if (high < b.high)
    return true;
  if (high > b.high)
    return false;
  if (low <= b.low)
    return true;
  return false;
}

/* Compares two signed values A and B for greater-than.  */

bool
double_int::sgt (double_int b) const
{
  if (high > b.high)
    return true;
  if (high < b.high)
    return false;
  if (low > b.low)
    return true;
  return false;
}


/* Compares two values A and B.  Returns max value.  Signedness of the
   comparison is given by UNS.  */

double_int
double_int::max (double_int b, bool uns)
{
  return (this->cmp (b, uns) == 1) ? *this : b;
}

/* Compares two signed values A and B.  Returns max value.  */

double_int
double_int::smax (double_int b)
{
  return (this->scmp (b) == 1) ? *this : b;
}

/* Compares two unsigned values A and B.  Returns max value.  */

double_int
double_int::umax (double_int b)
{
  return (this->ucmp (b) == 1) ? *this : b;
}

/* Compares two values A and B.  Returns mix value.  Signedness of the
   comparison is given by UNS.  */

double_int
double_int::min (double_int b, bool uns)
{
  return (this->cmp (b, uns) == -1) ? *this : b;
}

/* Compares two signed values A and B.  Returns min value.  */

double_int
double_int::smin (double_int b)
{
  return (this->scmp (b) == -1) ? *this : b;
}

/* Compares two unsigned values A and B.  Returns min value.  */

double_int
double_int::umin (double_int b)
{
  return (this->ucmp (b) == -1) ? *this : b;
}

/* Splits last digit of *CST (taken as unsigned) in BASE and returns it.  */

static unsigned
double_int_split_digit (double_int *cst, unsigned base)
{
  unsigned HOST_WIDE_INT resl, reml;
  HOST_WIDE_INT resh, remh;

  div_and_round_double (FLOOR_DIV_EXPR, true, cst->low, cst->high, base, 0,
			&resl, &resh, &reml, &remh);
  cst->high = resh;
  cst->low = resl;

  return reml;
}

/* Dumps CST to FILE.  If UNS is true, CST is considered to be unsigned,
   otherwise it is signed.  */

void
dump_double_int (FILE *file, double_int cst, bool uns)
{
  unsigned digits[100], n;
  int i;

  if (cst.is_zero ())
    {
      fprintf (file, "0");
      return;
    }

  if (!uns && cst.is_negative ())
    {
      fprintf (file, "-");
      cst = -cst;
    }

  for (n = 0; !cst.is_zero (); n++)
    digits[n] = double_int_split_digit (&cst, 10);
  for (i = n - 1; i >= 0; i--)
    fprintf (file, "%u", digits[i]);
}


/* Sets RESULT to VAL, taken unsigned if UNS is true and as signed
   otherwise.  */

void
mpz_set_double_int (mpz_t result, double_int val, bool uns)
{
  bool negate = false;