|
64 | 64 | #include "llvm/Support/FileSystem.h" |
65 | 65 | #include "llvm/Support/ManagedStatic.h" |
66 | 66 | #include "llvm/Support/Path.h" |
| 67 | +#include "llvm/Support/TargetSelect.h" |
67 | 68 | #include "llvm/Support/raw_ostream.h" |
68 | 69 | #include "llvm/TargetParser/Host.h" |
69 | 70 | #include "llvm/TargetParser/Triple.h" |
@@ -162,15 +163,85 @@ struct InterpreterInfo { |
162 | 163 | InterpreterInfo& operator=(const InterpreterInfo&) = delete; |
163 | 164 | }; |
164 | 165 |
|
165 | | -// std::deque avoids relocations and calling the dtor of InterpreterInfo. |
166 | | -static llvm::ManagedStatic<std::deque<InterpreterInfo>> sInterpreters; |
| 166 | +// Function-static storage for interpreters |
| 167 | +static std::deque<InterpreterInfo>& GetInterpreters() { |
| 168 | + static llvm::ManagedStatic<std::deque<InterpreterInfo>> sInterpreters; |
| 169 | + static bool ProcessInitialized = false; |
| 170 | + |
| 171 | + if (!ProcessInitialized) { |
| 172 | + // Initialize all targets (required for device offloading) |
| 173 | + llvm::InitializeAllTargetInfos(); |
| 174 | + llvm::InitializeAllTargets(); |
| 175 | + llvm::InitializeAllTargetMCs(); |
| 176 | + llvm::InitializeAllAsmParsers(); |
| 177 | + llvm::InitializeAllAsmPrinters(); |
| 178 | + ProcessInitialized = true; |
| 179 | + } |
| 180 | + |
| 181 | + return *sInterpreters; |
| 182 | +} |
| 183 | + |
| 184 | +static void RegisterInterpreter(compat::Interpreter* I, bool Owned) { |
| 185 | + std::deque<InterpreterInfo>& Interps = GetInterpreters(); |
| 186 | + Interps.emplace_back(I, Owned); |
| 187 | +} |
167 | 188 |
|
168 | 189 | static compat::Interpreter& getInterp(TInterp_t I = nullptr) { |
169 | 190 | if (I) |
170 | 191 | return *static_cast<compat::Interpreter*>(I); |
171 | | - assert(!sInterpreters->empty() && |
| 192 | + auto& Interps = GetInterpreters(); |
| 193 | + assert(!Interps.empty() && |
172 | 194 | "Interpreter instance must be set before calling this!"); |
173 | | - return *sInterpreters->back().Interpreter; |
| 195 | + return *Interps.back().Interpreter; |
| 196 | +} |
| 197 | + |
| 198 | +TInterp_t GetInterpreter() { |
| 199 | + std::deque<InterpreterInfo>& Interps = GetInterpreters(); |
| 200 | + if (Interps.empty()) |
| 201 | + return nullptr; |
| 202 | + return Interps.back().Interpreter; |
| 203 | +} |
| 204 | + |
| 205 | +void UseExternalInterpreter(TInterp_t I) { |
| 206 | + assert(GetInterpreters().empty() && "sInterpreter already in use!"); |
| 207 | + RegisterInterpreter(static_cast<compat::Interpreter*>(I), /*Owned=*/false); |
| 208 | +} |
| 209 | + |
| 210 | +bool ActivateInterpreter(TInterp_t I) { |
| 211 | + if (!I) |
| 212 | + return false; |
| 213 | + |
| 214 | + std::deque<InterpreterInfo>& Interps = GetInterpreters(); |
| 215 | + auto found = |
| 216 | + std::find_if(Interps.begin(), Interps.end(), |
| 217 | + [&I](const auto& Info) { return Info.Interpreter == I; }); |
| 218 | + if (found == Interps.end()) |
| 219 | + return false; |
| 220 | + |
| 221 | + if (std::next(found) != Interps.end()) // if not already last element. |
| 222 | + std::rotate(found, found + 1, Interps.end()); |
| 223 | + |
| 224 | + return true; // success |
| 225 | +} |
| 226 | + |
| 227 | +bool DeleteInterpreter(TInterp_t I /*=nullptr*/) { |
| 228 | + std::deque<InterpreterInfo>& Interps = GetInterpreters(); |
| 229 | + if (Interps.empty()) |
| 230 | + return false; |
| 231 | + |
| 232 | + if (!I) { |
| 233 | + Interps.pop_back(); // Triggers ~InterpreterInfo() and potential delete |
| 234 | + return true; |
| 235 | + } |
| 236 | + |
| 237 | + auto found = |
| 238 | + std::find_if(Interps.begin(), Interps.end(), |
| 239 | + [&I](const auto& Info) { return Info.Interpreter == I; }); |
| 240 | + if (found == Interps.end()) |
| 241 | + return false; // failure |
| 242 | + |
| 243 | + Interps.erase(found); |
| 244 | + return true; |
174 | 245 | } |
175 | 246 |
|
176 | 247 | static clang::Sema& getSema() { return getInterp().getCI()->getSema(); } |
@@ -3388,6 +3459,9 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/, |
3388 | 3459 | std::back_inserter(ClingArgv), |
3389 | 3460 | [&](const std::string& str) { return str.c_str(); }); |
3390 | 3461 |
|
| 3462 | + // Force global process initialization. |
| 3463 | + (void)GetInterpreters(); |
| 3464 | + |
3391 | 3465 | #ifdef CPPINTEROP_USE_CLING |
3392 | 3466 | auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); |
3393 | 3467 | #else |
@@ -3430,7 +3504,7 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/, |
3430 | 3504 | )"); |
3431 | 3505 | } |
3432 | 3506 |
|
3433 | | - sInterpreters->emplace_back(I, /*Owned=*/true); |
| 3507 | + RegisterInterpreter(I, /*Owned=*/true); |
3434 | 3508 |
|
3435 | 3509 | // Define runtime symbols in the JIT dylib for clang-repl |
3436 | 3510 | #if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) |
@@ -3462,44 +3536,6 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/, |
3462 | 3536 | return I; |
3463 | 3537 | } |
3464 | 3538 |
|
3465 | | -bool DeleteInterpreter(TInterp_t I /*=nullptr*/) { |
3466 | | - if (!I) { |
3467 | | - sInterpreters->pop_back(); |
3468 | | - return true; |
3469 | | - } |
3470 | | - |
3471 | | - auto found = |
3472 | | - std::find_if(sInterpreters->begin(), sInterpreters->end(), |
3473 | | - [&I](const auto& Info) { return Info.Interpreter == I; }); |
3474 | | - if (found == sInterpreters->end()) |
3475 | | - return false; // failure |
3476 | | - |
3477 | | - sInterpreters->erase(found); |
3478 | | - return true; |
3479 | | -} |
3480 | | - |
3481 | | -bool ActivateInterpreter(TInterp_t I) { |
3482 | | - if (!I) |
3483 | | - return false; |
3484 | | - |
3485 | | - auto found = |
3486 | | - std::find_if(sInterpreters->begin(), sInterpreters->end(), |
3487 | | - [&I](const auto& Info) { return Info.Interpreter == I; }); |
3488 | | - if (found == sInterpreters->end()) |
3489 | | - return false; |
3490 | | - |
3491 | | - if (std::next(found) != sInterpreters->end()) // if not already last element. |
3492 | | - std::rotate(found, found + 1, sInterpreters->end()); |
3493 | | - |
3494 | | - return true; // success |
3495 | | -} |
3496 | | - |
3497 | | -TInterp_t GetInterpreter() { |
3498 | | - if (sInterpreters->empty()) |
3499 | | - return nullptr; |
3500 | | - return sInterpreters->back().Interpreter; |
3501 | | -} |
3502 | | - |
3503 | 3539 | InterpreterLanguage GetLanguage(TInterp_t I /*=nullptr*/) { |
3504 | 3540 | compat::Interpreter* interp = &getInterp(I); |
3505 | 3541 | const auto& LO = interp->getCI()->getLangOpts(); |
@@ -3532,12 +3568,6 @@ InterpreterLanguageStandard GetLanguageStandard(TInterp_t I /*=nullptr*/) { |
3532 | 3568 | return langStandard; |
3533 | 3569 | } |
3534 | 3570 |
|
3535 | | -void UseExternalInterpreter(TInterp_t I) { |
3536 | | - assert(sInterpreters->empty() && "sInterpreter already in use!"); |
3537 | | - sInterpreters->emplace_back(static_cast<compat::Interpreter*>(I), |
3538 | | - /*isOwned=*/false); |
3539 | | -} |
3540 | | - |
3541 | 3571 | void AddSearchPath(const char* dir, bool isUser, bool prepend) { |
3542 | 3572 | getInterp().getDynamicLibraryManager()->addSearchPath(dir, isUser, prepend); |
3543 | 3573 | } |
|
0 commit comments