|
46 | 46 | #include "llvm/ADT/StringRef.h"
|
47 | 47 | #include "llvm/Demangle/Demangle.h"
|
48 | 48 | #include "llvm/Support/Casting.h"
|
| 49 | +#include "llvm/Support/CommandLine.h" |
49 | 50 | #include "llvm/Support/Debug.h"
|
50 | 51 | #include "llvm/Support/raw_os_ostream.h"
|
51 | 52 |
|
52 | 53 | #include <algorithm>
|
| 54 | +#include <cassert> |
53 | 55 | #include <iterator>
|
54 | 56 | #include <map>
|
| 57 | +#include <memory> |
55 | 58 | #include <set>
|
56 | 59 | #include <sstream>
|
| 60 | +#include <stack> |
57 | 61 | #include <string>
|
58 | 62 |
|
59 | 63 | // Stream redirect.
|
|
71 | 75 | #include <unistd.h>
|
72 | 76 | #endif // WIN32
|
73 | 77 |
|
74 |
| -#include <stack> |
75 |
| - |
76 | 78 | namespace Cpp {
|
77 | 79 |
|
78 | 80 | using namespace clang;
|
79 | 81 | using namespace llvm;
|
80 | 82 | using namespace std;
|
81 | 83 |
|
82 |
| -// Flag to indicate ownership when an external interpreter instance is used. |
83 |
| -static bool OwningSInterpreter = true; |
84 |
| -static compat::Interpreter* sInterpreter = nullptr; |
85 |
| -// Valgrind complains about __cxa_pure_virtual called when deleting |
86 |
| -// llvm::SectionMemoryManager::~SectionMemoryManager as part of the dtor chain |
87 |
| -// of the Interpreter. |
88 |
| -// This might fix the issue https://reviews.llvm.org/D107087 |
89 |
| -// FIXME: For now we just leak the Interpreter. |
90 |
| -struct InterpDeleter { |
91 |
| - ~InterpDeleter() = default; |
92 |
| -} Deleter; |
| 84 | +struct InterpreterInfo { |
| 85 | + compat::Interpreter* Interpreter = nullptr; |
| 86 | + bool isOwned = true; |
| 87 | + |
| 88 | + // Valgrind complains about __cxa_pure_virtual called when deleting |
| 89 | + // llvm::SectionMemoryManager::~SectionMemoryManager as part of the dtor |
| 90 | + // chain of the Interpreter. |
| 91 | + // This might fix the issue https://reviews.llvm.org/D107087 |
| 92 | + // FIXME: For now we just leak the Interpreter. |
| 93 | + ~InterpreterInfo() = default; |
| 94 | +}; |
| 95 | +static llvm::SmallVector<InterpreterInfo, 8> sInterpreters; |
93 | 96 |
|
94 | 97 | static compat::Interpreter& getInterp() {
|
95 |
| - assert(sInterpreter && |
| 98 | + assert(!sInterpreters.empty() && |
96 | 99 | "Interpreter instance must be set before calling this!");
|
97 |
| - return *sInterpreter; |
| 100 | + return *sInterpreters.back().Interpreter; |
98 | 101 | }
|
99 | 102 | static clang::Sema& getSema() { return getInterp().getCI()->getSema(); }
|
100 | 103 | static clang::ASTContext& getASTContext() { return getSema().getASTContext(); }
|
@@ -2920,19 +2923,54 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
|
2920 | 2923 | Args[NumArgs + 1] = nullptr;
|
2921 | 2924 | llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
|
2922 | 2925 | }
|
2923 |
| - // FIXME: Enable this assert once we figure out how to fix the multiple |
2924 |
| - // calls to CreateInterpreter. |
2925 |
| - // assert(!sInterpreter && "Interpreter already set."); |
2926 |
| - sInterpreter = I; |
| 2926 | + |
| 2927 | + sInterpreters.push_back({I, /*isOwned=*/true}); |
| 2928 | + |
2927 | 2929 | return I;
|
2928 | 2930 | }
|
2929 | 2931 |
|
2930 |
| -TInterp_t GetInterpreter() { return sInterpreter; } |
| 2932 | +bool DeleteInterpreter(TInterp_t I /*=nullptr*/) { |
| 2933 | + if (!I) { |
| 2934 | + sInterpreters.pop_back(); |
| 2935 | + return true; |
| 2936 | + } |
| 2937 | + |
| 2938 | + auto* found = |
| 2939 | + std::find_if(sInterpreters.begin(), sInterpreters.end(), |
| 2940 | + [&I](const auto& Info) { return Info.Interpreter == I; }); |
| 2941 | + if (found == sInterpreters.end()) |
| 2942 | + return false; // failure |
| 2943 | + |
| 2944 | + sInterpreters.erase(found); |
| 2945 | + return true; |
| 2946 | +} |
| 2947 | + |
| 2948 | +bool ActivateInterpreter(TInterp_t I) { |
| 2949 | + if (!I) |
| 2950 | + return false; |
| 2951 | + |
| 2952 | + auto* found = |
| 2953 | + std::find_if(sInterpreters.begin(), sInterpreters.end(), |
| 2954 | + [&I](const auto& Info) { return Info.Interpreter == I; }); |
| 2955 | + if (found == sInterpreters.end()) |
| 2956 | + return false; |
| 2957 | + |
| 2958 | + if (std::next(found) != sInterpreters.end()) // if not already last element. |
| 2959 | + std::rotate(found, found + 1, sInterpreters.end()); |
| 2960 | + |
| 2961 | + return true; // success |
| 2962 | +} |
| 2963 | + |
| 2964 | +TInterp_t GetInterpreter() { |
| 2965 | + if (sInterpreters.empty()) |
| 2966 | + return nullptr; |
| 2967 | + return sInterpreters.back().Interpreter; |
| 2968 | +} |
2931 | 2969 |
|
2932 | 2970 | void UseExternalInterpreter(TInterp_t I) {
|
2933 |
| - assert(!sInterpreter && "sInterpreter already in use!"); |
2934 |
| - sInterpreter = static_cast<compat::Interpreter*>(I); |
2935 |
| - OwningSInterpreter = false; |
| 2971 | + assert(sInterpreters.empty() && "sInterpreter already in use!"); |
| 2972 | + sInterpreters.push_back( |
| 2973 | + {static_cast<compat::Interpreter*>(I), /*isOwned=*/false}); |
2936 | 2974 | }
|
2937 | 2975 |
|
2938 | 2976 | void AddSearchPath(const char* dir, bool isUser, bool prepend) {
|
|
0 commit comments