On a target with a 16-bit mask (for example), we would choose the type
of an integer literal "1024" to be an int16. Previously, we used an int32,
which is a worse fit and leads to less efficient code than an int16
on a 16-bit mask target. (However, we'd still give an integer literal
1000000 the type int32, even in a 16-bit target.)
Updated the tests to still pass with 8 and 16-bit targets, given this
change.
There were a number of places throughout the system that assumed that the
execution mask would only have either 32-bit or 1-bit elements. This
commit makes it possible to have a target with an 8- or 16-bit mask.
We can now do constant folding with all basic datatypes (the previous
implementation handled int32 well, but had limited, if any, coverage
for other datatypes.)
Reduced a bit of repeated code in the constant folding implementation
through template helper functions.
We now follow the rule that the type of an integer constant is
the first of int32, uint32, int64, uint64, that can hold the
value. (Unless 'u' or 'l' suffixes have been provided.)
Fixes issue #299.
When "break", "continue", or "return" is used under varying control flow,
we now always check the execution mask to see if all of the program
instances are executing it. (Previously, this was only done with "cbreak",
"ccontinue", and "creturn", which are now deprecated.)
An important effect of this change is that it fixes a family of cases
where we could end up running with an "all off" execution mask, which isn't
supposed to happen, as it leads to all sorts of invalid behavior.
This change does cause the volume rendering example to run 9% slower, but
doesn't affect the other examples.
Issue #257.
It's now legal to write:
struct Foo { Foo *next; };
previously, a predeclaration "struct Foo;" was required. This fixes
issue #287.
This change also fixes a bug where multiple forward declarations
"struct Foo; struct Foo;" would incorrectly issue an error on the
second one.
This allows adding types to the list that are included in the automatically-generated
header files.
struct Foo { . . . };
struct Bar { . . . };
export { Foo, Bar };
It can sometimes be useful to know the general place we were in the program
when an assertion hit; when the position is available / applicable, this
macro is now used.
Issue #268.
We now have a set of template functions CastType<AtomicType>, etc., that in
turn use a new typeId field in each Type instance, allowing them to be inlined
and to be quite efficient.
This improves front-end performance for a particular large program by 28%.
Before, if the function was declared before being defined, then the symbol's
SourcePos would be left set to the position of the declaration. This ended
up getting the debugging symbols mixed up in this case, which was undesirable.
Now a declaration like 'struct Foo;' can be used to establish the
name of a struct type, without providing a definition. One can
pass pointers to such types around the system, but can't do much
else with them (as in C/C++).
Issue #125.
The decl.* code now no longer interacts with Symbols, but just returns
names, types, initializer expressions, etc., as needed. This makes the
code a bit more understandable.
Fixes issues #171 and #130.
We now have separate Expr implementations for dereferencing pointers
and automatically dereferencing references. This is in particular
necessary so that we can detect attempts to dereference references
with the '*' operator in programs and issue an error in that case.
Fixes issue #192.