-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework PathogenExtensions.cpp into a separate library. #2
Comments
… computed correctly. Turns out the root cause of the issues I was observing was the fact that in many places within LLVM uses the address of the fltSemantics instance to figure its identity. There's only a handful of fltSemantics instances and they're all statically allocated. This means that when there's multiple DLLs there's a set of fltSemantics instances for each DLL. We have multiple DLLs (the one that comes with ClangSharp and the one that holds PathogenExtensions) and we process data allocated in one with another, whoops. For whatever reason in certain scenarios the fltSemantics from the ClangSharp libclang were appearing in the APValue instances in libclang-pathogen. This problem will be properly fixed by #2 For now I am manually overriding the native library resolver to only resolve everything to libclang-pathogen.dll
This needs to happen sooner rather than later. I just spent all morning debugging weird behaviors in For now I've patched Biohazrd to override the DLL resolver in ClangSharp to load libclang-pathogen in place of its libclang. |
Looking into the issue a bit further, I'm actually not confident that refactoring things into a separate library will actually solve the issue permanently. Instead I think the proper solution is that we need to rework |
For the sake of posterity, I wanted to document the original issue here. CC @tannergooding: I don't have any reason to believe this is an issue in libClangSharp today, but it might be something you want to keep in mind since it's not a fun landmine to step on. (TL;DR: Linking to Clang libraries statically in one DLL and sharing data libclang from another DLL can be problematic.) I added functionality to ClangSharp.Pathogen that surfaces functionality provided by This result of this API is getting a union-like type
Some When you have multiple DLLs containing the Somewhere deep within Clang (didn't try to narrow things down) these Needless to say this was endlessly confusing and extremely problematic. (And was definitely not how I wanted to spend my morning yesterday.) |
… being loaded in the same process. See MochiLibraries/llvm-project#2 (comment) for details on this issue.
For reference, the number one issue I've hit is that both the consumed copy of libClang and the separate library (such as libClangSharp) need to match exactly. LLVM, in general, makes breaking changes almost every release and does not even have consistent type layout between the 4 default build configurations (debug, release, minsizerel, relwithdebinfo). In an ideal setup, libClang would take some changes to make it inherently more extensible, but the various issues I've logged haven't gotten any responses yet. |
I can definitely believe that. It seems to be a fickle library. The debug releases of LLVM don't even build properly on my machine. (Which makes debugging issues like this all the more annoying.) Besides this issue I've gotten lucky mixing my MSVC-built release library with yours so far, but I definitely want to move away from hopes and luck. (Especially since this issue wasn't caused by that exactly.)
I've been wondering how real that threat of "the internal API is unstable" was. Guess I'll have that to look forward to.
That's unfortunate to hear. The Clang API has so many powerful features that aren't accessible through libclang. |
… being loaded in the same process. See MochiLibraries/llvm-project#2 (comment) for details on this issue.
This wasn't even referring to the internal API, which I would naturally assume is prone to breaks. They break public surface area from release to release. The most common example is inserting new enum members between existing definitions, which shifts the constant value emitted for something like This can also happen with methods. For example I've also seen it happen with "value types" (types passed around by value, rather than by pointer or reference) in a past release which impacts compatibility for code compiled against one and consumed by another as field indexing ends up being different (something which C# doesn't normally have a problem with given it is jitted). |
"internal API" wasn't the right term here. I was referring to everything that isn't libclang.
Glad to know my hyper-paranoid enum asserts aren't for nothing. Thanks for the examples, it's helpful to know what sorts of issues to prepare for. |
ClangSharp.Pathogen's native runtime library (libclang-pathogen) now includes libClangSharp, which both makes it easier to build all of the native Clang-related components in one go and resolves any potential issues similar to MochiLibraries/llvm-project#2 (comment) by unifying all potential instances of Clang into a single DLL. Part of this involved formalizing the __HACK__InstallLibClangDllWorkaround method in TranslatedLibraryBuilder as LibClangSharpResolver. This new interface also adds the ability to easily override the native runtime library with a single method call (LibClangSharpResolver.OverrideNativeRuntime), which makes iterating on libclang-pathogen much easier. (Previously I did something very similar to this, but it was always quirky and annoying to get right in all situations.)
Closing this out as this ship has very sailed with the inline issues mentioned above and we've been shipping a single monolithic libclang+libClangSharp+Pathogen runtime for quite a while. |
Right now the Pathogen Extensions are built directly into libclang. This was done initially to make hacking on libclang easier, but I've since found that it's semi-necessary because we're using methods internal to libclang (such as
cxcursor::getCursorDecl
, which gets theDecl
hidden inside aCXCursor
.)This is not ideal because it means libclang-pathogen is huge since it contains all of libclang. It also means consumers of ClangSharp.Pathogen are shipping two copies of libclang.
We could eliminate the extra copy of libclang by blocking the libclang.runtime. package added by ClangSharp and substituting it for our own. Also I'd have to experiment to see if this is possible to do gracefully from our own NuGet package. In theory this should be fine since the libclang.runtime. packages are only updated on each LLVM release, and we wouldn't expect mixing and matching ClangSharp.Pathogen with different LLVM releases to work anyway.
libClangSharp works around this issue by copy+pasting the required functionality out of libclang: https://github.com/microsoft/ClangSharp/tree/2712e6b3ac30bb914ef99fdf66d7c38256a997ad/sources/libClangSharp
The text was updated successfully, but these errors were encountered: