1989-02-07 11:04:05 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*/
|
1994-06-27 08:03:14 +00:00
|
|
|
/* $Id$ */
|
1989-02-07 11:04:05 +00:00
|
|
|
/* A R I T H M E T I C C O N V E R S I O N S */
|
|
|
|
|
|
|
|
/* This file contains the routines for the various conversions that
|
|
|
|
may befall operands in C. It is structurally a mess, but I haven't
|
|
|
|
decided yet whether I can't find the right structure or the
|
|
|
|
semantics of C is a mess.
|
|
|
|
*/
|
|
|
|
|
2017-11-10 03:22:13 +00:00
|
|
|
#include <assert.h>
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
#include <stddef.h>
|
2013-05-12 19:45:55 +00:00
|
|
|
#include "parameters.h"
|
1989-02-07 11:04:05 +00:00
|
|
|
#include <alloc.h>
|
1989-09-19 16:13:23 +00:00
|
|
|
#include <flt_arith.h>
|
1989-02-07 11:04:05 +00:00
|
|
|
#include "arith.h"
|
|
|
|
#include "sizes.h"
|
|
|
|
#include "type.h"
|
|
|
|
#include "proto.h"
|
|
|
|
#include "label.h"
|
|
|
|
#include "expr.h"
|
|
|
|
#include "Lpars.h"
|
|
|
|
#include "field.h"
|
|
|
|
#include "mes.h"
|
2019-02-18 16:42:15 +00:00
|
|
|
#include "cstoper.h"
|
|
|
|
#include "ch3bin.h"
|
|
|
|
#include "ch3.h"
|
|
|
|
#include "error.h"
|
|
|
|
|
1989-02-07 11:04:05 +00:00
|
|
|
|
|
|
|
extern char *symbol2str();
|
|
|
|
extern char options[];
|
1990-02-26 15:39:45 +00:00
|
|
|
extern arith flt_flt2arith();
|
1993-03-30 09:41:00 +00:00
|
|
|
extern label code_string();
|
1989-02-07 11:04:05 +00:00
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
/* 3.1.2.5 */
|
|
|
|
void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expressions *e1p and *e2p are balanced to be operands
|
|
|
|
of the arithmetic operator oper.
|
1990-04-25 15:09:51 +00:00
|
|
|
We check here if the EX_PTRDIFF flag should be retained.
|
|
|
|
They are set to zero in because one of the opreands might
|
|
|
|
have a floating type, in which case the flags shouldn't
|
|
|
|
travel upward in the expression tree.
|
1989-02-07 11:04:05 +00:00
|
|
|
*/
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
struct type *convert1, *convert2;
|
|
|
|
int t1, t2, u1, u2;
|
1989-09-19 16:13:23 +00:00
|
|
|
int shifting = (oper == LEFT || oper == RIGHT
|
|
|
|
|| oper == LEFTAB || oper == RIGHTAB);
|
1990-04-25 15:09:51 +00:00
|
|
|
int ptrdiff = 0;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
|
|
|
t1 = any2arith(e1p, oper);
|
|
|
|
t2 = any2arith(e2p, oper);
|
1990-04-25 15:09:51 +00:00
|
|
|
|
|
|
|
if (int_size != pointer_size) {
|
|
|
|
if (ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF)
|
|
|
|
|| ((*e2p)->ex_flags & EX_PTRDIFF)) {
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
if (!((*e1p)->ex_flags & EX_PTRDIFF)
|
|
|
|
&& (t1 == LONG || t1 == LNGLNG))
|
1990-04-25 15:09:51 +00:00
|
|
|
ptrdiff = 0;
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
if (!((*e2p)->ex_flags & EX_PTRDIFF)
|
|
|
|
&& (t2 == LONG || t2 == LNGLNG)
|
1990-04-25 15:09:51 +00:00
|
|
|
&& !shifting)
|
|
|
|
ptrdiff = 0;
|
|
|
|
}
|
|
|
|
/* Now turn off ptrdiff flags */
|
|
|
|
(*e1p)->ex_flags &= ~EX_PTRDIFF;
|
|
|
|
(*e2p)->ex_flags &= ~EX_PTRDIFF;
|
|
|
|
}
|
|
|
|
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
/* Now t1 and t2 are either INT, LONG, LNGLNG,
|
|
|
|
FLOAT, DOUBLE, or LNGDBL
|
|
|
|
*/
|
1989-02-07 11:04:05 +00:00
|
|
|
|
|
|
|
/* If any operand has the type long double, the other operand
|
|
|
|
is converted to long double.
|
|
|
|
*/
|
1989-09-19 16:13:23 +00:00
|
|
|
/* ??? t1 == LNGDBL, t2 == DOUBLE */
|
1989-02-07 11:04:05 +00:00
|
|
|
if (t1 == LNGDBL) {
|
1992-04-21 09:54:32 +00:00
|
|
|
if (t2 != LNGDBL) {
|
|
|
|
if (t2 == DOUBLE || t2 == FLOAT)
|
|
|
|
float2float(e2p, lngdbl_type);
|
|
|
|
else
|
1989-02-07 11:04:05 +00:00
|
|
|
int2float(e2p, lngdbl_type);
|
1992-04-21 09:54:32 +00:00
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
return;
|
|
|
|
} else if (t2 == LNGDBL) {
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
if (t1 != LNGDBL) {
|
1992-04-21 09:54:32 +00:00
|
|
|
if (t1 == DOUBLE || t1 == FLOAT)
|
|
|
|
float2float(e1p, lngdbl_type);
|
|
|
|
else
|
1989-02-07 11:04:05 +00:00
|
|
|
int2float(e1p, lngdbl_type);
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If any operand has the type double, the other operand
|
|
|
|
is converted to double.
|
|
|
|
*/
|
|
|
|
if (t1 == DOUBLE) {
|
1992-04-21 09:54:32 +00:00
|
|
|
if (t2 == FLOAT)
|
|
|
|
float2float(e2p, double_type);
|
|
|
|
else if (t2 != DOUBLE)
|
1989-02-07 11:04:05 +00:00
|
|
|
int2float(e2p, double_type);
|
|
|
|
return;
|
|
|
|
} else if (t2 == DOUBLE) {
|
1992-04-21 09:54:32 +00:00
|
|
|
if (t1 == FLOAT)
|
|
|
|
float2float(e1p, double_type);
|
|
|
|
else if (t1 != DOUBLE)
|
1989-02-07 11:04:05 +00:00
|
|
|
int2float(e1p, double_type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If any operand has the type float, the other operand
|
|
|
|
is converted to float.
|
|
|
|
*/
|
|
|
|
if (t1 == FLOAT) {
|
|
|
|
if (t2 != FLOAT)
|
|
|
|
int2float(e2p, float_type);
|
|
|
|
return;
|
|
|
|
} else if (t2 == FLOAT) {
|
|
|
|
if (t1 != FLOAT)
|
|
|
|
int2float(e1p, float_type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
/* Now they are INT, LONG or LNGLNG */
|
1989-02-07 11:04:05 +00:00
|
|
|
u1 = (*e1p)->ex_type->tp_unsigned;
|
|
|
|
u2 = (*e2p)->ex_type->tp_unsigned;
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
convert1 = NULL;
|
|
|
|
convert2 = NULL;
|
|
|
|
|
|
|
|
/* If either operand is a long long, the other operand
|
|
|
|
is converted to long long; else if either operand is
|
|
|
|
a long, the other operand is converted to a long.
|
|
|
|
|
|
|
|
If one operand is signed and the other operand is
|
|
|
|
unsigned, if the signed type can represent all values
|
|
|
|
of the unsigned type, the unsigned operand is
|
|
|
|
converted to the signed type, else both operands are
|
|
|
|
converted to an unsigned type.
|
1989-02-07 11:04:05 +00:00
|
|
|
*/
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
if (t1 == LNGLNG && u1 && (t2 != LNGLNG || !u2))
|
|
|
|
convert2 = ulnglng_type;
|
|
|
|
else if (t2 == LNGLNG && u2 && (t1 != LNGLNG || !u1))
|
|
|
|
convert1 = ulnglng_type;
|
|
|
|
else if (t1 == LNGLNG && t2 != LNGLNG && u2) {
|
|
|
|
if ((t2 == LONG ? long_size : int_size) < lnglng_size)
|
|
|
|
convert2 = lnglng_type;
|
|
|
|
else
|
|
|
|
convert1 = convert2 = ulnglng_type;
|
|
|
|
} else if (t2 == LNGLNG && t1 != LNGLNG && u1) {
|
|
|
|
if ((t1 == LONG ? long_size : int_size) < lnglng_size)
|
|
|
|
convert1 = lnglng_type;
|
|
|
|
else
|
|
|
|
convert1 = convert2 = ulnglng_type;
|
|
|
|
} else if (t1 == LNGLNG && t2 != LNGLNG)
|
|
|
|
convert2 = lnglng_type;
|
|
|
|
else if (t2 == LNGLNG && t1 != LNGLNG)
|
|
|
|
convert1 = lnglng_type;
|
|
|
|
else if (t1 == LONG && u1 && (t2 != LONG || !u2))
|
|
|
|
convert2 = ulong_type;
|
|
|
|
else if (t2 == LONG && u2 && (t1 != LONG || !u1))
|
|
|
|
convert1 = ulong_type;
|
|
|
|
else if (t1 == LONG && t2 == INT && u2) {
|
|
|
|
if (int_size < long_size)
|
|
|
|
convert2 = long_type;
|
|
|
|
else
|
|
|
|
convert1 = convert2 = ulong_type;
|
|
|
|
} else if (t2 == LONG && t1 == INT && u1) {
|
|
|
|
if (int_size < long_size)
|
|
|
|
convert1 = long_type;
|
|
|
|
else
|
|
|
|
convert1 = convert2 = ulong_type;
|
|
|
|
} else if (t1 == LONG && t2 != LONG)
|
|
|
|
convert2 = long_type;
|
|
|
|
else if (t2 == LONG && t1 != LONG)
|
|
|
|
convert1 = long_type;
|
|
|
|
|
|
|
|
if (convert1 && !shifting) /* ??? */
|
|
|
|
t1 = int2int(e1p, convert1);
|
|
|
|
if (convert2)
|
|
|
|
t2 = int2int(e2p, convert2);
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1990-02-20 13:31:52 +00:00
|
|
|
u1 = (*e1p)->ex_type->tp_unsigned;
|
|
|
|
u2 = (*e2p)->ex_type->tp_unsigned;
|
|
|
|
|
1989-02-07 11:04:05 +00:00
|
|
|
/* If either operand has type unsigned int, the other operand
|
|
|
|
is converted to unsigned int.
|
|
|
|
Otherwise, both operands have type int.
|
|
|
|
*/
|
1989-09-19 16:13:23 +00:00
|
|
|
if (u1 && !u2 && !shifting)
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
t2 = int2int(e2p, uint_type);
|
1989-02-07 11:04:05 +00:00
|
|
|
else
|
1989-09-19 16:13:23 +00:00
|
|
|
if (!u1 && u2 && !shifting)
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
t1 = int2int(e1p, uint_type);
|
1990-04-25 15:09:51 +00:00
|
|
|
|
|
|
|
if (int_size != pointer_size) {
|
|
|
|
if (ptrdiff) {
|
|
|
|
(*e1p)->ex_flags |= EX_PTRDIFF;
|
|
|
|
(*e2p)->ex_flags |= EX_PTRDIFF;
|
|
|
|
}
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void relbalance(register struct expr **e1p, int oper, register struct expr **e2p)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expressions *e1p and *e2p are balanced to be operands
|
1989-12-12 12:52:03 +00:00
|
|
|
of the relational operator oper, or the ':'.
|
|
|
|
Care is taken to switch the operands in case of a
|
|
|
|
null-pointer constant. This is done so that ch3cast()
|
|
|
|
allows assignments of a null-pointer to a function
|
|
|
|
pointer.
|
1989-02-07 11:04:05 +00:00
|
|
|
*/
|
1989-12-12 12:52:03 +00:00
|
|
|
register struct expr *e1 = *e1p, *e2 = *e2p;
|
|
|
|
struct expr *tmpexpr;
|
|
|
|
|
|
|
|
if (e1->ex_type->tp_fund == POINTER
|
|
|
|
&& is_cp_cst(e1)
|
|
|
|
&& e1->VL_VALUE == 0) {
|
|
|
|
tmpexpr = e1;
|
|
|
|
e1 = e2;
|
|
|
|
e2 = tmpexpr;
|
|
|
|
}
|
|
|
|
if (e1->ex_type->tp_fund == POINTER)
|
|
|
|
ch3pointer(e2p, oper, e1->ex_type);
|
|
|
|
else if (e2->ex_type->tp_fund == POINTER)
|
|
|
|
ch3pointer(e1p, oper, e2->ex_type);
|
|
|
|
else if (e1->ex_type == e2->ex_type
|
|
|
|
&& e1->ex_type->tp_fund == ENUM) {}
|
1989-09-29 16:20:38 +00:00
|
|
|
else if (oper == ':'
|
1989-12-12 12:52:03 +00:00
|
|
|
&& e1->ex_type->tp_fund == VOID
|
|
|
|
&& e2->ex_type->tp_fund == VOID) {}
|
1989-02-07 11:04:05 +00:00
|
|
|
else
|
|
|
|
arithbalance(e1p, oper, e2p);
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void ch3pointer(struct expr **expp, int oper, register struct type *tp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* Checks whether *expp may be compared to tp using oper,
|
1989-09-29 16:20:38 +00:00
|
|
|
as described in chapter 3.3.8 and 3.3.9.
|
1989-02-07 11:04:05 +00:00
|
|
|
tp is known to be a pointer.
|
|
|
|
*/
|
|
|
|
register struct expr *exp = *expp;
|
|
|
|
|
|
|
|
if (exp->ex_type->tp_fund == POINTER) {
|
|
|
|
if (exp->ex_type != tp)
|
1989-09-25 14:28:10 +00:00
|
|
|
ch3cast(expp, oper, tp);
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
else
|
1989-09-19 16:13:23 +00:00
|
|
|
if (is_integral_type(exp->ex_type)) {
|
|
|
|
if ((oper != EQUAL && oper != NOTEQUAL && oper != ':')
|
|
|
|
|| !(is_cp_cst(exp) && exp->VL_VALUE == 0)) {
|
|
|
|
expr_error(exp,"%s on %s and pointer",
|
|
|
|
symbol2str(oper),
|
|
|
|
symbol2str(exp->ex_type->tp_fund));
|
|
|
|
}
|
1989-09-25 14:28:10 +00:00
|
|
|
ch3cast(expp, CAST, tp);
|
1989-09-19 16:13:23 +00:00
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
else {
|
|
|
|
expr_error(exp, "%s on %s and pointer",
|
|
|
|
symbol2str(oper),
|
|
|
|
symbol2str(exp->ex_type->tp_fund)
|
|
|
|
);
|
1989-09-25 14:28:10 +00:00
|
|
|
ch3cast(expp, oper, tp);
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-02-18 16:42:15 +00:00
|
|
|
any2arith(register struct expr **expp, register int oper)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
1989-09-19 16:13:23 +00:00
|
|
|
/* Turns any expression into int_type, long_type,
|
|
|
|
float_type, double_type or lngdbl_type.
|
1989-02-07 11:04:05 +00:00
|
|
|
*/
|
|
|
|
int fund;
|
|
|
|
|
|
|
|
switch (fund = (*expp)->ex_type->tp_fund) {
|
|
|
|
case CHAR:
|
|
|
|
case SHORT:
|
2017-11-10 03:22:13 +00:00
|
|
|
assert((*expp)->ex_type->tp_size <= int_type->tp_size);
|
1989-09-19 16:13:23 +00:00
|
|
|
|
|
|
|
if ((*expp)->ex_type->tp_unsigned
|
|
|
|
&& (*expp)->ex_type->tp_size == int_type->tp_size) {
|
|
|
|
int2int(expp, uint_type);
|
|
|
|
} else {
|
|
|
|
int2int(expp, int_type);
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
break;
|
|
|
|
case INT:
|
|
|
|
case LONG:
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
case LNGLNG:
|
1989-02-07 11:04:05 +00:00
|
|
|
break;
|
|
|
|
case ENUM:
|
|
|
|
#ifndef LINT
|
1991-01-07 12:33:38 +00:00
|
|
|
/* we do not want this conversion for lint, since we
|
|
|
|
want to keep enums and ints separate
|
|
|
|
*/
|
1989-02-07 11:04:05 +00:00
|
|
|
int2int(expp, int_type);
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* LINT */
|
1989-02-07 11:04:05 +00:00
|
|
|
break;
|
|
|
|
case FLOAT:
|
1989-09-19 16:13:23 +00:00
|
|
|
/* only when it is a parameter and the default promotion should
|
|
|
|
occur. Hence this code is moved to any2parameter().
|
1989-02-07 11:04:05 +00:00
|
|
|
float2float(expp, double_type);
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
case DOUBLE:
|
|
|
|
case LNGDBL:
|
|
|
|
break;
|
|
|
|
#ifndef NOBITFIELD
|
|
|
|
case FIELD:
|
|
|
|
field2arith(expp);
|
|
|
|
break;
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* NOBITFIELD */
|
1989-02-07 11:04:05 +00:00
|
|
|
default:
|
|
|
|
expr_error(*expp, "operator %s on non-numerical operand (%s)",
|
|
|
|
symbol2str(oper), symbol2str(fund));
|
|
|
|
case ERRONEOUS:
|
|
|
|
erroneous2int(expp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*expp)->ex_type->tp_fund;
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void erroneous2int(struct expr **expp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* the (erroneous) expression *expp is replaced by an
|
|
|
|
int expression
|
|
|
|
*/
|
|
|
|
register struct expr *exp = *expp;
|
|
|
|
int flags = exp->ex_flags;
|
|
|
|
|
|
|
|
free_expression(exp);
|
|
|
|
exp = intexpr((arith)0, INT);
|
|
|
|
exp->ex_flags = (flags | EX_ERROR);
|
|
|
|
*expp = exp;
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
struct expr *arith2arith(struct type *tp, int oper, register struct expr *expr)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* arith2arith constructs a new expression containing a
|
|
|
|
run-time conversion between some arithmetic types.
|
|
|
|
*/
|
|
|
|
register struct expr *new = new_expr();
|
|
|
|
|
|
|
|
new->ex_file = expr->ex_file;
|
|
|
|
new->ex_line = expr->ex_line;
|
|
|
|
new->ex_type = tp;
|
|
|
|
new->ex_class = Type;
|
|
|
|
return new_oper(tp, new, oper, expr);
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
int int2int(struct expr **expp, register struct type *tp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression *expp, which is of some integral type, is
|
|
|
|
converted to the integral type tp.
|
|
|
|
*/
|
|
|
|
register struct expr *exp = *expp;
|
|
|
|
|
|
|
|
if (is_cp_cst(exp)) {
|
|
|
|
register struct type *tp1 = exp->ex_type;
|
|
|
|
|
|
|
|
exp->ex_type = tp;
|
|
|
|
if (! tp1->tp_unsigned && tp->tp_unsigned) {
|
|
|
|
/* Avoid "unreal" overflow warnings, such as
|
|
|
|
caused by f.i.:
|
|
|
|
unsigned int x = ~0;
|
|
|
|
unsigned int y = -1;
|
|
|
|
*/
|
|
|
|
extern long full_mask[];
|
|
|
|
long remainder = exp->VL_VALUE &
|
|
|
|
~full_mask[(int)(tp->tp_size)];
|
|
|
|
|
|
|
|
if (remainder == 0 ||
|
|
|
|
remainder == ~full_mask[(int)(tp->tp_size)]) {
|
|
|
|
exp->VL_VALUE &= ~remainder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cut_size(exp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
exp = arith2arith(tp, INT2INT, exp);
|
|
|
|
}
|
|
|
|
*expp = exp;
|
|
|
|
return exp->ex_type->tp_fund;
|
|
|
|
}
|
|
|
|
|
1990-02-28 14:51:35 +00:00
|
|
|
/* With compile-time constants, we don't set fp_used, since this is done
|
|
|
|
* only when necessary in eval.c.
|
|
|
|
*/
|
2019-02-18 16:42:15 +00:00
|
|
|
void int2float(register struct expr **expp, struct type *tp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression *expp, which is of some integral type, is
|
|
|
|
converted to the floating type tp.
|
|
|
|
*/
|
|
|
|
register struct expr *exp = *expp;
|
1990-07-19 17:16:36 +00:00
|
|
|
int uns = exp->ex_type->tp_unsigned;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
|
|
|
if (is_cp_cst(exp)) {
|
|
|
|
exp->ex_type = tp;
|
|
|
|
exp->ex_class = Float;
|
1989-11-22 13:58:36 +00:00
|
|
|
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
1990-02-28 14:51:35 +00:00
|
|
|
else {
|
|
|
|
fp_used = 1;
|
|
|
|
*expp = arith2arith(tp, INT2FLOAT, *expp);
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void float2int(struct expr **expp, struct type *tp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression *expp, which is of some floating type, is
|
|
|
|
converted to the integral type tp.
|
|
|
|
*/
|
1989-11-22 13:58:36 +00:00
|
|
|
register struct expr *ex = *expp;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1989-11-22 13:58:36 +00:00
|
|
|
if (is_fp_cst(ex)) {
|
|
|
|
arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
|
|
|
|
|
|
|
|
if (flt_status == FLT_OVFL)
|
|
|
|
expr_warning(ex,"overflow in float to int conversion");
|
|
|
|
else if (flt_status == FLT_UNFL)
|
|
|
|
expr_warning(ex,"underflow in float to unsigned conversion");
|
|
|
|
ex->ex_type = tp;
|
|
|
|
/* The following lines are copied from fill_int_expr */
|
|
|
|
ex->ex_class = Value;
|
|
|
|
ex->VL_CLASS = Const;
|
|
|
|
ex->VL_VALUE = ar;
|
|
|
|
cut_size(ex);
|
1990-02-28 14:51:35 +00:00
|
|
|
} else {
|
|
|
|
fp_used = 1;
|
|
|
|
*expp = arith2arith(tp, FLOAT2INT, ex);
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void float2float(register struct expr **expp, struct type *tp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression *expp, which is of some floating type, is
|
|
|
|
converted to the floating type tp.
|
|
|
|
There is no need for an explicit conversion operator
|
|
|
|
if the expression is a constant.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (is_fp_cst(*expp))
|
|
|
|
(*expp)->ex_type = tp;
|
1990-02-28 14:51:35 +00:00
|
|
|
else {
|
|
|
|
fp_used = 1;
|
1989-02-07 11:04:05 +00:00
|
|
|
*expp = arith2arith(tp, FLOAT2FLOAT, *expp);
|
1990-02-28 14:51:35 +00:00
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void array2pointer(register struct expr *exp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression, which must be an array, is converted
|
|
|
|
to a pointer.
|
|
|
|
*/
|
1989-09-19 16:13:23 +00:00
|
|
|
exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up
|
|
|
|
, /* exp->ex_type->tp_typequal */ 0
|
|
|
|
, (arith)0, NO_PROTO);
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void function2pointer(register struct expr *exp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression, which must be a function, is converted
|
|
|
|
to a pointer to the function.
|
|
|
|
*/
|
|
|
|
exp->ex_type = construct_type(POINTER, exp->ex_type, 0,
|
|
|
|
(arith)0, NO_PROTO);
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void string2pointer(register struct expr *ex)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression, which must be a string constant, is converted
|
|
|
|
to a pointer to the string-containing area.
|
|
|
|
*/
|
1993-03-30 09:41:00 +00:00
|
|
|
label lbl;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1993-03-30 09:41:00 +00:00
|
|
|
lbl = code_string(ex->SG_VALUE, ex->SG_LEN);
|
1989-02-07 11:04:05 +00:00
|
|
|
ex->ex_class = Value;
|
|
|
|
ex->VL_CLASS = Label;
|
|
|
|
ex->VL_LBL = lbl;
|
|
|
|
ex->VL_VALUE = (arith)0;
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void opnd2integral(register struct expr **expp, int oper)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
register int fund = (*expp)->ex_type->tp_fund;
|
|
|
|
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
if (fund != INT && fund != LONG && fund != LNGLNG) {
|
1989-02-07 11:04:05 +00:00
|
|
|
expr_error(*expp, "%s operand to %s",
|
|
|
|
symbol2str(fund), symbol2str(oper));
|
|
|
|
erroneous2int(expp);
|
|
|
|
/* fund = INT; */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void opnd2logical(register struct expr **expp, int oper)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
int fund = (*expp)->ex_type->tp_fund;
|
|
|
|
|
1991-07-01 14:10:15 +00:00
|
|
|
if (fund == FUNCTION || fund == ARRAY) {
|
|
|
|
expr_warning(*expp, "%s operand to %s",
|
|
|
|
symbol2str(fund),
|
|
|
|
symbol2str(oper));
|
|
|
|
if (fund == FUNCTION) function2pointer(*expp);
|
|
|
|
else array2pointer(*expp);
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
#ifndef NOBITFIELD
|
1991-07-01 14:10:15 +00:00
|
|
|
else
|
1989-02-07 11:04:05 +00:00
|
|
|
if (fund == FIELD)
|
|
|
|
field2arith(expp);
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* NOBITFIELD */
|
1989-02-07 11:04:05 +00:00
|
|
|
switch (fund = (*expp)->ex_type->tp_fund) {
|
|
|
|
case CHAR:
|
|
|
|
case SHORT:
|
|
|
|
case INT:
|
|
|
|
case LONG:
|
Begin to add `long long` to C compiler for linux386.
Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough. Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
union q {
long long ll;
unsigned long long ull;
int i[2];
};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform. The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
- BigPars, SmallPars: Add default size, alignment of long long.
- align.h: Add lnglng_align.
- arith.c: Convert arithmetic operands to long long or unsigned long
long when necessary; avoid conversion from long long to long.
Allow long long as an arithmetic, integral, or logical operand.
- ch3.c: Handle long long like int and long when erroneously applying
a selector, like `long long ll; ll.member` or `ll->member`. Add
long long to integral and arithmetic types.
- code.c: Add long long to type stabs for debugging.
- conversion.c: Add long long to integral conversions.
- cstoper.c: Write masks up to full_mask[8]. Add FIXME comment.
- declar.g: Parse `long long` in code.
- decspecs.c: Understand long long in type declarations.
- eval.c: Add long long to operations, to generate code like `adi 8`.
Don't use `ldc` with constant over 4 bytes.
- ival.g: Allow long long in initializations.
- main.c: Set lnglng_type and related values.
- options.c: Add option like `-Vq8.4` to set long long to size 8,
alignment 4. I chose 'q', because Perl's pack and Ruby's
Array#pack use 'q' for 64-bit or long long values; it might be a
reference to BSD's old quad_t alias for long long.
- sizes.h: Add lnglng_size.
- stab.c: Allow long long when writing the type stab for debugging.
Switch from calculating the ranges to hardcoding them in strings;
add 8-byte ranges as a special case. This also hardcodes the
unsigned 4-byte range as "0;-1". Before it was either "0;-1" or
"0;4294967295", depending on sizeof(long) in the compiler.
- struct.c: Try long long bitfield, but it will probably give the
error, "bit field type long long does not fit in a word".
- switch.c: Update comment.
- tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
- type.c, type.str: Add lnglng_type and ulnglng_type. Add function
no_long_long() to check if long long is disabled.
2019-09-02 15:24:44 +00:00
|
|
|
case LNGLNG:
|
1989-02-07 11:04:05 +00:00
|
|
|
case ENUM:
|
|
|
|
case POINTER:
|
|
|
|
case FLOAT:
|
|
|
|
case DOUBLE:
|
1989-09-19 16:13:23 +00:00
|
|
|
case LNGDBL:
|
1989-02-07 11:04:05 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
expr_error(*expp, "%s operand to %s",
|
|
|
|
symbol2str(fund), symbol2str(oper));
|
|
|
|
case ERRONEOUS:
|
|
|
|
erroneous2int(expp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-10 21:04:18 +00:00
|
|
|
void
|
2019-02-18 16:42:15 +00:00
|
|
|
opnd2test(register struct expr **expp, int oper)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
opnd2logical(expp, oper);
|
1989-10-23 13:50:27 +00:00
|
|
|
if ((*expp)->ex_class == Oper) {
|
|
|
|
switch((*expp)->OP_OPER) {
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case LESSEQ:
|
|
|
|
case GREATEREQ:
|
|
|
|
case EQUAL:
|
|
|
|
case NOTEQUAL:
|
|
|
|
case '!':
|
|
|
|
case AND:
|
|
|
|
case OR: /* && and || also impose a test */
|
|
|
|
/* It is already a test */
|
|
|
|
return;
|
|
|
|
case ',':
|
|
|
|
opnd2test(&((*expp)->OP_RIGHT), oper);
|
|
|
|
return;
|
|
|
|
}
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
1989-10-23 13:50:27 +00:00
|
|
|
ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT));
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void any2opnd(register struct expr **expp, int oper)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
if (!*expp)
|
|
|
|
return;
|
1989-11-22 13:58:36 +00:00
|
|
|
|
1989-11-22 16:41:09 +00:00
|
|
|
if (oper == SIZEOF || oper == ADDRESSOF) return;
|
1989-11-22 13:58:36 +00:00
|
|
|
|
1989-09-19 16:13:23 +00:00
|
|
|
switch ((*expp)->ex_type->tp_fund) {
|
1989-02-07 11:04:05 +00:00
|
|
|
case CHAR:
|
|
|
|
case SHORT:
|
|
|
|
case ENUM:
|
2019-02-23 16:46:05 +00:00
|
|
|
/* case FLOAT: *//* not necessary anymore */
|
1989-02-07 11:04:05 +00:00
|
|
|
any2arith(expp, oper);
|
|
|
|
break;
|
|
|
|
case ARRAY:
|
|
|
|
array2pointer(*expp);
|
|
|
|
break;
|
|
|
|
case POINTER:
|
|
|
|
if ((*expp)->ex_class == String)
|
|
|
|
string2pointer(*expp);
|
|
|
|
break;
|
1989-11-22 13:58:36 +00:00
|
|
|
case FUNCTION:
|
|
|
|
function2pointer(*expp);
|
|
|
|
break;
|
1989-02-07 11:04:05 +00:00
|
|
|
#ifndef NOBITFIELD
|
|
|
|
case FIELD:
|
|
|
|
field2arith(expp);
|
|
|
|
break;
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* NOBITFIELD */
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:42:15 +00:00
|
|
|
void any2parameter(register struct expr **expp)
|
1989-02-07 13:16:02 +00:00
|
|
|
{
|
|
|
|
/* To handle default argument promotions
|
|
|
|
*/
|
|
|
|
any2opnd(expp, '(');
|
1990-04-25 15:09:51 +00:00
|
|
|
if (int_size != pointer_size)
|
|
|
|
if ((*expp)->ex_flags & EX_PTRDIFF)
|
|
|
|
expr_warning(*expp, "pointer difference caused long expression");
|
1989-02-07 13:16:02 +00:00
|
|
|
if ((*expp)->ex_type->tp_fund == FLOAT)
|
|
|
|
float2float(expp, double_type);
|
|
|
|
}
|
|
|
|
|
1989-02-07 11:04:05 +00:00
|
|
|
#ifndef NOBITFIELD
|
2019-02-18 16:42:15 +00:00
|
|
|
void field2arith(register struct expr **expp)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
|
|
|
/* The expression to extract the bitfield value from the
|
|
|
|
memory word is put in the tree.
|
|
|
|
*/
|
|
|
|
register struct type *tp = (*expp)->ex_type->tp_up;
|
|
|
|
register struct field *fd = (*expp)->ex_type->tp_field;
|
|
|
|
|
1990-05-18 10:29:57 +00:00
|
|
|
(*expp)->ex_type = word_type;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1990-03-29 10:41:46 +00:00
|
|
|
if (tp->tp_unsigned) { /* don't worry about the sign bit */
|
1990-07-19 17:16:36 +00:00
|
|
|
if (fd->fd_width >= 8 * (int)word_size)
|
1990-05-18 10:29:57 +00:00
|
|
|
(*expp)->ex_type = uword_type;
|
1989-09-25 14:28:10 +00:00
|
|
|
ch3bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
|
|
|
|
ch3bin(expp, '&', intexpr(fd->fd_mask, INT));
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
else { /* take care of the sign bit: sign extend if needed */
|
1990-07-19 17:16:36 +00:00
|
|
|
arith other_bits = (int)word_size * 8 - fd->fd_width;
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1989-09-25 14:28:10 +00:00
|
|
|
ch3bin(expp, LEFT,
|
1990-07-19 17:16:36 +00:00
|
|
|
intexpr(other_bits - fd->fd_shift,
|
1989-02-07 11:04:05 +00:00
|
|
|
INT)
|
|
|
|
);
|
1990-07-19 17:16:36 +00:00
|
|
|
ch3bin(expp, RIGHT, intexpr(other_bits, INT));
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|
|
|
|
}
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* NOBITFIELD */
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1989-09-19 16:13:23 +00:00
|
|
|
/* switch_sign_fp() negates the given floating constant expression,
|
|
|
|
* and frees the string representing the old value.
|
|
|
|
*/
|
2019-02-18 16:42:15 +00:00
|
|
|
void switch_sign_fp(register struct expr *expr)
|
1989-02-07 11:04:05 +00:00
|
|
|
{
|
1989-09-19 16:13:23 +00:00
|
|
|
flt_umin(&(expr->FL_ARITH));
|
1989-02-07 11:04:05 +00:00
|
|
|
}
|