Skip to content

Commit f034fed

Browse files
committed
Improve the process initialization logic using function statics.
This patch centralizes logically (but also lexically) the handling of the interpreter stack. We now have a single place where the global process initialization happens including initializing llvm. This opens up the space for implementing crash handlers and diagnostic suppression.
1 parent 5098770 commit f034fed

2 files changed

Lines changed: 79 additions & 56 deletions

File tree

lib/CppInterOp/CppInterOp.cpp

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "llvm/Support/FileSystem.h"
6565
#include "llvm/Support/ManagedStatic.h"
6666
#include "llvm/Support/Path.h"
67+
#include "llvm/Support/TargetSelect.h"
6768
#include "llvm/Support/raw_ostream.h"
6869
#include "llvm/TargetParser/Host.h"
6970
#include "llvm/TargetParser/Triple.h"
@@ -162,15 +163,85 @@ struct InterpreterInfo {
162163
InterpreterInfo& operator=(const InterpreterInfo&) = delete;
163164
};
164165

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+
}
167188

168189
static compat::Interpreter& getInterp(TInterp_t I = nullptr) {
169190
if (I)
170191
return *static_cast<compat::Interpreter*>(I);
171-
assert(!sInterpreters->empty() &&
192+
auto& Interps = GetInterpreters();
193+
assert(!Interps.empty() &&
172194
"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;
174245
}
175246

176247
static clang::Sema& getSema() { return getInterp().getCI()->getSema(); }
@@ -3388,6 +3459,9 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
33883459
std::back_inserter(ClingArgv),
33893460
[&](const std::string& str) { return str.c_str(); });
33903461

3462+
// Force global process initialization.
3463+
(void)GetInterpreters();
3464+
33913465
#ifdef CPPINTEROP_USE_CLING
33923466
auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]);
33933467
#else
@@ -3430,7 +3504,7 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34303504
)");
34313505
}
34323506

3433-
sInterpreters->emplace_back(I, /*Owned=*/true);
3507+
RegisterInterpreter(I, /*Owned=*/true);
34343508

34353509
// Define runtime symbols in the JIT dylib for clang-repl
34363510
#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
@@ -3462,44 +3536,6 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34623536
return I;
34633537
}
34643538

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-
35033539
InterpreterLanguage GetLanguage(TInterp_t I /*=nullptr*/) {
35043540
compat::Interpreter* interp = &getInterp(I);
35053541
const auto& LO = interp->getCI()->getLangOpts();
@@ -3532,12 +3568,6 @@ InterpreterLanguageStandard GetLanguageStandard(TInterp_t I /*=nullptr*/) {
35323568
return langStandard;
35333569
}
35343570

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-
35413571
void AddSearchPath(const char* dir, bool isUser, bool prepend) {
35423572
getInterp().getDynamicLibraryManager()->addSearchPath(dir, isUser, prepend);
35433573
}

lib/CppInterOp/CppInterOpInterpreter.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,6 @@ class Interpreter {
208208
const std::vector<std::shared_ptr<clang::ModuleFileExtension>>&
209209
moduleExtensions = {},
210210
void* extraLibHandle = nullptr, bool noRuntime = true) {
211-
// Initialize all targets (required for device offloading)
212-
llvm::InitializeAllTargetInfos();
213-
llvm::InitializeAllTargets();
214-
llvm::InitializeAllTargetMCs();
215-
llvm::InitializeAllAsmParsers();
216-
llvm::InitializeAllAsmPrinters();
217-
218211
std::vector<const char*> vargs(argv + 1, argv + argc);
219212

220213
int stdin_fd = 0;

0 commit comments

Comments
 (0)