Skip to content
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

[llvm-driver] Fix usage of InitLLVM on Windows #76306

Merged
merged 2 commits into from
Jan 12, 2024

Conversation

aganea
Copy link
Member

@aganea aganea commented Dec 24, 2023

Previously, some tools such as clang or lld which require strict order for certain command-line options, such as clang -cc1 or lld -flavor, would not longer work on Windows, when these tools were linked as part of llvm-driver. This was caused by InitLLVM which was part of the *_main() function of these tools, which in turn calls windows::GetCommandLineArguments. That function completly replaces argc/argv by new UTF-8 contents, so any ajustements to argc/argv made by llvm-driver prior to calling these tools was reset.

InitLLVM is now called by the llvm-driver. Any tool that participates in (or is part of) the llvm-driver doesn't call InitLLVM anymore.

Previously, some tools such as `clang` or `lld` which require strict order for certain command-line options, such as `clang -cc1` or `lld -flavor` would not long work on Windows, when these tools were linked as part of `llvm-driver`. This was caused by `InitLLVM` which was part of the `main()` function of these tools, which in turn calls `windows::GetCommandLineArguments`. This function completly replaces argc/argv by new UTF-8 contents, so any ajustements to argc/argv made by `llvm-driver` prior to calling these tools would be reset.

We now call `InitLLVM` as part of the `llvm-driver`. Any further usages to `InitLLVM` on the stack, after the first call in the process would have no effect. In the same way, the last `InitLLVM` on the stack will clear the `ManagedStatics` as usual.
@llvmbot llvmbot added cmake Build system in general and CMake in particular llvm:support labels Dec 24, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 24, 2023

@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-lld-wasm
@llvm/pr-subscribers-pgo
@llvm/pr-subscribers-lld-macho
@llvm/pr-subscribers-lld-coff
@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-llvm-support

Author: Alexandre Ganea (aganea)

Changes

Previously, some tools such as clang or lld which require strict order for certain command-line options, such as clang -cc1 or lld -flavor would not long work on Windows, when these tools were linked as part of llvm-driver. This was caused by InitLLVM which was part of the main() function of these tools, which in turn calls windows::GetCommandLineArguments. This function completly replaces argc/argv by new UTF-8 contents, so any ajustements to argc/argv made by llvm-driver prior to calling these tools would be reset.

We now call InitLLVM as part of the llvm-driver. Any further usages to InitLLVM on the stack, after the first call in the process would have no effect. In the same way, the last InitLLVM on the stack will clear the ManagedStatics as usual.


Full diff: https://github.com/llvm/llvm-project/pull/76306.diff

3 Files Affected:

  • (modified) llvm/cmake/modules/llvm-driver-template.cpp.in (+2)
  • (modified) llvm/lib/Support/InitLLVM.cpp (+6)
  • (modified) llvm/tools/llvm-driver/llvm-driver.cpp (+5-1)
