This fixes an issue where any instantiation of TypeInfo in the final
output would lead to a cryptic error with no file or line information.
This change brings ldc in line with dmd's reporting of the same error,
which at least gives file and line information to discover the problem.
Replace the stack of IRScopes, each with its own IRBuilder, by directly
tampering with the state of a single IRBuilder.
This seems like the most feasible way to account for a breaking change
in LLVM 11, disallowing IRBuilder from being copied.
Fixes#3400. The frontend pre-casts the static array operand to the
slice type for cases like `bool[4] == bool[]`, but that's not possible
in case the static array is non-mutable but the slice type is mutable.
So check the element types for equivalence, not the array types, as
static arrays and slices are NOT equivalent.
This may negatively impact performance, as the (final, i.e.,
non-virtual) Expression::is... family is implemented in D and not
available inline in the C++ headers.
The `__ArrayCast` lowering isn't (always?) done when casting a static
array to a slice with different element size.
So exploit constant source lengths and compute the target length at
compile-time.
This fixes compilable/ldc_github_421.d - a float[16] can be cast to a
float4[] with constant length 4.
Cache length & ptr in DSliceValue, so that e.g. a pair constructed from
a constant length and some ptr keeps returning a constant length instead
of an extractvalue instruction every time the length is needed.
This enables checking for matching constant lengths when copying slices
and makes `test1()` in runnable/betterc.d work (memcpy instead of
_d_array_slice_copy call):
```
int[10] a1 = void;
int[10] a2 = void;
a1[] = a2[];
```
(more or less equivalent to `a1 = a2`, which is already optimized)
I.e., this fixes#2588.
To fix the index of the new array element to be assigned to, I went for
decrementing the new length instead of saving the old length directly
before the druntime call (i.e., after evaluating the rhs expression due
to its potential side effects). The IR seems more intuitive to me this
way - load both new length+ptr directly after the druntime call and then
decrement the length by 1.
This also fixes a pessimization where the `memcmp` call would become an `invoke` if the user provides his own `memcmp` prototype in the code (the prototype would not carry the `nounwind` function attribute).
There's no <Type>_init type for aggregates (structs and classes) anymore,
effectively eliminating a *lot* of named LLVM types, some bitcasts as well
as replacements of globals etc.
To get there, it was even required to use the regular type for compatible
literals too, otherwise structs embedded as fields in other aggregates had
an anonymous type (well, the LLVM constant for the field initializer had)
and so the container initializer wasn't compatible with the regular type
anymore.
What was also necessary was a fix wrt. static arrays of bools (LLVM
constant of type `[N x i1]` vs. `[N x i8]` for regular type).
I also had to change the initializer for `char[2][3] x = 0xff` from
`[6 x i8]` to `[3 x [2 x i8]]`, i.e., NOT flattening multi-dimensional
inits from a scalar.
So only literals with overlapping (union) fields and an explicit
initializer initializing dominated non-alias union fields should still
have a mismatching anonymous type - i.e., very, very few cases.
Previously, the transitory state only needed and valid during
generation of the LLVM IR for the function body was conflated
with the general codegen metadata for the function declaration
in IrFunction.
There is further potential for cleanup regarding the use of
gIR->func() and so on all over the code base, but this is out
of scope of this commit, which is only concerned with those
IrFunction members moved to FuncGenState.
GitHub: Fixes#1661.