Analogous to ClassInfos, incl. normal linkage (external for non-
templates, weak_odr for templates).
This enables to get rid of frontend logic wrt. whether to add
TypeInfoStructDeclarations to a module's members tree - previously,
it was defined as linkonce_odr in the owning module and each referencing
module (unless speculative) - and related extra semantic and codegen for
the special member functions.
I've gone a bit further and moved the entire TypeInfo emission for LDC
to the codegen layer; no TypeInfoDeclarations are added to the module
members anymore. Whenever we need a TypeInfo symbol during codegen, it
is declared or defined, and we don't need to rely on brittle frontend
logic with speculative-ness complications.
This might slightly increase compilation speed due to less emitted
TypeInfos and functions (possibly less work for the linker too).
A slight drawback is that the job of stripping unused struct TypeInfos
is fully delegated to the linker, as the TypeInfo is guaranteed to end
up in the owning object file due to no linkonce_odr.
Another theoretical drawback is that the optimizer can definitely not
inline xtoHash/xopEquals/xopCmp/xtoString/xdtor[ti]/xpostblit function
pointer indirections in non-owning CUs without LTO (neither the pointers
nor the special member functions are defined anymore).
These (public) members are probably hardly used directly though, and
instead used by the virtual TypeInfo_Struct methods equals/compare/
getHash/destroy/postblit, which are exclusively defined in druntime's
object.o (incl. the TypeInfo_Struct vtable) and aren't cross-module-
inlined anyway (without LTO).
Re-emitting the struct TypeInfos (and optionally the special member
functions too) into each referencing CU could be handled in our codegen
layer, which should be much simpler and more robust than the upstream
scheme.
Fixing a regression in dmd-testsuite's compilable/test8543.d, where CTFE
changes seem not to consider such previous LDC-specific CastExp as lvalue
anymore.
LLVM already provides suited RAII helper types to restore the IRBuilder
state. [They sadly aren't movable, so I've had to wrap them in a
unique_ptr.]
While at it, also minimally revise debuginfo generation for functions.
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.
Whenever we need an IR function, we'd better make sure it exists. Handle
that in DtoCallee(), by invoking DtoDeclareFunction() by default,
instead of the previous DtoResolveFunction() + DtoCallee() combo.
DtoResolveFunction() usually declares the function, but somehow doesn't
for abstract and body-less functions.
Fixes#3490 by avoiding unnecessary extra key allocations for the literals cache etc.
Also gets rid of code duplication and improves IRState encapsulation.
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.
As the replacement most likely wouldn't work if the temporary lvalue was
a bitcast alloca, for example. We want to replace all usages of the
alloca to make sure all writes are redirected to the final lvalue.
Contracts are special nested functions, previously receiving the
aggregate `this` pointer as context ptr, as nothing except for `this`
can actually be captured from the original function (parameters are
passed explicitly).
If a contract features a nested function and that function accesses
`this`, it is captured from the original function, and the nested
function expects a regular context of depth 2.
By passing a pointer to the `this` pointer as context for contracts, it
can naturally be used directly as parent context in the contract.
This fixes newly extended runnable/testcontracts.d.
Bail out on unsupported vector ops (not checking the rhs type for binops
though) in the frontend instead of causing LLVM errors.
Also precompute the target's critical section size once at startup, like
DMD.
Functions, labels etc. aren't sized; respect that when coming across a SymOffExp (and checking whether we can elide a pointer cast to i8* for the GEP).
dlang/dmd#8359 introduces direct call expressions for struct methods
(which cannot be virtual anyway and are so always called directly).
Our previous code relied on the instance being a class. There are
multiple ways to fix this; I went with this one.
This fixes the std.conv unittests on Win64 with the more efficient
IndirectByvalRewrite. This code would segfault:
```
import std.typecons;
alias T = Tuple!(string, string, int);
void main()
{
T local;
local = T.init;
}
```
`T.init` represents a struct literal here (a D rvalue in memory) and is
newly forwarded directly by ref to the Tuple's `opAssign(auto ref
Tuple)` for high-level-by-value semantics.
The problem was that `emitStructLiteral()` would actually return a
DLValue to the global init symbol directly in some cases, i.e., a D
lvalue, instead of allocating a dedicated temporary and filling it with
a bitcopy.
Not all type declarations yet (e.g., some TypeInfo subtypes are still
accessed directly), but those already wrapped as LazyType in the
gen/runtime.cpp module (with check and proper error msg in case object.d
doesn't contain a required declaration).
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.
The dtors can be checked at compile-time; insert a runtime check for the
monitor before finalizing the stack-allocated class object via druntime
call.
See issue #2515.