The first member of the type info structs/objects is a pointer to the vtable of the type info class. If the standard C++ library that provides this vtable is linked as a DLL, this field of the struct needs to be initialized differently.
If statically initializing a variable with a pointer to a dllimported variable, that initalization can't be done as normal static initialization, since the address of the variable only will be available at runtime via the IAT.
For a struct/class with dllimported members, clang skips the normal static initalization and instead produces a constructor that will do the equivalent initialization at runtime.
For type info objects that are instantiated in ItaniumCXXABI, it's not enough to just set the dllimport attribute on the vtable pointer to invoke the existing generation of a constructor in CodeGenModule::EmitCXXGlobalVarDeclInitFunc in CGDeclCXX.cpp. Instead ItaniumCXXABI needs to manually produce the equivalent code for the runtime initialization as well, without a VarDecl for this struct.
To enable this behaviour, a new compiler flag, -fcxx-dll, is added, that can be set when building code that expects to be linking to the standard C++ library as a DLL.
This hasn't been an issue before, if linking with GNU ld, since GNU ld automatically can handle references to variables that weren't marked as dllimport during compilation, if the undefined references are found in a DLL import library. Since lld doesn't support this behaviour, we need to properly use dllimport mechanisms even for this field.
The actual implementation isn't very elegant yet (it's only a proof of concept so far) - directions on how to do it better are welcome.
I was surprised to discover that this probably works. I'd forgotten that mingw rolls its own .ctors section instead of reusing some of the .CRT$XCU machinery. This just makes me feel like we're layering the levels of paper deeper, and we might be better off implementing the mingw relocation thingy you mentioned.