-
-
Notifications
You must be signed in to change notification settings - Fork 267
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
Add support for Semantic Analysis plugins #4430
Conversation
The plugin's runSemanticAnalysis(Module) function is called for each module, after all other semantic analysis steps (also after DCompute SemA).
I'm stuck and don't know how to get this to work on Linux. Somehow some symbols are not exported on Linux, even when passing
|
Oh, an instantiated symbol. For C++, this would require extra stuff too (an 'explicit instantiation'): https://discourse.llvm.org/t/clang-and-c-exporting-member-function-template-from-library-using-attribute-visibility-default/54914/2 |
I'll have a look, but the symbol is already instantiated and emitted into the object file |
If I glanced over https://en.cppreference.com/w/cpp/language/function_template#Explicit_instantiation correctly, my understanding is that an explicit instantiation in C++ (nothing we'd have in D AFAIK) is a total special thing, probably getting an |
I found the problem using
|
And there was a further problem with "weak hidden" symbols in |
…ing -fvisibility-inlines-hidden
@kinke For ease of use, I think that we should actually ship the DMD frontend source. That is: we should make it part of the install package. DMD also does this. We cannot put it in the |
I'm not convinced wrt. shipping the frontend sources - is there any other usage except for building such plugins? I guess plugins are going to be extremely niche anyway, not working on Windows etc. |
OK. The use case is kind-of niche indeed. By the way, the reason I want this is:
|
I have added a Edit: investigating why things no longer work on the macOS arm64 cirrus testers... (the complicated test works, but the simple test doesn't..?!) |
@kinke the PR is ready now. |
cmake/Modules/BuildDExecutable.cmake
Outdated
@@ -40,7 +40,8 @@ function(build_d_executable target_name output_exe d_src_files compiler_args lin | |||
# Compile all D modules to a single object. | |||
set(object_file ${PROJECT_BINARY_DIR}/obj/${target_name}${CMAKE_CXX_OUTPUT_EXTENSION}) | |||
# Default to -linkonce-templates with LDMD host compiler, to speed-up optimization. | |||
if("${D_COMPILER_ID}" STREQUAL "LDMD") | |||
# Note: for plugin support we need the symbols to be global, don't use -linkonce-templates. | |||
if("${D_COMPILER_ID}" STREQUAL "LDMD" AND NOT LDC_ENABLE_PLUGINS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually only required for ldc2
, no other binary. The dependency on foreign-defined LDC_ENABLE_PLUGINS
would ideally be added to the comment starting in line 21.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed it so it only removes the flag for ldc2. (zooming out, perhaps it's not so nice that this method adds flags, should be added elsewhere I feel)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option would be to compile the plugins with either -linkonce-templates
or at least -allinst
- all instantiated stuff should be defined in the plugin itself then.
} | ||
|
||
//--- testcase.d | ||
// CHECK: testcase.d([[@LINE+1]]): Warning: It works! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So does the split-file
utility keep the original line numbers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, with --leading-lines
# For plugins, we shouldn't apply this flag because it hides the inline methods of e.g. Visitor. | ||
check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG) | ||
if (${SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG} AND NOT LDC_ENABLE_PLUGINS) | ||
append("-fvisibility-inlines-hidden" LDC_CXXFLAGS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The macOS builds (both x64 and arm64) now produce something like ~500 warnings:
ld: warning: direct access in function 'llvm::cl::AddLiteralOption(llvm::cl::Option&, llvm::StringRef)' from file '/Users/runner/work/ldc/llvm/lib/libLLVMSupport.a(CommandLine.cpp.o)' to global weak symbol 'llvm::object_deleter<llvm::cl::SubCommand>::call(void*)' from file 'utils/CMakeFiles/split-file.dir/split-file.cpp.o' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how the macOS CI testers are different from my macOS..... I don't see any of this, and also did not need to remove this flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's related to how LLVM was built. The CI build in our llvm-project
fork is pretty standard though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's see if I can only remove this flag for linux builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it worked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UNIX
includes APPLE
; I've pushed an according commit really testing macOS with that flag.
"--d-version=IN_LLVM", | ||
"-J" ~ buildPath(config.ldcSourceDir, "dmd", "res"), | ||
"--shared", | ||
"--defaultlib=", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, so do the plugins depend on statically-linked druntime+Phobos being exported from ldc2
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how well that works, both in terms of different host compilers for plugin/ldc2
, and more complex plugins with TLS data, module ctors, GC usage etc. We normally require all D binaries of some process to be linked against shared druntime/Phobos...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The plugin should ideally be built by the same compiler that it will be used with. Any other compiler might give issues due to ABI differences. For the simple plugin in the test, apparently LDC 1.30 is a good enough match with LDC master, but that might change.
I intentionally do not link with the standard library, because (1) it caused dynamic load problems when the plugin was linked with stdlib (macos has statically linked stdlib), and (2) ldc2 exports stdlib symbols (shared or static druntime), which is good enough for now. Module ctors are probably not supported this way, but those are easily worked around. Having some plugin support is already so much better than having none at all!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just saying that one might quite easily end up with hard-to-troubleshoot issues, as the plugin DSO isn't registered with druntime etc. The GC being disabled by default probably helps though wrt. unscanned static data ranges etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, so if we want to support plugins, we must link ldc2 with shared stdlib. Is there another option of manually letting ldc2 call the module registration upon loading a plugin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's a way around the shared libs; static druntime isn't able to handle multiple D binaries AFAIK. Plus the current official packages even have LTO'd druntime+Phobos, so hopefully excluding most unused parts, which a plugin might happen to need.
We currently link druntime+Phobos statically into each bundled D executable (incl. ldc-build-plugin
etc.) for the official packages, so switching to the bundled shared libs could be somewhat nicer wrt. bundle size anyway. We'd have to take care of the rpath though, to keep the package portable etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fully agree with not making the shared lib change in this release, let's figure that out in new beta later :)
I'll need to write up a blog post about the plugin stuff, and then list all the shortcomings right now (due to no module init). I think it is still very very useful with that limitation.
Note that I plan on releasing a v1.34 beta soon (next weekend or so) - #4440 is basically ready, a single importC dmd-testsuite test wrt. |
Hmm, possibly due to sharing the same temporary |
Reminder for ourselves: the visitor_example.d plugin will stop working after this fix for tuples: dlang/dmd#15351 . We can then change the plugin to trigger on some other AST thing. |
Add support for Semantic Analysis plugins
This adds support for semantic analysis plugins, that receive the frontend modules ASTs.
The plugin's runSemanticAnalysis(Module) function is called for each module, after all other semantic analysis steps (also after DCompute SemA).
TODOI'm not going to implement these things here:ldc-build-runtime
to build plugins...Maybe, but let's not complicate things for now. It is not that hard to compile a plugin well, and we should document that.tool is now part of the PR