diff --git a/llvm/cmake/modules/llvm-driver-template.cpp.in b/llvm/cmake/modules/llvm-driver-template.cpp.in
index 16c4fb34714638..71aca6cd140cb5 100644
--- a/llvm/cmake/modules/llvm-driver-template.cpp.in
+++ b/llvm/cmake/modules/llvm-driver-template.cpp.in
@@ -8,9 +8,11 @@
 
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
 
 int @TOOL_NAME@_main(int argc, char **, const llvm::ToolContext &);
 
 int main(int argc, char **argv) {
+  llvm::InitLLVM X(argc, argv);
   return @TOOL_NAME@_main(argc, argv, {argv[0], nullptr, false});
 }
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 7f475f42f3cb81..2a2e6c254c795a 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -36,8 +36,12 @@ void CleanupStdHandles(void *Cookie) {
 using namespace llvm;
 using namespace llvm::sys;
 
+static std::atomic<unsigned> UsageCount{0};
+
 InitLLVM::InitLLVM(int &Argc, const char **&Argv,
                    bool InstallPipeSignalExitHandler) {
+  if (UsageCount++)
+    return;
 #ifdef __MVS__
   // Bring stdin/stdout/stderr into a known state.
   sys::AddSignalHandler(CleanupStdHandles, nullptr);
@@ -94,6 +98,8 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
 }
 
 InitLLVM::~InitLLVM() {
+  if (--UsageCount)
+    return;
 #ifdef __MVS__
   CleanupStdHandles(nullptr);
 #endif
diff --git a/llvm/tools/llvm-driver/llvm-driver.cpp b/llvm/tools/llvm-driver/llvm-driver.cpp
index a0f1ca831d93b6..53a8b9357e3780 100644
--- a/llvm/tools/llvm-driver/llvm-driver.cpp
+++ b/llvm/tools/llvm-driver/llvm-driver.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/WithColor.h"
@@ -79,4 +80,7 @@ static int findTool(int Argc, char **Argv, const char *Argv0) {
   return 1;
 }
 
-int main(int Argc, char **Argv) { return findTool(Argc, Argv, Argv[0]); }
+int main(int Argc, char **Argv) {
+  llvm::InitLLVM X(Argc, Argv);
+  return findTool(Argc, Argv, Argv[0]);
+}

@aganea aganea changed the title [llvm-driver] Fix tool re-entrance on Windows. [llvm-driver] Fix usage of InitLLVM on Windows Dec 24, 2023
Copy link
Contributor

@abhina-sree abhina-sree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@MaskRay
Copy link
Member

MaskRay commented Dec 29, 2023

I hope that we do not add UsageCount to allow repeated uses of InitLLVM. Can a macro guard be used instead?

@aganea
Copy link
Member Author

aganea commented Dec 29, 2023

I hope that we do not add UsageCount to allow repeated uses of InitLLVM. Can a macro guard be used instead?

I can also remove usages of InitLLVM in all the tools embedded by llvm-driver and only keep it in the topmost main().

@llvmbot llvmbot added clang Clang issues not falling into any other category lld debuginfo lld:MachO lld:ELF lld:COFF lld:wasm PGO Profile Guided Optimizations llvm:binary-utilities labels Dec 31, 2023
@aganea
Copy link
Member Author

aganea commented Dec 31, 2023

@MaskRay Can you please take another look?

@llvm-beanz
Copy link
Collaborator

@aganea, this ends up being a nice way to collapse down a tiny bit of shared tool boilerplate. Thank you!

This LGTM, but let's make sure @MaskRay is happy too.

@MaskRay
Copy link
Member

MaskRay commented Jan 8, 2024

InitLLVM which was part of the main() function of these tools

*_main functions?

@aganea aganea merged commit 3c6f47d into llvm:main Jan 12, 2024
13 checks passed
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
Previously, some tools such as `clang` or `lld` which require strict
order for certain command-line options, such as `clang -cc1` or `lld
-flavor`, would not longer work on Windows, when these tools were linked
as part of `llvm-driver`. This was caused by `InitLLVM` which was part
of the `*_main()` function of these tools, which in turn calls
`windows::GetCommandLineArguments`. That function completly replaces
argc/argv by new UTF-8 contents, so any ajustements to argc/argv made by
`llvm-driver` prior to calling these tools was reset.

`InitLLVM` is now called by the `llvm-driver`. Any tool that
participates in (or is part of) the `llvm-driver` doesn't call
`InitLLVM` anymore.
@aganea aganea deleted the fix_llvm-driver_windows branch February 8, 2024 15:28
@DimitryAndric
Copy link
Collaborator

Maybe I'm doing something wrong, but after this commit (and its merge to 18.x) I don't see to get stack traces from clang anymore after assertions? How is this supposed to work?

@jrtc27
Copy link
Collaborator

jrtc27 commented Feb 10, 2024

llvm-driver-template.cpp.in is what should be generating the real main for Clang (and call clang_main), and that was patched in this commit.

@DimitryAndric
Copy link
Collaborator

Ah that was my error, I hadn't used the regenerated *-driver.cpp files. These indeed should contain the InitLLVM call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category cmake Build system in general and CMake in particular debuginfo lld:COFF lld:ELF lld:MachO lld:wasm lld llvm:binary-utilities llvm:support PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants