This was already done by the optimizer, but it is simple enough to just do it all the time. This avoids most performance regressions from the previous commit, and also generates more efficient code for long long stores (in the common cases where the value of an assignment expression is not used in any larger expression).
The value of an assignment expression should be exactly what gets written to the destination, without any extra range or precision. Since floating-point expressions generally do have extra precision, we need to load the actual stored value to get rid of it.
This means that floating-point constants can now have the range and precision of the extended type (aka long double), and floating-point constant expressions evaluated within the compiler also have that same range and precision (matching expressions evaluated at run time). This new behavior is intended to match the behavior specified in the C99 and later standards for FLT_EVAL_METHOD 2.
This fixes the previous problem where long double constants and constant expressions of type long double were not represented and evaluated with the full range and precision that they should be. It also gives extra range and precision to constants and constant expressions of type double or float. This may have pluses and minuses, but at any rate it is consistent with the existing behavior for expressions evaluated at run time, and with one of the possible models of floating point evaluation specified in the C standards.
This gives the name of the current function, as if the following definition appeared at the beginning of the function body:
static const char __func__[] = "function-name";
These instructions can be generated for indirect accesses to quad values, and the optimization can sometimes make those code sequences more efficient (e.g. avoiding unnecessary reloads of Y).
It was calling fabs() without having included <math.h>, causing fabs() to be treated as returning an int rather than a floating-point value. This misinterpretation of the return value could cause test failures.
* longlong:
In PP expressions, make sure identifiers turn into 0LL.
Optimize quad == 0 comparisons.
Do unsigned quad inequalities without loading operands on stack.
Do quad equality comparisons without loading operands on stack.
Do unary quad ops without loading operand on stack.
Do quad add/subtract without loading operands on stack.
Implement support for doing quad ops without loading operands on stack.
Evaluate constant expressions with long long and floating operands.
Let functions store a long long return value directly into a variable in the caller.
Optimize some quad ops to use interleaved loads and stores.
Basic infrastructure for using different quadword locations in codegen.
Allow static evaluation of ? : expressions with long long operands.
Statically evaluate casts to and from long long.
Implement conversions from long long to other types in the optimizer.
Add various intermediate code peephole optimizations.
Fix a comment.
Support switch statements using long long expressions.
Update headers to support long long (and intmax_t typedef'd as long long).
Add the predefined macro __ORCAC_HAS_LONG_LONG__.
Do preprocessor arithmetic in intmax_t/uintmax_t (aka long long types).
Evaluate 64-bit comparisons in constant expressions.
Add support for real to long long conversions.
Implement comparisons for signed long long.
Implement comparisons (>, >=, <, <=) for unsigned long long.
Support 64-bit decimal constants in code.
Evaluate arithmetic and shifts in long long constant expressions.
Update printf/scanf format checker to match recent library changes.
Implement && and || operators for long long types.
Implement pc_ind (load indirect) for long long.
Do not corrupt long long expressions that cannot be evaluated at compile time.
Report errors in a few cases where the codegen finds unexpected types.
Slightly optimize stack save code for calls to long long functions.
Handle long long in pc_equ/pc_neq optimizations.
Allow unsigned constants in "address+constant" constant expressions.
Evaluate some kinds of long long operations in constant expressions.
Implement 64-bit shifts.
Implement basic peephole optimizations for some 64-bit operations.
Do not copy CGI.Comments into CGI.pas.
Generate code for long long to real conversions.
Don't bogusly push stuff on the stack for conversions to non-long types.
Implement support for functions returning (unsigned) long long.
Compute how many bytes of arguments are passed to a function.
Implement 64-bit division and remainder, signed and unsigned.
Implement 64-bit multiplication support.
Allow pointer arithmetic using long long values.
Implement indirect store/copy operations for 64-bit types.
Add long long support for a couple lint checks.
Add long long support for the ! operator.
Give an error when trying to evaluate constant expressions with long long operands.
Make expressionValue a saturating approximation of the true value for long long expressions.
Enable automatic comparison with 0 for long longs.
Add some support for ++/-- on long long values.
Add support for emitting 64-bit constants in statically-initialized data.
Add most of the infrastructure to support 64-bit decimal constants.
Support 64-bit integer constants in hex/octal/binary formats.
Initial support for constants with long long types.
Implement equality/inequality comparisons for 64-bit types.
Implement remaining conversions of integer types to and from long long.
Update the debugging format for long long values.
Begin implementing conversions to and from 64-bit types.
Implement 64-bit addition and subtraction.
Add support for new pcodes in optimizer.
Implement unary negation and bitwise complement for 64-bit types.
Implement bitwise and/or/xor for 64-bit types.
Handle (unsigned) long long in the front-end code for binary conversions.
Restore old order of baseTypeEnum values.
Implement basic load/store ops for long long.
Initial code to recognize 'long long' as a type.
This works when both operands are simple loads, such that they can be broken up into operations on their subwords in a standard format.
Currently, this is implemented for bitwise binary ops, but it can also be expanded to arithmetic, etc.
Note that we currently defer evaluation of such expressions to run time if the long long value cannot be represented exactly in a double, because statically-evaluated floating point expressions use the double format rather than the extended (long double) format used at run time.
This optimization works when the return value is stored directly to a local variable and not used otherwise (typically only recognized when using intermediate code peephole optimization).
This allows them to bypass the intermediate step of loading the value onto the stack. Currently, this only works for simple cases where a value is loaded and immediately stored.
For the moment, this does not really do anything, but it lays the groundwork for not always having to load quadword values to the stack before operating on or storing them.
The code of PeepHoleOptimization is now big enough that it triggers bogus "Relative address out of range" range errors from the linker. This is a linker bug and should be fixed there.
When an expression that the intermediate code peephole optimizer could reduce to a constant was cast to a char type, the resulting value could be outside the range of that type.
The following program illustrates the problem:
#pragma optimize 1
#include <stdio.h>
int main(void) {
int i = 0;
i = (unsigned char)(i | -1);
printf("%i\n", i);
}
This includes:
*Functions operating on long long in <stdlib.h>
*Limits of long long types in <limits.h>
*64-bit types and limits (plus intmax_t and its limits) in <stdint.h>
*New format codes, plus functions operating on intmax_t, in <inttypes.h>
The new stuff is generally conditionalized to only be included if __ORCAC_HAS_LONG_LONG__ is defined, or if the implementation claims to be C99 or later. This allows the headers to remain usable with older versions of ORCA/C, or with any hypothetical "strict C89" mode that might be implemented in the future.
*Recognize the 'll' and 'j' size modifiers as denoting long long times.
*Recognize '%P' as equivalent to '%b'.
*Give a warning for 'L' length modifier in scanf, which is currently not supported (except when assignment is suppressed).
The changes to constant expressions were not allowing the unsupported constant expressions to be evaluated at run time when they appear in regular code.
This makes it more likely that unsupported ops on long long or any other types added in the future will give an error rather than silently generating bad code.
Also, update a comment.
This affected initializers like the following:
static int a[50];
static int *ip = &a[0] + 2U;
Also, introduce some basic range checks for calculations that are obviously outside the 65816's address space.