From e1b178e3244b5653c234064918aef5152162f44c Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Thu, 24 Oct 2024 06:07:13 +0100 Subject: [PATCH] [llvm] Support llvm::Any across shared libraries on windows (#108051) This is part of the effort to support for enabling plugins on windows by adding better support for building llvm as a DLL. The export macros used here were added in #96630 Since shared library symbols aren't deduplicated across multiple libraries on windows like Linux we have to manually explicitly import and export `Any::TypeId` template instantiations for the uses of `llvm::Any` in the LLVM codebase to support LLVM Windows shared library builds. This change ensures that external code, including LLVM's own tests, can use PassManager callbacks when LLVM is built as a DLL. I also removed the only use of llvm::Any for LoopNest that only existed in debug code and there also doesn't seem to be any code creating `Any` --- .../clang/Analysis/FlowSensitive/NoopLattice.h | 10 ++++++++++ .../FlowSensitive/TypeErasedDataflowAnalysis.cpp | 15 +++++++++++++++ llvm/include/llvm/Analysis/LazyCallGraph.h | 3 +++ llvm/include/llvm/IR/PassInstrumentation.h | 10 +++++++++- llvm/lib/Analysis/LazyCallGraph.cpp | 2 ++ llvm/lib/IR/PassInstrumentation.cpp | 4 ++++ llvm/lib/Transforms/Scalar/LoopPassManager.cpp | 5 +---- llvm/unittests/IR/PassBuilderCallbacksTest.cpp | 2 -- 8 files changed, 44 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/NoopLattice.h b/clang/include/clang/Analysis/FlowSensitive/NoopLattice.h index 01921932811198..6cc00680eab791 100644 --- a/clang/include/clang/Analysis/FlowSensitive/NoopLattice.h +++ b/clang/include/clang/Analysis/FlowSensitive/NoopLattice.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H #include "clang/Analysis/FlowSensitive/DataflowLattice.h" +#include "llvm/ADT/Any.h" #include namespace clang { @@ -38,4 +39,13 @@ inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) { } // namespace dataflow } // namespace clang +namespace llvm { +// This needs to be exported for ClangAnalysisFlowSensitiveTests so any_cast +// uses the correct address of Any::TypeId from the clang shared library instead +// of creating one in the test executable. when building with +// CLANG_LINK_CLANG_DYLIB +extern template struct CLANG_TEMPLATE_ABI + Any::TypeId; +}; // namespace llvm + #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 8afd18b315d286..32b3886439495f 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -30,6 +30,7 @@ #include "clang/Analysis/FlowSensitive/Transfer.h" #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/Value.h" +#include "clang/Support/Compiler.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" @@ -37,6 +38,20 @@ #define DEBUG_TYPE "clang-dataflow" +namespace clang { +namespace dataflow { +class NoopLattice; +} +} // namespace clang + +namespace llvm { +// This needs to be exported for ClangAnalysisFlowSensitiveTests so any_cast +// uses the correct address of Any::TypeId from the clang shared library instead +// of creating one in the test executable. when building with +// CLANG_LINK_CLANG_DYLIB +template struct CLANG_EXPORT_TEMPLATE Any::TypeId; +} // namespace llvm + namespace clang { namespace dataflow { diff --git a/llvm/include/llvm/Analysis/LazyCallGraph.h b/llvm/include/llvm/Analysis/LazyCallGraph.h index e7fd18967d9bed..289e9c3990bcc6 100644 --- a/llvm/include/llvm/Analysis/LazyCallGraph.h +++ b/llvm/include/llvm/Analysis/LazyCallGraph.h @@ -34,6 +34,7 @@ #ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H #define LLVM_ANALYSIS_LAZYCALLGRAPH_H +#include "llvm/ADT/Any.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -1308,6 +1309,8 @@ class LazyCallGraphDOTPrinterPass static bool isRequired() { return true; } }; +extern template struct LLVM_TEMPLATE_ABI + Any::TypeId; } // end namespace llvm #endif // LLVM_ANALYSIS_LAZYCALLGRAPH_H diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h index 9fcc2d5957a30c..45ee372e7959d1 100644 --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -50,10 +50,11 @@ #define LLVM_IR_PASSINSTRUMENTATION_H #include "llvm/ADT/Any.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/IR/PassManager.h" +#include "llvm/Support/Compiler.h" #include #include @@ -61,6 +62,13 @@ namespace llvm { class PreservedAnalyses; class StringRef; +class Module; +class Loop; +class Function; + +extern template struct LLVM_TEMPLATE_ABI Any::TypeId; +extern template struct LLVM_TEMPLATE_ABI Any::TypeId; +extern template struct LLVM_TEMPLATE_ABI Any::TypeId; /// This class manages callbacks registration, as well as provides a way for /// PassInstrumentation to pass control to the registered callbacks. diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp index e6bf8c9cbb289f..5aa36bfc36d468 100644 --- a/llvm/lib/Analysis/LazyCallGraph.cpp +++ b/llvm/lib/Analysis/LazyCallGraph.cpp @@ -37,6 +37,8 @@ using namespace llvm; #define DEBUG_TYPE "lcg" +template struct LLVM_EXPORT_TEMPLATE Any::TypeId; + void LazyCallGraph::EdgeSequence::insertEdgeInternal(Node &TargetN, Edge::Kind EK) { EdgeIndexMap.try_emplace(&TargetN, Edges.size()); diff --git a/llvm/lib/IR/PassInstrumentation.cpp b/llvm/lib/IR/PassInstrumentation.cpp index 0c4e7698d9fa87..94ad124a6c770a 100644 --- a/llvm/lib/IR/PassInstrumentation.cpp +++ b/llvm/lib/IR/PassInstrumentation.cpp @@ -17,6 +17,10 @@ namespace llvm { +template struct LLVM_EXPORT_TEMPLATE Any::TypeId; +template struct LLVM_EXPORT_TEMPLATE Any::TypeId; +template struct LLVM_EXPORT_TEMPLATE Any::TypeId; + void PassInstrumentationCallbacks::addClassToPassName(StringRef ClassName, StringRef PassName) { ClassToPassName.try_emplace(ClassName, PassName.str()); diff --git a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp index 5ef25c21162fe2..d3bcfb8cc64044 100644 --- a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -269,12 +269,9 @@ PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F, PI.pushBeforeNonSkippedPassCallback([&LAR, &LI](StringRef PassID, Any IR) { if (isSpecialPass(PassID, {"PassManager"})) return; - assert(llvm::any_cast(&IR) || - llvm::any_cast(&IR)); + assert(llvm::any_cast(&IR)); const Loop **LPtr = llvm::any_cast(&IR); const Loop *L = LPtr ? *LPtr : nullptr; - if (!L) - L = &llvm::any_cast(IR)->getOutermostLoop(); assert(L && "Loop should be valid for printing"); // Verify the loop structure and LCSSA form before visiting the loop. diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp index 6230aed7b7119b..9aad6e3ca91255 100644 --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -298,8 +298,6 @@ template <> std::string getName(const Any &WrappedIR) { return (*F)->getName().str(); if (const auto *const *L = llvm::any_cast(&WrappedIR)) return (*L)->getName().str(); - if (const auto *const *L = llvm::any_cast(&WrappedIR)) - return (*L)->getName().str(); if (const auto *const *C = llvm::any_cast(&WrappedIR)) return (*C)->getName();