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.
Previously, GetElementType() would end up causing dynamic allocation to
happen to compute the final element type (turning types with unbound
variability into the same type with the struct's variability) each it was
called, which was wasteful and slow. Now we cache the result.
Another 20% perf on compiling that problematic program.
We don't need to explicitly create the non-const Types to do type
comparison when ignoring const-ness in the check.
We can also save some unnecessary dynamic memory allocation by
keeping strings returned from GetStructName() as references to strings.
This gives another 10% on front-end perf on that big program.
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%.
In one very large program, we were spending quite a bit of time repeatedly
getting const variants of StructTypes. This speeds up the front-end by
about 40% for that test case.
(This is something of a band-aid, pending uniquing types.)
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.
Not only was this quite verbose, it was unnecessary since we do type
equality by name. This also needed to be fixed before we could
handle structs declared like "struct Foo;", when we then e.g. have
other structs with Foo * members.
Implicit conversion to function types is now a more standard part of
the type conversion infrastructure, rather than special cases of things
like FunctionSymbolExpr immediately returning a pointer type, etc.
Improved AddressOfExpr::TypeCheck() to actually issue errors in cases
where it's illegal to take the address of an expression.
Added AddressOfExpr::GetConstant() implementation that handles taking
the address of functions.
Issue #223.