File: | tools/lli/lli.cpp |
Warning: | line 945, column 33 2nd function call argument is an uninitialized value |
1 | //===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This utility provides a simple wrapper around the LLVM Execution Engines, | |||
11 | // which allow the direct execution of LLVM programs through a Just-In-Time | |||
12 | // compiler, or through an interpreter if no JIT is available for this platform. | |||
13 | // | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #include "OrcLazyJIT.h" | |||
17 | #include "RemoteJITUtils.h" | |||
18 | #include "llvm/ADT/StringExtras.h" | |||
19 | #include "llvm/ADT/Triple.h" | |||
20 | #include "llvm/Bitcode/BitcodeReader.h" | |||
21 | #include "llvm/CodeGen/CommandFlags.h" | |||
22 | #include "llvm/CodeGen/LinkAllCodegenComponents.h" | |||
23 | #include "llvm/ExecutionEngine/GenericValue.h" | |||
24 | #include "llvm/ExecutionEngine/Interpreter.h" | |||
25 | #include "llvm/ExecutionEngine/JITEventListener.h" | |||
26 | #include "llvm/ExecutionEngine/MCJIT.h" | |||
27 | #include "llvm/ExecutionEngine/ObjectCache.h" | |||
28 | #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" | |||
29 | #include "llvm/ExecutionEngine/OrcMCJITReplacement.h" | |||
30 | #include "llvm/ExecutionEngine/SectionMemoryManager.h" | |||
31 | #include "llvm/IR/IRBuilder.h" | |||
32 | #include "llvm/IR/LLVMContext.h" | |||
33 | #include "llvm/IR/Module.h" | |||
34 | #include "llvm/IR/Type.h" | |||
35 | #include "llvm/IR/TypeBuilder.h" | |||
36 | #include "llvm/IRReader/IRReader.h" | |||
37 | #include "llvm/Object/Archive.h" | |||
38 | #include "llvm/Object/ObjectFile.h" | |||
39 | #include "llvm/Support/CommandLine.h" | |||
40 | #include "llvm/Support/Debug.h" | |||
41 | #include "llvm/Support/DynamicLibrary.h" | |||
42 | #include "llvm/Support/Format.h" | |||
43 | #include "llvm/Support/ManagedStatic.h" | |||
44 | #include "llvm/Support/MathExtras.h" | |||
45 | #include "llvm/Support/Memory.h" | |||
46 | #include "llvm/Support/MemoryBuffer.h" | |||
47 | #include "llvm/Support/Path.h" | |||
48 | #include "llvm/Support/PluginLoader.h" | |||
49 | #include "llvm/Support/PrettyStackTrace.h" | |||
50 | #include "llvm/Support/Process.h" | |||
51 | #include "llvm/Support/Program.h" | |||
52 | #include "llvm/Support/Signals.h" | |||
53 | #include "llvm/Support/SourceMgr.h" | |||
54 | #include "llvm/Support/TargetSelect.h" | |||
55 | #include "llvm/Support/raw_ostream.h" | |||
56 | #include "llvm/Transforms/Instrumentation.h" | |||
57 | #include <cerrno> | |||
58 | ||||
59 | #ifdef __CYGWIN__ | |||
60 | #include <cygwin/version.h> | |||
61 | #if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 | |||
62 | #define DO_NOTHING_ATEXIT 1 | |||
63 | #endif | |||
64 | #endif | |||
65 | ||||
66 | using namespace llvm; | |||
67 | ||||
68 | #define DEBUG_TYPE"lli" "lli" | |||
69 | ||||
70 | namespace { | |||
71 | ||||
72 | enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy }; | |||
73 | ||||
74 | cl::opt<std::string> | |||
75 | InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-")); | |||
76 | ||||
77 | cl::list<std::string> | |||
78 | InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>...")); | |||
79 | ||||
80 | cl::opt<bool> ForceInterpreter("force-interpreter", | |||
81 | cl::desc("Force interpretation: disable JIT"), | |||
82 | cl::init(false)); | |||
83 | ||||
84 | cl::opt<JITKind> UseJITKind("jit-kind", | |||
85 | cl::desc("Choose underlying JIT kind."), | |||
86 | cl::init(JITKind::MCJIT), | |||
87 | cl::values( | |||
88 | clEnumValN(JITKind::MCJIT, "mcjit",llvm::cl::OptionEnumValue { "mcjit", int(JITKind::MCJIT), "MCJIT" } | |||
89 | "MCJIT")llvm::cl::OptionEnumValue { "mcjit", int(JITKind::MCJIT), "MCJIT" }, | |||
90 | clEnumValN(JITKind::OrcMCJITReplacement,llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" } | |||
91 | "orc-mcjit",llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" } | |||
92 | "Orc-based MCJIT replacement")llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" }, | |||
93 | clEnumValN(JITKind::OrcLazy,llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." } | |||
94 | "orc-lazy",llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." } | |||
95 | "Orc-based lazy JIT.")llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." })); | |||
96 | ||||
97 | // The MCJIT supports building for a target address space separate from | |||
98 | // the JIT compilation process. Use a forked process and a copying | |||
99 | // memory manager with IPC to execute using this functionality. | |||
100 | cl::opt<bool> RemoteMCJIT("remote-mcjit", | |||
101 | cl::desc("Execute MCJIT'ed code in a separate process."), | |||
102 | cl::init(false)); | |||
103 | ||||
104 | // Manually specify the child process for remote execution. This overrides | |||
105 | // the simulated remote execution that allocates address space for child | |||
106 | // execution. The child process will be executed and will communicate with | |||
107 | // lli via stdin/stdout pipes. | |||
108 | cl::opt<std::string> | |||
109 | ChildExecPath("mcjit-remote-process", | |||
110 | cl::desc("Specify the filename of the process to launch " | |||
111 | "for remote MCJIT execution. If none is specified," | |||
112 | "\n\tremote execution will be simulated in-process."), | |||
113 | cl::value_desc("filename"), cl::init("")); | |||
114 | ||||
115 | // Determine optimization level. | |||
116 | cl::opt<char> | |||
117 | OptLevel("O", | |||
118 | cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " | |||
119 | "(default = '-O2')"), | |||
120 | cl::Prefix, | |||
121 | cl::ZeroOrMore, | |||
122 | cl::init(' ')); | |||
123 | ||||
124 | cl::opt<std::string> | |||
125 | TargetTriple("mtriple", cl::desc("Override target triple for module")); | |||
126 | ||||
127 | cl::opt<std::string> | |||
128 | EntryFunc("entry-function", | |||
129 | cl::desc("Specify the entry function (default = 'main') " | |||
130 | "of the executable"), | |||
131 | cl::value_desc("function"), | |||
132 | cl::init("main")); | |||
133 | ||||
134 | cl::list<std::string> | |||
135 | ExtraModules("extra-module", | |||
136 | cl::desc("Extra modules to be loaded"), | |||
137 | cl::value_desc("input bitcode")); | |||
138 | ||||
139 | cl::list<std::string> | |||
140 | ExtraObjects("extra-object", | |||
141 | cl::desc("Extra object files to be loaded"), | |||
142 | cl::value_desc("input object")); | |||
143 | ||||
144 | cl::list<std::string> | |||
145 | ExtraArchives("extra-archive", | |||
146 | cl::desc("Extra archive files to be loaded"), | |||
147 | cl::value_desc("input archive")); | |||
148 | ||||
149 | cl::opt<bool> | |||
150 | EnableCacheManager("enable-cache-manager", | |||
151 | cl::desc("Use cache manager to save/load mdoules"), | |||
152 | cl::init(false)); | |||
153 | ||||
154 | cl::opt<std::string> | |||
155 | ObjectCacheDir("object-cache-dir", | |||
156 | cl::desc("Directory to store cached object files " | |||
157 | "(must be user writable)"), | |||
158 | cl::init("")); | |||
159 | ||||
160 | cl::opt<std::string> | |||
161 | FakeArgv0("fake-argv0", | |||
162 | cl::desc("Override the 'argv[0]' value passed into the executing" | |||
163 | " program"), cl::value_desc("executable")); | |||
164 | ||||
165 | cl::opt<bool> | |||
166 | DisableCoreFiles("disable-core-files", cl::Hidden, | |||
167 | cl::desc("Disable emission of core files if possible")); | |||
168 | ||||
169 | cl::opt<bool> | |||
170 | NoLazyCompilation("disable-lazy-compilation", | |||
171 | cl::desc("Disable JIT lazy compilation"), | |||
172 | cl::init(false)); | |||
173 | ||||
174 | cl::opt<bool> | |||
175 | GenerateSoftFloatCalls("soft-float", | |||
176 | cl::desc("Generate software floating point library calls"), | |||
177 | cl::init(false)); | |||
178 | ||||
179 | ExitOnError ExitOnErr; | |||
180 | } | |||
181 | ||||
182 | //===----------------------------------------------------------------------===// | |||
183 | // Object cache | |||
184 | // | |||
185 | // This object cache implementation writes cached objects to disk to the | |||
186 | // directory specified by CacheDir, using a filename provided in the module | |||
187 | // descriptor. The cache tries to load a saved object using that path if the | |||
188 | // file exists. CacheDir defaults to "", in which case objects are cached | |||
189 | // alongside their originating bitcodes. | |||
190 | // | |||
191 | class LLIObjectCache : public ObjectCache { | |||
192 | public: | |||
193 | LLIObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) { | |||
194 | // Add trailing '/' to cache dir if necessary. | |||
195 | if (!this->CacheDir.empty() && | |||
196 | this->CacheDir[this->CacheDir.size() - 1] != '/') | |||
197 | this->CacheDir += '/'; | |||
198 | } | |||
199 | ~LLIObjectCache() override {} | |||
200 | ||||
201 | void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { | |||
202 | const std::string &ModuleID = M->getModuleIdentifier(); | |||
203 | std::string CacheName; | |||
204 | if (!getCacheFilename(ModuleID, CacheName)) | |||
205 | return; | |||
206 | if (!CacheDir.empty()) { // Create user-defined cache dir. | |||
207 | SmallString<128> dir(sys::path::parent_path(CacheName)); | |||
208 | sys::fs::create_directories(Twine(dir)); | |||
209 | } | |||
210 | std::error_code EC; | |||
211 | raw_fd_ostream outfile(CacheName, EC, sys::fs::F_None); | |||
212 | outfile.write(Obj.getBufferStart(), Obj.getBufferSize()); | |||
213 | outfile.close(); | |||
214 | } | |||
215 | ||||
216 | std::unique_ptr<MemoryBuffer> getObject(const Module* M) override { | |||
217 | const std::string &ModuleID = M->getModuleIdentifier(); | |||
218 | std::string CacheName; | |||
219 | if (!getCacheFilename(ModuleID, CacheName)) | |||
220 | return nullptr; | |||
221 | // Load the object from the cache filename | |||
222 | ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer = | |||
223 | MemoryBuffer::getFile(CacheName, -1, false); | |||
224 | // If the file isn't there, that's OK. | |||
225 | if (!IRObjectBuffer) | |||
226 | return nullptr; | |||
227 | // MCJIT will want to write into this buffer, and we don't want that | |||
228 | // because the file has probably just been mmapped. Instead we make | |||
229 | // a copy. The filed-based buffer will be released when it goes | |||
230 | // out of scope. | |||
231 | return MemoryBuffer::getMemBufferCopy(IRObjectBuffer.get()->getBuffer()); | |||
232 | } | |||
233 | ||||
234 | private: | |||
235 | std::string CacheDir; | |||
236 | ||||
237 | bool getCacheFilename(const std::string &ModID, std::string &CacheName) { | |||
238 | std::string Prefix("file:"); | |||
239 | size_t PrefixLength = Prefix.length(); | |||
240 | if (ModID.substr(0, PrefixLength) != Prefix) | |||
241 | return false; | |||
242 | std::string CacheSubdir = ModID.substr(PrefixLength); | |||
243 | #if defined(_WIN32) | |||
244 | // Transform "X:\foo" => "/X\foo" for convenience. | |||
245 | if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') { | |||
246 | CacheSubdir[1] = CacheSubdir[0]; | |||
247 | CacheSubdir[0] = '/'; | |||
248 | } | |||
249 | #endif | |||
250 | CacheName = CacheDir + CacheSubdir; | |||
251 | size_t pos = CacheName.rfind('.'); | |||
252 | CacheName.replace(pos, CacheName.length() - pos, ".o"); | |||
253 | return true; | |||
254 | } | |||
255 | }; | |||
256 | ||||
257 | // On Mingw and Cygwin, an external symbol named '__main' is called from the | |||
258 | // generated 'main' function to allow static initialization. To avoid linking | |||
259 | // problems with remote targets (because lli's remote target support does not | |||
260 | // currently handle external linking) we add a secondary module which defines | |||
261 | // an empty '__main' function. | |||
262 | static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context, | |||
263 | StringRef TargetTripleStr) { | |||
264 | IRBuilder<> Builder(Context); | |||
265 | Triple TargetTriple(TargetTripleStr); | |||
266 | ||||
267 | // Create a new module. | |||
268 | std::unique_ptr<Module> M = make_unique<Module>("CygMingHelper", Context); | |||
269 | M->setTargetTriple(TargetTripleStr); | |||
270 | ||||
271 | // Create an empty function named "__main". | |||
272 | Function *Result; | |||
273 | if (TargetTriple.isArch64Bit()) { | |||
274 | Result = Function::Create( | |||
275 | TypeBuilder<int64_t(void), false>::get(Context), | |||
276 | GlobalValue::ExternalLinkage, "__main", M.get()); | |||
277 | } else { | |||
278 | Result = Function::Create( | |||
279 | TypeBuilder<int32_t(void), false>::get(Context), | |||
280 | GlobalValue::ExternalLinkage, "__main", M.get()); | |||
281 | } | |||
282 | BasicBlock *BB = BasicBlock::Create(Context, "__main", Result); | |||
283 | Builder.SetInsertPoint(BB); | |||
284 | Value *ReturnVal; | |||
285 | if (TargetTriple.isArch64Bit()) | |||
286 | ReturnVal = ConstantInt::get(Context, APInt(64, 0)); | |||
287 | else | |||
288 | ReturnVal = ConstantInt::get(Context, APInt(32, 0)); | |||
289 | Builder.CreateRet(ReturnVal); | |||
290 | ||||
291 | // Add this new module to the ExecutionEngine. | |||
292 | EE.addModule(std::move(M)); | |||
293 | } | |||
294 | ||||
295 | CodeGenOpt::Level getOptLevel() { | |||
296 | switch (OptLevel) { | |||
297 | default: | |||
298 | errs() << "lli: Invalid optimization level.\n"; | |||
299 | exit(1); | |||
300 | case '0': return CodeGenOpt::None; | |||
301 | case '1': return CodeGenOpt::Less; | |||
302 | case ' ': | |||
303 | case '2': return CodeGenOpt::Default; | |||
304 | case '3': return CodeGenOpt::Aggressive; | |||
305 | } | |||
306 | llvm_unreachable("Unrecognized opt level.")::llvm::llvm_unreachable_internal("Unrecognized opt level.", "/build/llvm-toolchain-snapshot-6.0~svn319013/tools/lli/lli.cpp" , 306); | |||
307 | } | |||
308 | ||||
309 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
310 | static void reportError(SMDiagnostic Err, const char *ProgName) { | |||
311 | Err.print(ProgName, errs()); | |||
312 | exit(1); | |||
313 | } | |||
314 | ||||
315 | //===----------------------------------------------------------------------===// | |||
316 | // main Driver function | |||
317 | // | |||
318 | int main(int argc, char **argv, char * const *envp) { | |||
319 | sys::PrintStackTraceOnErrorSignal(argv[0]); | |||
320 | PrettyStackTraceProgram X(argc, argv); | |||
321 | ||||
322 | atexit(llvm_shutdown); // Call llvm_shutdown() on exit. | |||
323 | ||||
324 | if (argc > 1) | |||
| ||||
325 | ExitOnErr.setBanner(std::string(argv[0]) + ": "); | |||
326 | ||||
327 | // If we have a native target, initialize it to ensure it is linked in and | |||
328 | // usable by the JIT. | |||
329 | InitializeNativeTarget(); | |||
330 | InitializeNativeTargetAsmPrinter(); | |||
331 | InitializeNativeTargetAsmParser(); | |||
332 | ||||
333 | cl::ParseCommandLineOptions(argc, argv, | |||
334 | "llvm interpreter & dynamic compiler\n"); | |||
335 | ||||
336 | // If the user doesn't want core files, disable them. | |||
337 | if (DisableCoreFiles) | |||
338 | sys::Process::PreventCoreFiles(); | |||
339 | ||||
340 | LLVMContext Context; | |||
341 | ||||
342 | // Load the bitcode... | |||
343 | SMDiagnostic Err; | |||
344 | std::unique_ptr<Module> Owner = parseIRFile(InputFile, Err, Context); | |||
345 | Module *Mod = Owner.get(); | |||
346 | if (!Mod) | |||
347 | reportError(Err, argv[0]); | |||
348 | ||||
349 | if (UseJITKind == JITKind::OrcLazy) { | |||
350 | std::vector<std::unique_ptr<Module>> Ms; | |||
351 | Ms.push_back(std::move(Owner)); | |||
352 | for (auto &ExtraMod : ExtraModules) { | |||
353 | Ms.push_back(parseIRFile(ExtraMod, Err, Context)); | |||
354 | if (!Ms.back()) | |||
355 | reportError(Err, argv[0]); | |||
356 | } | |||
357 | std::vector<std::string> Args; | |||
358 | Args.push_back(InputFile); | |||
359 | for (auto &Arg : InputArgv) | |||
360 | Args.push_back(Arg); | |||
361 | return runOrcLazyJIT(std::move(Ms), Args); | |||
362 | } | |||
363 | ||||
364 | if (EnableCacheManager) { | |||
365 | std::string CacheName("file:"); | |||
366 | CacheName.append(InputFile); | |||
367 | Mod->setModuleIdentifier(CacheName); | |||
368 | } | |||
369 | ||||
370 | // If not jitting lazily, load the whole bitcode file eagerly too. | |||
371 | if (NoLazyCompilation) { | |||
372 | // Use *argv instead of argv[0] to work around a wrong GCC warning. | |||
373 | ExitOnError ExitOnErr(std::string(*argv) + | |||
374 | ": bitcode didn't read correctly: "); | |||
375 | ExitOnErr(Mod->materializeAll()); | |||
376 | } | |||
377 | ||||
378 | std::string ErrorMsg; | |||
379 | EngineBuilder builder(std::move(Owner)); | |||
380 | builder.setMArch(MArch); | |||
381 | builder.setMCPU(MCPU); | |||
382 | builder.setMAttrs(MAttrs); | |||
383 | if (RelocModel.getNumOccurrences()) | |||
384 | builder.setRelocationModel(RelocModel); | |||
385 | if (CMModel.getNumOccurrences()) | |||
386 | builder.setCodeModel(CMModel); | |||
387 | builder.setErrorStr(&ErrorMsg); | |||
388 | builder.setEngineKind(ForceInterpreter | |||
389 | ? EngineKind::Interpreter | |||
390 | : EngineKind::JIT); | |||
391 | builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement); | |||
392 | ||||
393 | // If we are supposed to override the target triple, do so now. | |||
394 | if (!TargetTriple.empty()) | |||
395 | Mod->setTargetTriple(Triple::normalize(TargetTriple)); | |||
396 | ||||
397 | // Enable MCJIT if desired. | |||
398 | RTDyldMemoryManager *RTDyldMM = nullptr; | |||
399 | if (!ForceInterpreter) { | |||
400 | if (RemoteMCJIT) | |||
401 | RTDyldMM = new ForwardingMemoryManager(); | |||
402 | else | |||
403 | RTDyldMM = new SectionMemoryManager(); | |||
404 | ||||
405 | // Deliberately construct a temp std::unique_ptr to pass in. Do not null out | |||
406 | // RTDyldMM: We still use it below, even though we don't own it. | |||
407 | builder.setMCJITMemoryManager( | |||
408 | std::unique_ptr<RTDyldMemoryManager>(RTDyldMM)); | |||
409 | } else if (RemoteMCJIT) { | |||
410 | errs() << "error: Remote process execution does not work with the " | |||
411 | "interpreter.\n"; | |||
412 | exit(1); | |||
413 | } | |||
414 | ||||
415 | builder.setOptLevel(getOptLevel()); | |||
416 | ||||
417 | TargetOptions Options; | |||
418 | if (FloatABIForCalls != FloatABI::Default) | |||
419 | Options.FloatABIType = FloatABIForCalls; | |||
420 | ||||
421 | builder.setTargetOptions(Options); | |||
422 | ||||
423 | std::unique_ptr<ExecutionEngine> EE(builder.create()); | |||
424 | if (!EE) { | |||
425 | if (!ErrorMsg.empty()) | |||
426 | errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n"; | |||
427 | else | |||
428 | errs() << argv[0] << ": unknown error creating EE!\n"; | |||
429 | exit(1); | |||
430 | } | |||
431 | ||||
432 | std::unique_ptr<LLIObjectCache> CacheManager; | |||
433 | if (EnableCacheManager) { | |||
434 | CacheManager.reset(new LLIObjectCache(ObjectCacheDir)); | |||
435 | EE->setObjectCache(CacheManager.get()); | |||
436 | } | |||
437 | ||||
438 | // Load any additional modules specified on the command line. | |||
439 | for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) { | |||
440 | std::unique_ptr<Module> XMod = parseIRFile(ExtraModules[i], Err, Context); | |||
441 | if (!XMod) | |||
442 | reportError(Err, argv[0]); | |||
443 | if (EnableCacheManager) { | |||
444 | std::string CacheName("file:"); | |||
445 | CacheName.append(ExtraModules[i]); | |||
446 | XMod->setModuleIdentifier(CacheName); | |||
447 | } | |||
448 | EE->addModule(std::move(XMod)); | |||
449 | } | |||
450 | ||||
451 | for (unsigned i = 0, e = ExtraObjects.size(); i != e; ++i) { | |||
452 | Expected<object::OwningBinary<object::ObjectFile>> Obj = | |||
453 | object::ObjectFile::createObjectFile(ExtraObjects[i]); | |||
454 | if (!Obj) { | |||
455 | // TODO: Actually report errors helpfully. | |||
456 | consumeError(Obj.takeError()); | |||
457 | reportError(Err, argv[0]); | |||
458 | } | |||
459 | object::OwningBinary<object::ObjectFile> &O = Obj.get(); | |||
460 | EE->addObjectFile(std::move(O)); | |||
461 | } | |||
462 | ||||
463 | for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) { | |||
464 | ErrorOr<std::unique_ptr<MemoryBuffer>> ArBufOrErr = | |||
465 | MemoryBuffer::getFileOrSTDIN(ExtraArchives[i]); | |||
466 | if (!ArBufOrErr) | |||
467 | reportError(Err, argv[0]); | |||
468 | std::unique_ptr<MemoryBuffer> &ArBuf = ArBufOrErr.get(); | |||
469 | ||||
470 | Expected<std::unique_ptr<object::Archive>> ArOrErr = | |||
471 | object::Archive::create(ArBuf->getMemBufferRef()); | |||
472 | if (!ArOrErr) { | |||
473 | std::string Buf; | |||
474 | raw_string_ostream OS(Buf); | |||
475 | logAllUnhandledErrors(ArOrErr.takeError(), OS, ""); | |||
476 | OS.flush(); | |||
477 | errs() << Buf; | |||
478 | exit(1); | |||
479 | } | |||
480 | std::unique_ptr<object::Archive> &Ar = ArOrErr.get(); | |||
481 | ||||
482 | object::OwningBinary<object::Archive> OB(std::move(Ar), std::move(ArBuf)); | |||
483 | ||||
484 | EE->addArchive(std::move(OB)); | |||
485 | } | |||
486 | ||||
487 | // If the target is Cygwin/MingW and we are generating remote code, we | |||
488 | // need an extra module to help out with linking. | |||
489 | if (RemoteMCJIT && Triple(Mod->getTargetTriple()).isOSCygMing()) { | |||
490 | addCygMingExtraModule(*EE, Context, Mod->getTargetTriple()); | |||
491 | } | |||
492 | ||||
493 | // The following functions have no effect if their respective profiling | |||
494 | // support wasn't enabled in the build configuration. | |||
495 | EE->RegisterJITEventListener( | |||
496 | JITEventListener::createOProfileJITEventListener()); | |||
497 | EE->RegisterJITEventListener( | |||
498 | JITEventListener::createIntelJITEventListener()); | |||
499 | ||||
500 | if (!NoLazyCompilation && RemoteMCJIT) { | |||
501 | errs() << "warning: remote mcjit does not support lazy compilation\n"; | |||
502 | NoLazyCompilation = true; | |||
503 | } | |||
504 | EE->DisableLazyCompilation(NoLazyCompilation); | |||
505 | ||||
506 | // If the user specifically requested an argv[0] to pass into the program, | |||
507 | // do it now. | |||
508 | if (!FakeArgv0.empty()) { | |||
509 | InputFile = static_cast<std::string>(FakeArgv0); | |||
510 | } else { | |||
511 | // Otherwise, if there is a .bc suffix on the executable strip it off, it | |||
512 | // might confuse the program. | |||
513 | if (StringRef(InputFile).endswith(".bc")) | |||
514 | InputFile.erase(InputFile.length() - 3); | |||
515 | } | |||
516 | ||||
517 | // Add the module's name to the start of the vector of arguments to main(). | |||
518 | InputArgv.insert(InputArgv.begin(), InputFile); | |||
519 | ||||
520 | // Call the main function from M as if its signature were: | |||
521 | // int main (int argc, char **argv, const char **envp) | |||
522 | // using the contents of Args to determine argc & argv, and the contents of | |||
523 | // EnvVars to determine envp. | |||
524 | // | |||
525 | Function *EntryFn = Mod->getFunction(EntryFunc); | |||
526 | if (!EntryFn) { | |||
527 | errs() << '\'' << EntryFunc << "\' function not found in module.\n"; | |||
528 | return -1; | |||
529 | } | |||
530 | ||||
531 | // Reset errno to zero on entry to main. | |||
532 | errno(*__errno_location ()) = 0; | |||
533 | ||||
534 | int Result = -1; | |||
535 | ||||
536 | // Sanity check use of remote-jit: LLI currently only supports use of the | |||
537 | // remote JIT on Unix platforms. | |||
538 | if (RemoteMCJIT) { | |||
539 | #ifndef LLVM_ON_UNIX1 | |||
540 | errs() << "Warning: host does not support external remote targets.\n" | |||
541 | << " Defaulting to local execution\n"; | |||
542 | return -1; | |||
543 | #else | |||
544 | if (ChildExecPath.empty()) { | |||
545 | errs() << "-remote-mcjit requires -mcjit-remote-process.\n"; | |||
546 | exit(1); | |||
547 | } else if (!sys::fs::can_execute(ChildExecPath)) { | |||
548 | errs() << "Unable to find usable child executable: '" << ChildExecPath | |||
549 | << "'\n"; | |||
550 | return -1; | |||
551 | } | |||
552 | #endif | |||
553 | } | |||
554 | ||||
555 | if (!RemoteMCJIT) { | |||
556 | // If the program doesn't explicitly call exit, we will need the Exit | |||
557 | // function later on to make an explicit call, so get the function now. | |||
558 | Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context), | |||
559 | Type::getInt32Ty(Context)); | |||
560 | ||||
561 | // Run static constructors. | |||
562 | if (!ForceInterpreter) { | |||
563 | // Give MCJIT a chance to apply relocations and set page permissions. | |||
564 | EE->finalizeObject(); | |||
565 | } | |||
566 | EE->runStaticConstructorsDestructors(false); | |||
567 | ||||
568 | // Trigger compilation separately so code regions that need to be | |||
569 | // invalidated will be known. | |||
570 | (void)EE->getPointerToFunction(EntryFn); | |||
571 | // Clear instruction cache before code will be executed. | |||
572 | if (RTDyldMM) | |||
573 | static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache(); | |||
574 | ||||
575 | // Run main. | |||
576 | Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); | |||
577 | ||||
578 | // Run static destructors. | |||
579 | EE->runStaticConstructorsDestructors(true); | |||
580 | ||||
581 | // If the program didn't call exit explicitly, we should call it now. | |||
582 | // This ensures that any atexit handlers get called correctly. | |||
583 | if (Function *ExitF = dyn_cast<Function>(Exit)) { | |||
584 | std::vector<GenericValue> Args; | |||
585 | GenericValue ResultGV; | |||
586 | ResultGV.IntVal = APInt(32, Result); | |||
587 | Args.push_back(ResultGV); | |||
588 | EE->runFunction(ExitF, Args); | |||
589 | errs() << "ERROR: exit(" << Result << ") returned!\n"; | |||
590 | abort(); | |||
591 | } else { | |||
592 | errs() << "ERROR: exit defined with wrong prototype!\n"; | |||
593 | abort(); | |||
594 | } | |||
595 | } else { | |||
596 | // else == "if (RemoteMCJIT)" | |||
597 | ||||
598 | // Remote target MCJIT doesn't (yet) support static constructors. No reason | |||
599 | // it couldn't. This is a limitation of the LLI implementation, not the | |||
600 | // MCJIT itself. FIXME. | |||
601 | ||||
602 | // Lanch the remote process and get a channel to it. | |||
603 | std::unique_ptr<FDRawChannel> C = launchRemote(); | |||
604 | if (!C) { | |||
605 | errs() << "Failed to launch remote JIT.\n"; | |||
606 | exit(1); | |||
607 | } | |||
608 | ||||
609 | // Create a remote target client running over the channel. | |||
610 | typedef orc::remote::OrcRemoteTargetClient MyRemote; | |||
611 | auto R = ExitOnErr(MyRemote::Create(*C, ExitOnErr)); | |||
612 | ||||
613 | // Create a remote memory manager. | |||
614 | auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager()); | |||
615 | ||||
616 | // Forward MCJIT's memory manager calls to the remote memory manager. | |||
617 | static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr( | |||
618 | std::move(RemoteMM)); | |||
619 | ||||
620 | // Forward MCJIT's symbol resolution calls to the remote. | |||
621 | static_cast<ForwardingMemoryManager *>(RTDyldMM)->setResolver( | |||
622 | orc::createLambdaResolver( | |||
623 | [](const std::string &Name) { return nullptr; }, | |||
624 | [&](const std::string &Name) { | |||
625 | if (auto Addr = ExitOnErr(R->getSymbolAddress(Name))) | |||
626 | return JITSymbol(Addr, JITSymbolFlags::Exported); | |||
627 | return JITSymbol(nullptr); | |||
628 | })); | |||
629 | ||||
630 | // Grab the target address of the JIT'd main function on the remote and call | |||
631 | // it. | |||
632 | // FIXME: argv and envp handling. | |||
633 | JITTargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str()); | |||
634 | EE->finalizeObject(); | |||
635 | DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Executing '" << EntryFn-> getName() << "' at 0x" << format("%llx", Entry) << "\n"; } } while (false) | |||
636 | << format("%llx", Entry) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Executing '" << EntryFn-> getName() << "' at 0x" << format("%llx", Entry) << "\n"; } } while (false); | |||
637 | Result = ExitOnErr(R->callIntVoid(Entry)); | |||
638 | ||||
639 | // Like static constructors, the remote target MCJIT support doesn't handle | |||
640 | // this yet. It could. FIXME. | |||
641 | ||||
642 | // Delete the EE - we need to tear it down *before* we terminate the session | |||
643 | // with the remote, otherwise it'll crash when it tries to release resources | |||
644 | // on a remote that has already been disconnected. | |||
645 | EE.reset(); | |||
646 | ||||
647 | // Signal the remote target that we're done JITing. | |||
648 | ExitOnErr(R->terminateSession()); | |||
649 | } | |||
650 | ||||
651 | return Result; | |||
652 | } | |||
653 | ||||
654 | std::unique_ptr<FDRawChannel> launchRemote() { | |||
655 | #ifndef LLVM_ON_UNIX1 | |||
656 | llvm_unreachable("launchRemote not supported on non-Unix platforms")::llvm::llvm_unreachable_internal("launchRemote not supported on non-Unix platforms" , "/build/llvm-toolchain-snapshot-6.0~svn319013/tools/lli/lli.cpp" , 656); | |||
657 | #else | |||
658 | int PipeFD[2][2]; | |||
659 | pid_t ChildPID; | |||
660 | ||||
661 | // Create two pipes. | |||
662 | if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) | |||
663 | perror("Error creating pipe: "); | |||
664 | ||||
665 | ChildPID = fork(); | |||
666 | ||||
667 | if (ChildPID == 0) { | |||
668 | // In the child... | |||
669 | ||||
670 | // Close the parent ends of the pipes | |||
671 | close(PipeFD[0][1]); | |||
672 | close(PipeFD[1][0]); | |||
673 | ||||
674 | ||||
675 | // Execute the child process. | |||
676 | std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut; | |||
677 | { | |||
678 | ChildPath.reset(new char[ChildExecPath.size() + 1]); | |||
679 | std::copy(ChildExecPath.begin(), ChildExecPath.end(), &ChildPath[0]); | |||
680 | ChildPath[ChildExecPath.size()] = '\0'; | |||
681 | std::string ChildInStr = utostr(PipeFD[0][0]); | |||
682 | ChildIn.reset(new char[ChildInStr.size() + 1]); | |||
683 | std::copy(ChildInStr.begin(), ChildInStr.end(), &ChildIn[0]); | |||
684 | ChildIn[ChildInStr.size()] = '\0'; | |||
685 | std::string ChildOutStr = utostr(PipeFD[1][1]); | |||
686 | ChildOut.reset(new char[ChildOutStr.size() + 1]); | |||
687 | std::copy(ChildOutStr.begin(), ChildOutStr.end(), &ChildOut[0]); | |||
688 | ChildOut[ChildOutStr.size()] = '\0'; | |||
689 | } | |||
690 | ||||
691 | char * const args[] = { &ChildPath[0], &ChildIn[0], &ChildOut[0], nullptr }; | |||
692 | int rc = execv(ChildExecPath.c_str(), args); | |||
693 | if (rc != 0) | |||
694 | perror("Error executing child process: "); | |||
695 | llvm_unreachable("Error executing child process")::llvm::llvm_unreachable_internal("Error executing child process" , "/build/llvm-toolchain-snapshot-6.0~svn319013/tools/lli/lli.cpp" , 695); | |||
696 | } | |||
697 | // else we're the parent... | |||
698 | ||||
699 | // Close the child ends of the pipes | |||
700 | close(PipeFD[0][0]); | |||
701 | close(PipeFD[1][1]); | |||
702 | ||||
703 | // Return an RPC channel connected to our end of the pipes. | |||
704 | return llvm::make_unique<FDRawChannel>(PipeFD[1][0], PipeFD[0][1]); | |||
705 | #endif | |||
706 | } |
1 | //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file defines the OrcRemoteTargetClient class and helpers. This class |
11 | // can be used to communicate over an RawByteChannel with an |
12 | // OrcRemoteTargetServer instance to support remote-JITing. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H |
17 | #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H |
18 | |
19 | #include "llvm/ADT/Optional.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/ADT/StringMap.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/ExecutionEngine/JITSymbol.h" |
24 | #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" |
25 | #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" |
26 | #include "llvm/ExecutionEngine/RuntimeDyld.h" |
27 | #include "llvm/Support/Debug.h" |
28 | #include "llvm/Support/Error.h" |
29 | #include "llvm/Support/ErrorHandling.h" |
30 | #include "llvm/Support/Format.h" |
31 | #include "llvm/Support/MathExtras.h" |
32 | #include "llvm/Support/Memory.h" |
33 | #include "llvm/Support/raw_ostream.h" |
34 | #include <algorithm> |
35 | #include <cassert> |
36 | #include <cstdint> |
37 | #include <memory> |
38 | #include <string> |
39 | #include <tuple> |
40 | #include <utility> |
41 | #include <vector> |
42 | |
43 | #define DEBUG_TYPE"lli" "orc-remote" |
44 | |
45 | namespace llvm { |
46 | namespace orc { |
47 | namespace remote { |
48 | |
49 | /// This class provides utilities (including memory manager, indirect stubs |
50 | /// manager, and compile callback manager types) that support remote JITing |
51 | /// in ORC. |
52 | /// |
53 | /// Each of the utility classes talks to a JIT server (an instance of the |
54 | /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out |
55 | /// its actions. |
56 | class OrcRemoteTargetClient |
57 | : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { |
58 | public: |
59 | /// Remote-mapped RuntimeDyld-compatible memory manager. |
60 | class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager { |
61 | friend class OrcRemoteTargetClient; |
62 | |
63 | public: |
64 | ~RemoteRTDyldMemoryManager() { |
65 | Client.destroyRemoteAllocator(Id); |
66 | DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Destroyed remote allocator " << Id << "\n"; } } while (false); |
67 | } |
68 | |
69 | RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete; |
70 | RemoteRTDyldMemoryManager & |
71 | operator=(const RemoteRTDyldMemoryManager &) = delete; |
72 | RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default; |
73 | RemoteRTDyldMemoryManager & |
74 | operator=(RemoteRTDyldMemoryManager &&) = default; |
75 | |
76 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
77 | unsigned SectionID, |
78 | StringRef SectionName) override { |
79 | Unmapped.back().CodeAllocs.emplace_back(Size, Alignment); |
80 | uint8_t *Alloc = reinterpret_cast<uint8_t *>( |
81 | Unmapped.back().CodeAllocs.back().getLocalAddress()); |
82 | DEBUG(dbgs() << "Allocator " << Id << " allocated code for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated code for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
83 | << SectionName << ": " << Alloc << " (" << Sizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated code for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
84 | << " bytes, alignment " << Alignment << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated code for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false); |
85 | return Alloc; |
86 | } |
87 | |
88 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, |
89 | unsigned SectionID, StringRef SectionName, |
90 | bool IsReadOnly) override { |
91 | if (IsReadOnly) { |
92 | Unmapped.back().RODataAllocs.emplace_back(Size, Alignment); |
93 | uint8_t *Alloc = reinterpret_cast<uint8_t *>( |
94 | Unmapped.back().RODataAllocs.back().getLocalAddress()); |
95 | DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated ro-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
96 | << SectionName << ": " << Alloc << " (" << Sizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated ro-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
97 | << " bytes, alignment " << Alignment << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated ro-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false); |
98 | return Alloc; |
99 | } // else... |
100 | |
101 | Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment); |
102 | uint8_t *Alloc = reinterpret_cast<uint8_t *>( |
103 | Unmapped.back().RWDataAllocs.back().getLocalAddress()); |
104 | DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated rw-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
105 | << SectionName << ": " << Alloc << " (" << Sizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated rw-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false) |
106 | << " bytes, alignment " << Alignment << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " allocated rw-data for " << SectionName << ": " << Alloc << " (" << Size << " bytes, alignment " << Alignment << ")\n"; } } while (false); |
107 | return Alloc; |
108 | } |
109 | |
110 | void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, |
111 | uintptr_t RODataSize, uint32_t RODataAlign, |
112 | uintptr_t RWDataSize, |
113 | uint32_t RWDataAlign) override { |
114 | Unmapped.push_back(ObjectAllocs()); |
115 | |
116 | DEBUG(dbgs() << "Allocator " << Id << " reserved:\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " reserved:\n" ; } } while (false); |
117 | |
118 | if (CodeSize != 0) { |
119 | Unmapped.back().RemoteCodeAddr = |
120 | Client.reserveMem(Id, CodeSize, CodeAlign); |
121 | |
122 | DEBUG(dbgs() << " code: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " code: " << format("0x%016x" , Unmapped.back().RemoteCodeAddr) << " (" << CodeSize << " bytes, alignment " << CodeAlign << ")\n" ; } } while (false) |
123 | << format("0x%016x", Unmapped.back().RemoteCodeAddr)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " code: " << format("0x%016x" , Unmapped.back().RemoteCodeAddr) << " (" << CodeSize << " bytes, alignment " << CodeAlign << ")\n" ; } } while (false) |
124 | << " (" << CodeSize << " bytes, alignment " << CodeAligndo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " code: " << format("0x%016x" , Unmapped.back().RemoteCodeAddr) << " (" << CodeSize << " bytes, alignment " << CodeAlign << ")\n" ; } } while (false) |
125 | << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " code: " << format("0x%016x" , Unmapped.back().RemoteCodeAddr) << " (" << CodeSize << " bytes, alignment " << CodeAlign << ")\n" ; } } while (false); |
126 | } |
127 | |
128 | if (RODataSize != 0) { |
129 | Unmapped.back().RemoteRODataAddr = |
130 | Client.reserveMem(Id, RODataSize, RODataAlign); |
131 | |
132 | DEBUG(dbgs() << " ro-data: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " ro-data: " << format("0x%016x" , Unmapped.back().RemoteRODataAddr) << " (" << RODataSize << " bytes, alignment " << RODataAlign << ")\n" ; } } while (false) |
133 | << format("0x%016x", Unmapped.back().RemoteRODataAddr)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " ro-data: " << format("0x%016x" , Unmapped.back().RemoteRODataAddr) << " (" << RODataSize << " bytes, alignment " << RODataAlign << ")\n" ; } } while (false) |
134 | << " (" << RODataSize << " bytes, alignment "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " ro-data: " << format("0x%016x" , Unmapped.back().RemoteRODataAddr) << " (" << RODataSize << " bytes, alignment " << RODataAlign << ")\n" ; } } while (false) |
135 | << RODataAlign << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " ro-data: " << format("0x%016x" , Unmapped.back().RemoteRODataAddr) << " (" << RODataSize << " bytes, alignment " << RODataAlign << ")\n" ; } } while (false); |
136 | } |
137 | |
138 | if (RWDataSize != 0) { |
139 | Unmapped.back().RemoteRWDataAddr = |
140 | Client.reserveMem(Id, RWDataSize, RWDataAlign); |
141 | |
142 | DEBUG(dbgs() << " rw-data: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " rw-data: " << format("0x%016x" , Unmapped.back().RemoteRWDataAddr) << " (" << RWDataSize << " bytes, alignment " << RWDataAlign << ")\n" ; } } while (false) |
143 | << format("0x%016x", Unmapped.back().RemoteRWDataAddr)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " rw-data: " << format("0x%016x" , Unmapped.back().RemoteRWDataAddr) << " (" << RWDataSize << " bytes, alignment " << RWDataAlign << ")\n" ; } } while (false) |
144 | << " (" << RWDataSize << " bytes, alignment "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " rw-data: " << format("0x%016x" , Unmapped.back().RemoteRWDataAddr) << " (" << RWDataSize << " bytes, alignment " << RWDataAlign << ")\n" ; } } while (false) |
145 | << RWDataAlign << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " rw-data: " << format("0x%016x" , Unmapped.back().RemoteRWDataAddr) << " (" << RWDataSize << " bytes, alignment " << RWDataAlign << ")\n" ; } } while (false); |
146 | } |
147 | } |
148 | |
149 | bool needsToReserveAllocationSpace() override { return true; } |
150 | |
151 | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, |
152 | size_t Size) override { |
153 | UnfinalizedEHFrames.push_back({LoadAddr, Size}); |
154 | } |
155 | |
156 | void deregisterEHFrames() override { |
157 | for (auto &Frame : RegisteredEHFrames) { |
158 | // FIXME: Add error poll. |
159 | Client.deregisterEHFrames(Frame.Addr, Frame.Size); |
160 | } |
161 | } |
162 | |
163 | void notifyObjectLoaded(RuntimeDyld &Dyld, |
164 | const object::ObjectFile &Obj) override { |
165 | DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " applied mappings:\n" ; } } while (false); |
166 | for (auto &ObjAllocs : Unmapped) { |
167 | mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs, |
168 | ObjAllocs.RemoteCodeAddr); |
169 | mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs, |
170 | ObjAllocs.RemoteRODataAddr); |
171 | mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs, |
172 | ObjAllocs.RemoteRWDataAddr); |
173 | Unfinalized.push_back(std::move(ObjAllocs)); |
174 | } |
175 | Unmapped.clear(); |
176 | } |
177 | |
178 | bool finalizeMemory(std::string *ErrMsg = nullptr) override { |
179 | DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Allocator " << Id << " finalizing:\n" ; } } while (false); |
180 | |
181 | for (auto &ObjAllocs : Unfinalized) { |
182 | if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr, |
183 | sys::Memory::MF_READ | sys::Memory::MF_EXEC)) |
184 | return true; |
185 | |
186 | if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr, |
187 | sys::Memory::MF_READ)) |
188 | return true; |
189 | |
190 | if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr, |
191 | sys::Memory::MF_READ | sys::Memory::MF_WRITE)) |
192 | return true; |
193 | } |
194 | Unfinalized.clear(); |
195 | |
196 | for (auto &EHFrame : UnfinalizedEHFrames) { |
197 | if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) { |
198 | // FIXME: Replace this once finalizeMemory can return an Error. |
199 | handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { |
200 | if (ErrMsg) { |
201 | raw_string_ostream ErrOut(*ErrMsg); |
202 | EIB.log(ErrOut); |
203 | } |
204 | }); |
205 | return false; |
206 | } |
207 | } |
208 | RegisteredEHFrames = std::move(UnfinalizedEHFrames); |
209 | UnfinalizedEHFrames = {}; |
210 | |
211 | return false; |
212 | } |
213 | |
214 | private: |
215 | class Alloc { |
216 | public: |
217 | Alloc(uint64_t Size, unsigned Align) |
218 | : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {} |
219 | |
220 | Alloc(const Alloc &) = delete; |
221 | Alloc &operator=(const Alloc &) = delete; |
222 | Alloc(Alloc &&) = default; |
223 | Alloc &operator=(Alloc &&) = default; |
224 | |
225 | uint64_t getSize() const { return Size; } |
226 | |
227 | unsigned getAlign() const { return Align; } |
228 | |
229 | char *getLocalAddress() const { |
230 | uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get()); |
231 | LocalAddr = alignTo(LocalAddr, Align); |
232 | return reinterpret_cast<char *>(LocalAddr); |
233 | } |
234 | |
235 | void setRemoteAddress(JITTargetAddress RemoteAddr) { |
236 | this->RemoteAddr = RemoteAddr; |
237 | } |
238 | |
239 | JITTargetAddress getRemoteAddress() const { return RemoteAddr; } |
240 | |
241 | private: |
242 | uint64_t Size; |
243 | unsigned Align; |
244 | std::unique_ptr<char[]> Contents; |
245 | JITTargetAddress RemoteAddr = 0; |
246 | }; |
247 | |
248 | struct ObjectAllocs { |
249 | ObjectAllocs() = default; |
250 | ObjectAllocs(const ObjectAllocs &) = delete; |
251 | ObjectAllocs &operator=(const ObjectAllocs &) = delete; |
252 | ObjectAllocs(ObjectAllocs &&) = default; |
253 | ObjectAllocs &operator=(ObjectAllocs &&) = default; |
254 | |
255 | JITTargetAddress RemoteCodeAddr = 0; |
256 | JITTargetAddress RemoteRODataAddr = 0; |
257 | JITTargetAddress RemoteRWDataAddr = 0; |
258 | std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs; |
259 | }; |
260 | |
261 | RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client, |
262 | ResourceIdMgr::ResourceId Id) |
263 | : Client(Client), Id(Id) { |
264 | DEBUG(dbgs() << "Created remote allocator " << Id << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Created remote allocator " << Id << "\n"; } } while (false); |
265 | } |
266 | |
267 | // Maps all allocations in Allocs to aligned blocks |
268 | void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs, |
269 | JITTargetAddress NextAddr) { |
270 | for (auto &Alloc : Allocs) { |
271 | NextAddr = alignTo(NextAddr, Alloc.getAlign()); |
272 | Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr); |
273 | DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress()) << " -> " << format ("0x%016x", NextAddr) << "\n"; } } while (false) |
274 | << " -> " << format("0x%016x", NextAddr) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress()) << " -> " << format ("0x%016x", NextAddr) << "\n"; } } while (false); |
275 | Alloc.setRemoteAddress(NextAddr); |
276 | |
277 | // Only advance NextAddr if it was non-null to begin with, |
278 | // otherwise leave it as null. |
279 | if (NextAddr) |
280 | NextAddr += Alloc.getSize(); |
281 | } |
282 | } |
283 | |
284 | // Copies data for each alloc in the list, then set permissions on the |
285 | // segment. |
286 | bool copyAndProtect(const std::vector<Alloc> &Allocs, |
287 | JITTargetAddress RemoteSegmentAddr, |
288 | unsigned Permissions) { |
289 | if (RemoteSegmentAddr) { |
290 | assert(!Allocs.empty() && "No sections in allocated segment")(static_cast <bool> (!Allocs.empty() && "No sections in allocated segment" ) ? void (0) : __assert_fail ("!Allocs.empty() && \"No sections in allocated segment\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 290, __extension__ __PRETTY_FUNCTION__)); |
291 | |
292 | for (auto &Alloc : Allocs) { |
293 | DEBUG(dbgs() << " copying section: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " copying section: " << static_cast <void *>(Alloc.getLocalAddress()) << " -> " << format("0x%016x", Alloc.getRemoteAddress()) << " (" << Alloc.getSize() << " bytes)\n";; } } while (false) |
294 | << static_cast<void *>(Alloc.getLocalAddress()) << " -> "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " copying section: " << static_cast <void *>(Alloc.getLocalAddress()) << " -> " << format("0x%016x", Alloc.getRemoteAddress()) << " (" << Alloc.getSize() << " bytes)\n";; } } while (false) |
295 | << format("0x%016x", Alloc.getRemoteAddress()) << " ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " copying section: " << static_cast <void *>(Alloc.getLocalAddress()) << " -> " << format("0x%016x", Alloc.getRemoteAddress()) << " (" << Alloc.getSize() << " bytes)\n";; } } while (false) |
296 | << Alloc.getSize() << " bytes)\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " copying section: " << static_cast <void *>(Alloc.getLocalAddress()) << " -> " << format("0x%016x", Alloc.getRemoteAddress()) << " (" << Alloc.getSize() << " bytes)\n";; } } while (false); |
297 | |
298 | if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(), |
299 | Alloc.getSize())) |
300 | return true; |
301 | } |
302 | |
303 | DEBUG(dbgs() << " setting "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false) |
304 | << (Permissions & sys::Memory::MF_READ ? 'R' : '-')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false) |
305 | << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false) |
306 | << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false) |
307 | << " permissions on block: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false) |
308 | << format("0x%016x", RemoteSegmentAddr) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << " setting " << (Permissions & sys::Memory::MF_READ ? 'R' : '-') << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') << " permissions on block: " << format("0x%016x", RemoteSegmentAddr) << "\n"; } } while (false); |
309 | if (Client.setProtections(Id, RemoteSegmentAddr, Permissions)) |
310 | return true; |
311 | } |
312 | return false; |
313 | } |
314 | |
315 | OrcRemoteTargetClient &Client; |
316 | ResourceIdMgr::ResourceId Id; |
317 | std::vector<ObjectAllocs> Unmapped; |
318 | std::vector<ObjectAllocs> Unfinalized; |
319 | |
320 | struct EHFrame { |
321 | JITTargetAddress Addr; |
322 | uint64_t Size; |
323 | }; |
324 | std::vector<EHFrame> UnfinalizedEHFrames; |
325 | std::vector<EHFrame> RegisteredEHFrames; |
326 | }; |
327 | |
328 | /// Remote indirect stubs manager. |
329 | class RemoteIndirectStubsManager : public IndirectStubsManager { |
330 | public: |
331 | RemoteIndirectStubsManager(OrcRemoteTargetClient &Client, |
332 | ResourceIdMgr::ResourceId Id) |
333 | : Client(Client), Id(Id) {} |
334 | |
335 | ~RemoteIndirectStubsManager() override { |
336 | Client.destroyIndirectStubsManager(Id); |
337 | } |
338 | |
339 | Error createStub(StringRef StubName, JITTargetAddress StubAddr, |
340 | JITSymbolFlags StubFlags) override { |
341 | if (auto Err = reserveStubs(1)) |
342 | return Err; |
343 | |
344 | return createStubInternal(StubName, StubAddr, StubFlags); |
345 | } |
346 | |
347 | Error createStubs(const StubInitsMap &StubInits) override { |
348 | if (auto Err = reserveStubs(StubInits.size())) |
349 | return Err; |
350 | |
351 | for (auto &Entry : StubInits) |
352 | if (auto Err = createStubInternal(Entry.first(), Entry.second.first, |
353 | Entry.second.second)) |
354 | return Err; |
355 | |
356 | return Error::success(); |
357 | } |
358 | |
359 | JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { |
360 | auto I = StubIndexes.find(Name); |
361 | if (I == StubIndexes.end()) |
362 | return nullptr; |
363 | auto Key = I->second.first; |
364 | auto Flags = I->second.second; |
365 | auto StubSymbol = JITSymbol(getStubAddr(Key), Flags); |
366 | if (ExportedStubsOnly && !StubSymbol.getFlags().isExported()) |
367 | return nullptr; |
368 | return StubSymbol; |
369 | } |
370 | |
371 | JITSymbol findPointer(StringRef Name) override { |
372 | auto I = StubIndexes.find(Name); |
373 | if (I == StubIndexes.end()) |
374 | return nullptr; |
375 | auto Key = I->second.first; |
376 | auto Flags = I->second.second; |
377 | return JITSymbol(getPtrAddr(Key), Flags); |
378 | } |
379 | |
380 | Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override { |
381 | auto I = StubIndexes.find(Name); |
382 | assert(I != StubIndexes.end() && "No stub pointer for symbol")(static_cast <bool> (I != StubIndexes.end() && "No stub pointer for symbol" ) ? void (0) : __assert_fail ("I != StubIndexes.end() && \"No stub pointer for symbol\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 382, __extension__ __PRETTY_FUNCTION__)); |
383 | auto Key = I->second.first; |
384 | return Client.writePointer(getPtrAddr(Key), NewAddr); |
385 | } |
386 | |
387 | private: |
388 | struct RemoteIndirectStubsInfo { |
389 | JITTargetAddress StubBase; |
390 | JITTargetAddress PtrBase; |
391 | unsigned NumStubs; |
392 | }; |
393 | |
394 | using StubKey = std::pair<uint16_t, uint16_t>; |
395 | |
396 | Error reserveStubs(unsigned NumStubs) { |
397 | if (NumStubs <= FreeStubs.size()) |
398 | return Error::success(); |
399 | |
400 | unsigned NewStubsRequired = NumStubs - FreeStubs.size(); |
401 | JITTargetAddress StubBase; |
402 | JITTargetAddress PtrBase; |
403 | unsigned NumStubsEmitted; |
404 | |
405 | if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired)) |
406 | std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr; |
407 | else |
408 | return StubInfoOrErr.takeError(); |
409 | |
410 | unsigned NewBlockId = RemoteIndirectStubsInfos.size(); |
411 | RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted}); |
412 | |
413 | for (unsigned I = 0; I < NumStubsEmitted; ++I) |
414 | FreeStubs.push_back(std::make_pair(NewBlockId, I)); |
415 | |
416 | return Error::success(); |
417 | } |
418 | |
419 | Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr, |
420 | JITSymbolFlags StubFlags) { |
421 | auto Key = FreeStubs.back(); |
422 | FreeStubs.pop_back(); |
423 | StubIndexes[StubName] = std::make_pair(Key, StubFlags); |
424 | return Client.writePointer(getPtrAddr(Key), InitAddr); |
425 | } |
426 | |
427 | JITTargetAddress getStubAddr(StubKey K) { |
428 | assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&(static_cast <bool> (RemoteIndirectStubsInfos[K.first]. StubBase != 0 && "Missing stub address") ? void (0) : __assert_fail ("RemoteIndirectStubsInfos[K.first].StubBase != 0 && \"Missing stub address\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 429, __extension__ __PRETTY_FUNCTION__)) |
429 | "Missing stub address")(static_cast <bool> (RemoteIndirectStubsInfos[K.first]. StubBase != 0 && "Missing stub address") ? void (0) : __assert_fail ("RemoteIndirectStubsInfos[K.first].StubBase != 0 && \"Missing stub address\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 429, __extension__ __PRETTY_FUNCTION__)); |
430 | return RemoteIndirectStubsInfos[K.first].StubBase + |
431 | K.second * Client.getIndirectStubSize(); |
432 | } |
433 | |
434 | JITTargetAddress getPtrAddr(StubKey K) { |
435 | assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&(static_cast <bool> (RemoteIndirectStubsInfos[K.first]. PtrBase != 0 && "Missing pointer address") ? void (0) : __assert_fail ("RemoteIndirectStubsInfos[K.first].PtrBase != 0 && \"Missing pointer address\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 436, __extension__ __PRETTY_FUNCTION__)) |
436 | "Missing pointer address")(static_cast <bool> (RemoteIndirectStubsInfos[K.first]. PtrBase != 0 && "Missing pointer address") ? void (0) : __assert_fail ("RemoteIndirectStubsInfos[K.first].PtrBase != 0 && \"Missing pointer address\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 436, __extension__ __PRETTY_FUNCTION__)); |
437 | return RemoteIndirectStubsInfos[K.first].PtrBase + |
438 | K.second * Client.getPointerSize(); |
439 | } |
440 | |
441 | OrcRemoteTargetClient &Client; |
442 | ResourceIdMgr::ResourceId Id; |
443 | std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos; |
444 | std::vector<StubKey> FreeStubs; |
445 | StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes; |
446 | }; |
447 | |
448 | /// Remote compile callback manager. |
449 | class RemoteCompileCallbackManager : public JITCompileCallbackManager { |
450 | public: |
451 | RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, |
452 | JITTargetAddress ErrorHandlerAddress) |
453 | : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {} |
454 | |
455 | private: |
456 | Error grow() override { |
457 | JITTargetAddress BlockAddr = 0; |
458 | uint32_t NumTrampolines = 0; |
459 | if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock()) |
460 | std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr; |
461 | else |
462 | return TrampolineInfoOrErr.takeError(); |
463 | |
464 | uint32_t TrampolineSize = Client.getTrampolineSize(); |
465 | for (unsigned I = 0; I < NumTrampolines; ++I) |
466 | this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); |
467 | |
468 | return Error::success(); |
469 | } |
470 | |
471 | OrcRemoteTargetClient &Client; |
472 | }; |
473 | |
474 | /// Create an OrcRemoteTargetClient. |
475 | /// Channel is the ChannelT instance to communicate on. It is assumed that |
476 | /// the channel is ready to be read from and written to. |
477 | static Expected<std::unique_ptr<OrcRemoteTargetClient>> |
478 | Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) { |
479 | Error Err = Error::success(); |
480 | auto Client = std::unique_ptr<OrcRemoteTargetClient>( |
481 | new OrcRemoteTargetClient(Channel, std::move(ReportError), Err)); |
482 | if (Err) |
483 | return std::move(Err); |
484 | return std::move(Client); |
485 | } |
486 | |
487 | /// Call the int(void) function at the given address in the target and return |
488 | /// its result. |
489 | Expected<int> callIntVoid(JITTargetAddress Addr) { |
490 | DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Calling int(*)(void) " << format ("0x%016x", Addr) << "\n"; } } while (false); |
491 | return callB<exec::CallIntVoid>(Addr); |
492 | } |
493 | |
494 | /// Call the int(int, char*[]) function at the given address in the target and |
495 | /// return its result. |
496 | Expected<int> callMain(JITTargetAddress Addr, |
497 | const std::vector<std::string> &Args) { |
498 | DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr) << "\n"; } } while (false) |
499 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr) << "\n"; } } while (false); |
500 | return callB<exec::CallMain>(Addr, Args); |
501 | } |
502 | |
503 | /// Call the void() function at the given address in the target and wait for |
504 | /// it to finish. |
505 | Error callVoidVoid(JITTargetAddress Addr) { |
506 | DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Calling void(*)(void) " << format ("0x%016x", Addr) << "\n"; } } while (false) |
507 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Calling void(*)(void) " << format ("0x%016x", Addr) << "\n"; } } while (false); |
508 | return callB<exec::CallVoidVoid>(Addr); |
509 | } |
510 | |
511 | /// Create an RCMemoryManager which will allocate its memory on the remote |
512 | /// target. |
513 | Expected<std::unique_ptr<RemoteRTDyldMemoryManager>> |
514 | createRemoteMemoryManager() { |
515 | auto Id = AllocatorIds.getNext(); |
516 | if (auto Err = callB<mem::CreateRemoteAllocator>(Id)) |
517 | return std::move(Err); |
518 | return std::unique_ptr<RemoteRTDyldMemoryManager>( |
519 | new RemoteRTDyldMemoryManager(*this, Id)); |
520 | } |
521 | |
522 | /// Create an RCIndirectStubsManager that will allocate stubs on the remote |
523 | /// target. |
524 | Expected<std::unique_ptr<RemoteIndirectStubsManager>> |
525 | createIndirectStubsManager() { |
526 | auto Id = IndirectStubOwnerIds.getNext(); |
527 | if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id)) |
528 | return std::move(Err); |
529 | return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id); |
530 | } |
531 | |
532 | Expected<RemoteCompileCallbackManager &> |
533 | enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) { |
534 | // Emit the resolver block on the JIT server. |
535 | if (auto Err = callB<stubs::EmitResolverBlock>()) |
536 | return std::move(Err); |
537 | |
538 | // Create the callback manager. |
539 | CallbackManager.emplace(*this, ErrorHandlerAddress); |
540 | RemoteCompileCallbackManager &Mgr = *CallbackManager; |
541 | return Mgr; |
542 | } |
543 | |
544 | /// Search for symbols in the remote process. Note: This should be used by |
545 | /// symbol resolvers *after* they've searched the local symbol table in the |
546 | /// JIT stack. |
547 | Expected<JITTargetAddress> getSymbolAddress(StringRef Name) { |
548 | return callB<utils::GetSymbolAddress>(Name); |
549 | } |
550 | |
551 | /// Get the triple for the remote target. |
552 | const std::string &getTargetTriple() const { return RemoteTargetTriple; } |
553 | |
554 | Error terminateSession() { return callB<utils::TerminateSession>(); } |
555 | |
556 | private: |
557 | OrcRemoteTargetClient(rpc::RawByteChannel &Channel, |
558 | std::function<void(Error)> ReportError, Error &Err) |
559 | : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true), |
560 | ReportError(std::move(ReportError)) { |
561 | ErrorAsOutParameter EAO(&Err); |
562 | |
563 | addHandler<utils::RequestCompile>( |
564 | [this](JITTargetAddress Addr) -> JITTargetAddress { |
565 | if (CallbackManager) |
566 | return CallbackManager->executeCompileCallback(Addr); |
567 | return 0; |
568 | }); |
569 | |
570 | if (auto RIOrErr = callB<utils::GetRemoteInfo>()) { |
571 | std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize, |
572 | RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr; |
573 | Err = Error::success(); |
574 | } else |
575 | Err = RIOrErr.takeError(); |
576 | } |
577 | |
578 | void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) { |
579 | if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size)) |
580 | ReportError(std::move(Err)); |
581 | } |
582 | |
583 | void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { |
584 | if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) { |
585 | // FIXME: This will be triggered by a removeModuleSet call: Propagate |
586 | // error return up through that. |
587 | llvm_unreachable("Failed to destroy remote allocator.")::llvm::llvm_unreachable_internal("Failed to destroy remote allocator." , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" , 587); |
588 | AllocatorIds.release(Id); |
589 | } |
590 | } |
591 | |
592 | void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) { |
593 | IndirectStubOwnerIds.release(Id); |
594 | if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id)) |
595 | ReportError(std::move(Err)); |
596 | } |
597 | |
598 | Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>> |
599 | emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { |
600 | return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired); |
601 | } |
602 | |
603 | Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() { |
604 | return callB<stubs::EmitTrampolineBlock>(); |
605 | } |
606 | |
607 | uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; } |
608 | uint32_t getPageSize() const { return RemotePageSize; } |
609 | uint32_t getPointerSize() const { return RemotePointerSize; } |
610 | |
611 | uint32_t getTrampolineSize() const { return RemoteTrampolineSize; } |
612 | |
613 | Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src, |
614 | uint64_t Size) { |
615 | return callB<mem::ReadMem>(Src, Size); |
616 | } |
617 | |
618 | Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) { |
619 | // FIXME: Duplicate error and report it via ReportError too? |
620 | return callB<eh::RegisterEHFrames>(RAddr, Size); |
621 | } |
622 | |
623 | JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size, |
624 | uint32_t Align) { |
625 | if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align)) |
626 | return *AddrOrErr; |
627 | else { |
628 | ReportError(AddrOrErr.takeError()); |
629 | return 0; |
630 | } |
631 | } |
632 | |
633 | bool setProtections(ResourceIdMgr::ResourceId Id, |
634 | JITTargetAddress RemoteSegAddr, unsigned ProtFlags) { |
635 | if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) { |
636 | ReportError(std::move(Err)); |
637 | return true; |
638 | } else |
639 | return false; |
640 | } |
641 | |
642 | bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) { |
643 | if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) { |
644 | ReportError(std::move(Err)); |
645 | return true; |
646 | } else |
647 | return false; |
648 | } |
649 | |
650 | Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) { |
651 | return callB<mem::WritePtr>(Addr, PtrVal); |
652 | } |
653 | |
654 | static Error doNothing() { return Error::success(); } |
655 | |
656 | std::function<void(Error)> ReportError; |
657 | std::string RemoteTargetTriple; |
658 | uint32_t RemotePointerSize = 0; |
659 | uint32_t RemotePageSize = 0; |
660 | uint32_t RemoteTrampolineSize = 0; |
661 | uint32_t RemoteIndirectStubSize = 0; |
662 | ResourceIdMgr AllocatorIds, IndirectStubOwnerIds; |
663 | Optional<RemoteCompileCallbackManager> CallbackManager; |
664 | }; |
665 | |
666 | } // end namespace remote |
667 | } // end namespace orc |
668 | } // end namespace llvm |
669 | |
670 | #undef DEBUG_TYPE"lli" |
671 | |
672 | #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H |
1 | //===------- RPCUTils.h - Utilities for building RPC APIs -------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // Utilities to support construction of simple RPC APIs. |
11 | // |
12 | // The RPC utilities aim for ease of use (minimal conceptual overhead) for C++ |
13 | // programmers, high performance, low memory overhead, and efficient use of the |
14 | // communications channel. |
15 | // |
16 | //===----------------------------------------------------------------------===// |
17 | |
18 | #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H |
19 | #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H |
20 | |
21 | #include <map> |
22 | #include <thread> |
23 | #include <vector> |
24 | |
25 | #include "llvm/ADT/STLExtras.h" |
26 | #include "llvm/ExecutionEngine/Orc/OrcError.h" |
27 | #include "llvm/ExecutionEngine/Orc/RPCSerialization.h" |
28 | |
29 | #include <future> |
30 | |
31 | namespace llvm { |
32 | namespace orc { |
33 | namespace rpc { |
34 | |
35 | /// Base class of all fatal RPC errors (those that necessarily result in the |
36 | /// termination of the RPC session). |
37 | class RPCFatalError : public ErrorInfo<RPCFatalError> { |
38 | public: |
39 | static char ID; |
40 | }; |
41 | |
42 | /// RPCConnectionClosed is returned from RPC operations if the RPC connection |
43 | /// has already been closed due to either an error or graceful disconnection. |
44 | class ConnectionClosed : public ErrorInfo<ConnectionClosed> { |
45 | public: |
46 | static char ID; |
47 | std::error_code convertToErrorCode() const override; |
48 | void log(raw_ostream &OS) const override; |
49 | }; |
50 | |
51 | /// BadFunctionCall is returned from handleOne when the remote makes a call with |
52 | /// an unrecognized function id. |
53 | /// |
54 | /// This error is fatal because Orc RPC needs to know how to parse a function |
55 | /// call to know where the next call starts, and if it doesn't recognize the |
56 | /// function id it cannot parse the call. |
57 | template <typename FnIdT, typename SeqNoT> |
58 | class BadFunctionCall |
59 | : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> { |
60 | public: |
61 | static char ID; |
62 | |
63 | BadFunctionCall(FnIdT FnId, SeqNoT SeqNo) |
64 | : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {} |
65 | |
66 | std::error_code convertToErrorCode() const override { |
67 | return orcError(OrcErrorCode::UnexpectedRPCCall); |
68 | } |
69 | |
70 | void log(raw_ostream &OS) const override { |
71 | OS << "Call to invalid RPC function id '" << FnId << "' with " |
72 | "sequence number " << SeqNo; |
73 | } |
74 | |
75 | private: |
76 | FnIdT FnId; |
77 | SeqNoT SeqNo; |
78 | }; |
79 | |
80 | template <typename FnIdT, typename SeqNoT> |
81 | char BadFunctionCall<FnIdT, SeqNoT>::ID = 0; |
82 | |
83 | /// InvalidSequenceNumberForResponse is returned from handleOne when a response |
84 | /// call arrives with a sequence number that doesn't correspond to any in-flight |
85 | /// function call. |
86 | /// |
87 | /// This error is fatal because Orc RPC needs to know how to parse the rest of |
88 | /// the response call to know where the next call starts, and if it doesn't have |
89 | /// a result parser for this sequence number it can't do that. |
90 | template <typename SeqNoT> |
91 | class InvalidSequenceNumberForResponse |
92 | : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> { |
93 | public: |
94 | static char ID; |
95 | |
96 | InvalidSequenceNumberForResponse(SeqNoT SeqNo) |
97 | : SeqNo(std::move(SeqNo)) {} |
98 | |
99 | std::error_code convertToErrorCode() const override { |
100 | return orcError(OrcErrorCode::UnexpectedRPCCall); |
101 | }; |
102 | |
103 | void log(raw_ostream &OS) const override { |
104 | OS << "Response has unknown sequence number " << SeqNo; |
105 | } |
106 | private: |
107 | SeqNoT SeqNo; |
108 | }; |
109 | |
110 | template <typename SeqNoT> |
111 | char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0; |
112 | |
113 | /// This non-fatal error will be passed to asynchronous result handlers in place |
114 | /// of a result if the connection goes down before a result returns, or if the |
115 | /// function to be called cannot be negotiated with the remote. |
116 | class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> { |
117 | public: |
118 | static char ID; |
119 | |
120 | std::error_code convertToErrorCode() const override; |
121 | void log(raw_ostream &OS) const override; |
122 | }; |
123 | |
124 | /// This error is returned if the remote does not have a handler installed for |
125 | /// the given RPC function. |
126 | class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> { |
127 | public: |
128 | static char ID; |
129 | |
130 | CouldNotNegotiate(std::string Signature); |
131 | std::error_code convertToErrorCode() const override; |
132 | void log(raw_ostream &OS) const override; |
133 | const std::string &getSignature() const { return Signature; } |
134 | private: |
135 | std::string Signature; |
136 | }; |
137 | |
138 | template <typename DerivedFunc, typename FnT> class Function; |
139 | |
140 | // RPC Function class. |
141 | // DerivedFunc should be a user defined class with a static 'getName()' method |
142 | // returning a const char* representing the function's name. |
143 | template <typename DerivedFunc, typename RetT, typename... ArgTs> |
144 | class Function<DerivedFunc, RetT(ArgTs...)> { |
145 | public: |
146 | /// User defined function type. |
147 | using Type = RetT(ArgTs...); |
148 | |
149 | /// Return type. |
150 | using ReturnType = RetT; |
151 | |
152 | /// Returns the full function prototype as a string. |
153 | static const char *getPrototype() { |
154 | std::lock_guard<std::mutex> Lock(NameMutex); |
155 | if (Name.empty()) |
156 | raw_string_ostream(Name) |
157 | << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName() |
158 | << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")"; |
159 | return Name.data(); |
160 | } |
161 | |
162 | private: |
163 | static std::mutex NameMutex; |
164 | static std::string Name; |
165 | }; |
166 | |
167 | template <typename DerivedFunc, typename RetT, typename... ArgTs> |
168 | std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex; |
169 | |
170 | template <typename DerivedFunc, typename RetT, typename... ArgTs> |
171 | std::string Function<DerivedFunc, RetT(ArgTs...)>::Name; |
172 | |
173 | /// Allocates RPC function ids during autonegotiation. |
174 | /// Specializations of this class must provide four members: |
175 | /// |
176 | /// static T getInvalidId(): |
177 | /// Should return a reserved id that will be used to represent missing |
178 | /// functions during autonegotiation. |
179 | /// |
180 | /// static T getResponseId(): |
181 | /// Should return a reserved id that will be used to send function responses |
182 | /// (return values). |
183 | /// |
184 | /// static T getNegotiateId(): |
185 | /// Should return a reserved id for the negotiate function, which will be used |
186 | /// to negotiate ids for user defined functions. |
187 | /// |
188 | /// template <typename Func> T allocate(): |
189 | /// Allocate a unique id for function Func. |
190 | template <typename T, typename = void> class RPCFunctionIdAllocator; |
191 | |
192 | /// This specialization of RPCFunctionIdAllocator provides a default |
193 | /// implementation for integral types. |
194 | template <typename T> |
195 | class RPCFunctionIdAllocator< |
196 | T, typename std::enable_if<std::is_integral<T>::value>::type> { |
197 | public: |
198 | static T getInvalidId() { return T(0); } |
199 | static T getResponseId() { return T(1); } |
200 | static T getNegotiateId() { return T(2); } |
201 | |
202 | template <typename Func> T allocate() { return NextId++; } |
203 | |
204 | private: |
205 | T NextId = 3; |
206 | }; |
207 | |
208 | namespace detail { |
209 | |
210 | // FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation |
211 | // supports classes without default constructors. |
212 | #ifdef _MSC_VER |
213 | |
214 | namespace msvc_hacks { |
215 | |
216 | // Work around MSVC's future implementation's use of default constructors: |
217 | // A default constructed value in the promise will be overwritten when the |
218 | // real error is set - so the default constructed Error has to be checked |
219 | // already. |
220 | class MSVCPError : public Error { |
221 | public: |
222 | MSVCPError() { (void)!!*this; } |
223 | |
224 | MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {} |
225 | |
226 | MSVCPError &operator=(MSVCPError Other) { |
227 | Error::operator=(std::move(Other)); |
228 | return *this; |
229 | } |
230 | |
231 | MSVCPError(Error Err) : Error(std::move(Err)) {} |
232 | }; |
233 | |
234 | // Work around MSVC's future implementation, similar to MSVCPError. |
235 | template <typename T> class MSVCPExpected : public Expected<T> { |
236 | public: |
237 | MSVCPExpected() |
238 | : Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) { |
239 | consumeError(this->takeError()); |
240 | } |
241 | |
242 | MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {} |
243 | |
244 | MSVCPExpected &operator=(MSVCPExpected &&Other) { |
245 | Expected<T>::operator=(std::move(Other)); |
246 | return *this; |
247 | } |
248 | |
249 | MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {} |
250 | |
251 | template <typename OtherT> |
252 | MSVCPExpected( |
253 | OtherT &&Val, |
254 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = |
255 | nullptr) |
256 | : Expected<T>(std::move(Val)) {} |
257 | |
258 | template <class OtherT> |
259 | MSVCPExpected( |
260 | Expected<OtherT> &&Other, |
261 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = |
262 | nullptr) |
263 | : Expected<T>(std::move(Other)) {} |
264 | |
265 | template <class OtherT> |
266 | explicit MSVCPExpected( |
267 | Expected<OtherT> &&Other, |
268 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = |
269 | nullptr) |
270 | : Expected<T>(std::move(Other)) {} |
271 | }; |
272 | |
273 | } // end namespace msvc_hacks |
274 | |
275 | #endif // _MSC_VER |
276 | |
277 | /// Provides a typedef for a tuple containing the decayed argument types. |
278 | template <typename T> class FunctionArgsTuple; |
279 | |
280 | template <typename RetT, typename... ArgTs> |
281 | class FunctionArgsTuple<RetT(ArgTs...)> { |
282 | public: |
283 | using Type = std::tuple<typename std::decay< |
284 | typename std::remove_reference<ArgTs>::type>::type...>; |
285 | }; |
286 | |
287 | // ResultTraits provides typedefs and utilities specific to the return type |
288 | // of functions. |
289 | template <typename RetT> class ResultTraits { |
290 | public: |
291 | // The return type wrapped in llvm::Expected. |
292 | using ErrorReturnType = Expected<RetT>; |
293 | |
294 | #ifdef _MSC_VER |
295 | // The ErrorReturnType wrapped in a std::promise. |
296 | using ReturnPromiseType = std::promise<msvc_hacks::MSVCPExpected<RetT>>; |
297 | |
298 | // The ErrorReturnType wrapped in a std::future. |
299 | using ReturnFutureType = std::future<msvc_hacks::MSVCPExpected<RetT>>; |
300 | #else |
301 | // The ErrorReturnType wrapped in a std::promise. |
302 | using ReturnPromiseType = std::promise<ErrorReturnType>; |
303 | |
304 | // The ErrorReturnType wrapped in a std::future. |
305 | using ReturnFutureType = std::future<ErrorReturnType>; |
306 | #endif |
307 | |
308 | // Create a 'blank' value of the ErrorReturnType, ready and safe to |
309 | // overwrite. |
310 | static ErrorReturnType createBlankErrorReturnValue() { |
311 | return ErrorReturnType(RetT()); |
312 | } |
313 | |
314 | // Consume an abandoned ErrorReturnType. |
315 | static void consumeAbandoned(ErrorReturnType RetOrErr) { |
316 | consumeError(RetOrErr.takeError()); |
317 | } |
318 | }; |
319 | |
320 | // ResultTraits specialization for void functions. |
321 | template <> class ResultTraits<void> { |
322 | public: |
323 | // For void functions, ErrorReturnType is llvm::Error. |
324 | using ErrorReturnType = Error; |
325 | |
326 | #ifdef _MSC_VER |
327 | // The ErrorReturnType wrapped in a std::promise. |
328 | using ReturnPromiseType = std::promise<msvc_hacks::MSVCPError>; |
329 | |
330 | // The ErrorReturnType wrapped in a std::future. |
331 | using ReturnFutureType = std::future<msvc_hacks::MSVCPError>; |
332 | #else |
333 | // The ErrorReturnType wrapped in a std::promise. |
334 | using ReturnPromiseType = std::promise<ErrorReturnType>; |
335 | |
336 | // The ErrorReturnType wrapped in a std::future. |
337 | using ReturnFutureType = std::future<ErrorReturnType>; |
338 | #endif |
339 | |
340 | // Create a 'blank' value of the ErrorReturnType, ready and safe to |
341 | // overwrite. |
342 | static ErrorReturnType createBlankErrorReturnValue() { |
343 | return ErrorReturnType::success(); |
344 | } |
345 | |
346 | // Consume an abandoned ErrorReturnType. |
347 | static void consumeAbandoned(ErrorReturnType Err) { |
348 | consumeError(std::move(Err)); |
349 | } |
350 | }; |
351 | |
352 | // ResultTraits<Error> is equivalent to ResultTraits<void>. This allows |
353 | // handlers for void RPC functions to return either void (in which case they |
354 | // implicitly succeed) or Error (in which case their error return is |
355 | // propagated). See usage in HandlerTraits::runHandlerHelper. |
356 | template <> class ResultTraits<Error> : public ResultTraits<void> {}; |
357 | |
358 | // ResultTraits<Expected<T>> is equivalent to ResultTraits<T>. This allows |
359 | // handlers for RPC functions returning a T to return either a T (in which |
360 | // case they implicitly succeed) or Expected<T> (in which case their error |
361 | // return is propagated). See usage in HandlerTraits::runHandlerHelper. |
362 | template <typename RetT> |
363 | class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {}; |
364 | |
365 | // Determines whether an RPC function's defined error return type supports |
366 | // error return value. |
367 | template <typename T> |
368 | class SupportsErrorReturn { |
369 | public: |
370 | static const bool value = false; |
371 | }; |
372 | |
373 | template <> |
374 | class SupportsErrorReturn<Error> { |
375 | public: |
376 | static const bool value = true; |
377 | }; |
378 | |
379 | template <typename T> |
380 | class SupportsErrorReturn<Expected<T>> { |
381 | public: |
382 | static const bool value = true; |
383 | }; |
384 | |
385 | // RespondHelper packages return values based on whether or not the declared |
386 | // RPC function return type supports error returns. |
387 | template <bool FuncSupportsErrorReturn> |
388 | class RespondHelper; |
389 | |
390 | // RespondHelper specialization for functions that support error returns. |
391 | template <> |
392 | class RespondHelper<true> { |
393 | public: |
394 | |
395 | // Send Expected<T>. |
396 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, |
397 | typename FunctionIdT, typename SequenceNumberT> |
398 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, |
399 | SequenceNumberT SeqNo, |
400 | Expected<HandlerRetT> ResultOrErr) { |
401 | if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>()) |
402 | return ResultOrErr.takeError(); |
403 | |
404 | // Open the response message. |
405 | if (auto Err = C.startSendMessage(ResponseId, SeqNo)) |
406 | return Err; |
407 | |
408 | // Serialize the result. |
409 | if (auto Err = |
410 | SerializationTraits<ChannelT, WireRetT, |
411 | Expected<HandlerRetT>>::serialize( |
412 | C, std::move(ResultOrErr))) |
413 | return Err; |
414 | |
415 | // Close the response message. |
416 | return C.endSendMessage(); |
417 | } |
418 | |
419 | template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT> |
420 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, |
421 | SequenceNumberT SeqNo, Error Err) { |
422 | if (Err && Err.isA<RPCFatalError>()) |
423 | return Err; |
424 | if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) |
425 | return Err2; |
426 | if (auto Err2 = serializeSeq(C, std::move(Err))) |
427 | return Err2; |
428 | return C.endSendMessage(); |
429 | } |
430 | |
431 | }; |
432 | |
433 | // RespondHelper specialization for functions that do not support error returns. |
434 | template <> |
435 | class RespondHelper<false> { |
436 | public: |
437 | |
438 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, |
439 | typename FunctionIdT, typename SequenceNumberT> |
440 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, |
441 | SequenceNumberT SeqNo, |
442 | Expected<HandlerRetT> ResultOrErr) { |
443 | if (auto Err = ResultOrErr.takeError()) |
444 | return Err; |
445 | |
446 | // Open the response message. |
447 | if (auto Err = C.startSendMessage(ResponseId, SeqNo)) |
448 | return Err; |
449 | |
450 | // Serialize the result. |
451 | if (auto Err = |
452 | SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize( |
453 | C, *ResultOrErr)) |
454 | return Err; |
455 | |
456 | // Close the response message. |
457 | return C.endSendMessage(); |
458 | } |
459 | |
460 | template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT> |
461 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, |
462 | SequenceNumberT SeqNo, Error Err) { |
463 | if (Err) |
464 | return Err; |
465 | if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) |
466 | return Err2; |
467 | return C.endSendMessage(); |
468 | } |
469 | |
470 | }; |
471 | |
472 | |
473 | // Send a response of the given wire return type (WireRetT) over the |
474 | // channel, with the given sequence number. |
475 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, |
476 | typename FunctionIdT, typename SequenceNumberT> |
477 | Error respond(ChannelT &C, const FunctionIdT &ResponseId, |
478 | SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) { |
479 | return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: |
480 | template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr)); |
481 | } |
482 | |
483 | // Send an empty response message on the given channel to indicate that |
484 | // the handler ran. |
485 | template <typename WireRetT, typename ChannelT, typename FunctionIdT, |
486 | typename SequenceNumberT> |
487 | Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, |
488 | Error Err) { |
489 | return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: |
490 | sendResult(C, ResponseId, SeqNo, std::move(Err)); |
491 | } |
492 | |
493 | // Converts a given type to the equivalent error return type. |
494 | template <typename T> class WrappedHandlerReturn { |
495 | public: |
496 | using Type = Expected<T>; |
497 | }; |
498 | |
499 | template <typename T> class WrappedHandlerReturn<Expected<T>> { |
500 | public: |
501 | using Type = Expected<T>; |
502 | }; |
503 | |
504 | template <> class WrappedHandlerReturn<void> { |
505 | public: |
506 | using Type = Error; |
507 | }; |
508 | |
509 | template <> class WrappedHandlerReturn<Error> { |
510 | public: |
511 | using Type = Error; |
512 | }; |
513 | |
514 | template <> class WrappedHandlerReturn<ErrorSuccess> { |
515 | public: |
516 | using Type = Error; |
517 | }; |
518 | |
519 | // Traits class that strips the response function from the list of handler |
520 | // arguments. |
521 | template <typename FnT> class AsyncHandlerTraits; |
522 | |
523 | template <typename ResultT, typename... ArgTs> |
524 | class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> { |
525 | public: |
526 | using Type = Error(ArgTs...); |
527 | using ResultType = Expected<ResultT>; |
528 | }; |
529 | |
530 | template <typename... ArgTs> |
531 | class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> { |
532 | public: |
533 | using Type = Error(ArgTs...); |
534 | using ResultType = Error; |
535 | }; |
536 | |
537 | template <typename... ArgTs> |
538 | class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> { |
539 | public: |
540 | using Type = Error(ArgTs...); |
541 | using ResultType = Error; |
542 | }; |
543 | |
544 | template <typename... ArgTs> |
545 | class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> { |
546 | public: |
547 | using Type = Error(ArgTs...); |
548 | using ResultType = Error; |
549 | }; |
550 | |
551 | template <typename ResponseHandlerT, typename... ArgTs> |
552 | class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> : |
553 | public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type, |
554 | ArgTs...)> {}; |
555 | |
556 | // This template class provides utilities related to RPC function handlers. |
557 | // The base case applies to non-function types (the template class is |
558 | // specialized for function types) and inherits from the appropriate |
559 | // speciilization for the given non-function type's call operator. |
560 | template <typename HandlerT> |
561 | class HandlerTraits : public HandlerTraits<decltype( |
562 | &std::remove_reference<HandlerT>::type::operator())> { |
563 | }; |
564 | |
565 | // Traits for handlers with a given function type. |
566 | template <typename RetT, typename... ArgTs> |
567 | class HandlerTraits<RetT(ArgTs...)> { |
568 | public: |
569 | // Function type of the handler. |
570 | using Type = RetT(ArgTs...); |
571 | |
572 | // Return type of the handler. |
573 | using ReturnType = RetT; |
574 | |
575 | // Call the given handler with the given arguments. |
576 | template <typename HandlerT, typename... TArgTs> |
577 | static typename WrappedHandlerReturn<RetT>::Type |
578 | unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) { |
579 | return unpackAndRunHelper(Handler, Args, |
580 | llvm::index_sequence_for<TArgTs...>()); |
581 | } |
582 | |
583 | // Call the given handler with the given arguments. |
584 | template <typename HandlerT, typename ResponderT, typename... TArgTs> |
585 | static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder, |
586 | std::tuple<TArgTs...> &Args) { |
587 | return unpackAndRunAsyncHelper(Handler, Responder, Args, |
588 | llvm::index_sequence_for<TArgTs...>()); |
589 | } |
590 | |
591 | // Call the given handler with the given arguments. |
592 | template <typename HandlerT> |
593 | static typename std::enable_if< |
594 | std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, |
595 | Error>::type |
596 | run(HandlerT &Handler, ArgTs &&... Args) { |
597 | Handler(std::move(Args)...); |
598 | return Error::success(); |
599 | } |
600 | |
601 | template <typename HandlerT, typename... TArgTs> |
602 | static typename std::enable_if< |
603 | !std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, |
604 | typename HandlerTraits<HandlerT>::ReturnType>::type |
605 | run(HandlerT &Handler, TArgTs... Args) { |
606 | return Handler(std::move(Args)...); |
607 | } |
608 | |
609 | // Serialize arguments to the channel. |
610 | template <typename ChannelT, typename... CArgTs> |
611 | static Error serializeArgs(ChannelT &C, const CArgTs... CArgs) { |
612 | return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...); |
613 | } |
614 | |
615 | // Deserialize arguments from the channel. |
616 | template <typename ChannelT, typename... CArgTs> |
617 | static Error deserializeArgs(ChannelT &C, std::tuple<CArgTs...> &Args) { |
618 | return deserializeArgsHelper(C, Args, |
619 | llvm::index_sequence_for<CArgTs...>()); |
620 | } |
621 | |
622 | private: |
623 | template <typename ChannelT, typename... CArgTs, size_t... Indexes> |
624 | static Error deserializeArgsHelper(ChannelT &C, std::tuple<CArgTs...> &Args, |
625 | llvm::index_sequence<Indexes...> _) { |
626 | return SequenceSerialization<ChannelT, ArgTs...>::deserialize( |
627 | C, std::get<Indexes>(Args)...); |
628 | } |
629 | |
630 | template <typename HandlerT, typename ArgTuple, size_t... Indexes> |
631 | static typename WrappedHandlerReturn< |
632 | typename HandlerTraits<HandlerT>::ReturnType>::Type |
633 | unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args, |
634 | llvm::index_sequence<Indexes...>) { |
635 | return run(Handler, std::move(std::get<Indexes>(Args))...); |
636 | } |
637 | |
638 | |
639 | template <typename HandlerT, typename ResponderT, typename ArgTuple, |
640 | size_t... Indexes> |
641 | static typename WrappedHandlerReturn< |
642 | typename HandlerTraits<HandlerT>::ReturnType>::Type |
643 | unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder, |
644 | ArgTuple &Args, |
645 | llvm::index_sequence<Indexes...>) { |
646 | return run(Handler, Responder, std::move(std::get<Indexes>(Args))...); |
647 | } |
648 | }; |
649 | |
650 | // Handler traits for free functions. |
651 | template <typename RetT, typename... ArgTs> |
652 | class HandlerTraits<RetT(*)(ArgTs...)> |
653 | : public HandlerTraits<RetT(ArgTs...)> {}; |
654 | |
655 | // Handler traits for class methods (especially call operators for lambdas). |
656 | template <typename Class, typename RetT, typename... ArgTs> |
657 | class HandlerTraits<RetT (Class::*)(ArgTs...)> |
658 | : public HandlerTraits<RetT(ArgTs...)> {}; |
659 | |
660 | // Handler traits for const class methods (especially call operators for |
661 | // lambdas). |
662 | template <typename Class, typename RetT, typename... ArgTs> |
663 | class HandlerTraits<RetT (Class::*)(ArgTs...) const> |
664 | : public HandlerTraits<RetT(ArgTs...)> {}; |
665 | |
666 | // Utility to peel the Expected wrapper off a response handler error type. |
667 | template <typename HandlerT> class ResponseHandlerArg; |
668 | |
669 | template <typename ArgT> class ResponseHandlerArg<Error(Expected<ArgT>)> { |
670 | public: |
671 | using ArgType = Expected<ArgT>; |
672 | using UnwrappedArgType = ArgT; |
673 | }; |
674 | |
675 | template <typename ArgT> |
676 | class ResponseHandlerArg<ErrorSuccess(Expected<ArgT>)> { |
677 | public: |
678 | using ArgType = Expected<ArgT>; |
679 | using UnwrappedArgType = ArgT; |
680 | }; |
681 | |
682 | template <> class ResponseHandlerArg<Error(Error)> { |
683 | public: |
684 | using ArgType = Error; |
685 | }; |
686 | |
687 | template <> class ResponseHandlerArg<ErrorSuccess(Error)> { |
688 | public: |
689 | using ArgType = Error; |
690 | }; |
691 | |
692 | // ResponseHandler represents a handler for a not-yet-received function call |
693 | // result. |
694 | template <typename ChannelT> class ResponseHandler { |
695 | public: |
696 | virtual ~ResponseHandler() {} |
697 | |
698 | // Reads the function result off the wire and acts on it. The meaning of |
699 | // "act" will depend on how this method is implemented in any given |
700 | // ResponseHandler subclass but could, for example, mean running a |
701 | // user-specified handler or setting a promise value. |
702 | virtual Error handleResponse(ChannelT &C) = 0; |
703 | |
704 | // Abandons this outstanding result. |
705 | virtual void abandon() = 0; |
706 | |
707 | // Create an error instance representing an abandoned response. |
708 | static Error createAbandonedResponseError() { |
709 | return make_error<ResponseAbandoned>(); |
710 | } |
711 | }; |
712 | |
713 | // ResponseHandler subclass for RPC functions with non-void returns. |
714 | template <typename ChannelT, typename FuncRetT, typename HandlerT> |
715 | class ResponseHandlerImpl : public ResponseHandler<ChannelT> { |
716 | public: |
717 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} |
718 | |
719 | // Handle the result by deserializing it from the channel then passing it |
720 | // to the user defined handler. |
721 | Error handleResponse(ChannelT &C) override { |
722 | using UnwrappedArgType = typename ResponseHandlerArg< |
723 | typename HandlerTraits<HandlerT>::Type>::UnwrappedArgType; |
724 | UnwrappedArgType Result; |
725 | if (auto Err = |
726 | SerializationTraits<ChannelT, FuncRetT, |
727 | UnwrappedArgType>::deserialize(C, Result)) |
728 | return Err; |
729 | if (auto Err = C.endReceiveMessage()) |
730 | return Err; |
731 | return Handler(std::move(Result)); |
732 | } |
733 | |
734 | // Abandon this response by calling the handler with an 'abandoned response' |
735 | // error. |
736 | void abandon() override { |
737 | if (auto Err = Handler(this->createAbandonedResponseError())) { |
738 | // Handlers should not fail when passed an abandoned response error. |
739 | report_fatal_error(std::move(Err)); |
740 | } |
741 | } |
742 | |
743 | private: |
744 | HandlerT Handler; |
745 | }; |
746 | |
747 | // ResponseHandler subclass for RPC functions with void returns. |
748 | template <typename ChannelT, typename HandlerT> |
749 | class ResponseHandlerImpl<ChannelT, void, HandlerT> |
750 | : public ResponseHandler<ChannelT> { |
751 | public: |
752 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} |
753 | |
754 | // Handle the result (no actual value, just a notification that the function |
755 | // has completed on the remote end) by calling the user-defined handler with |
756 | // Error::success(). |
757 | Error handleResponse(ChannelT &C) override { |
758 | if (auto Err = C.endReceiveMessage()) |
759 | return Err; |
760 | return Handler(Error::success()); |
761 | } |
762 | |
763 | // Abandon this response by calling the handler with an 'abandoned response' |
764 | // error. |
765 | void abandon() override { |
766 | if (auto Err = Handler(this->createAbandonedResponseError())) { |
767 | // Handlers should not fail when passed an abandoned response error. |
768 | report_fatal_error(std::move(Err)); |
769 | } |
770 | } |
771 | |
772 | private: |
773 | HandlerT Handler; |
774 | }; |
775 | |
776 | template <typename ChannelT, typename FuncRetT, typename HandlerT> |
777 | class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT> |
778 | : public ResponseHandler<ChannelT> { |
779 | public: |
780 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} |
781 | |
782 | // Handle the result by deserializing it from the channel then passing it |
783 | // to the user defined handler. |
784 | Error handleResponse(ChannelT &C) override { |
785 | using HandlerArgType = typename ResponseHandlerArg< |
786 | typename HandlerTraits<HandlerT>::Type>::ArgType; |
787 | HandlerArgType Result((typename HandlerArgType::value_type())); |
788 | |
789 | if (auto Err = |
790 | SerializationTraits<ChannelT, Expected<FuncRetT>, |
791 | HandlerArgType>::deserialize(C, Result)) |
792 | return Err; |
793 | if (auto Err = C.endReceiveMessage()) |
794 | return Err; |
795 | return Handler(std::move(Result)); |
796 | } |
797 | |
798 | // Abandon this response by calling the handler with an 'abandoned response' |
799 | // error. |
800 | void abandon() override { |
801 | if (auto Err = Handler(this->createAbandonedResponseError())) { |
802 | // Handlers should not fail when passed an abandoned response error. |
803 | report_fatal_error(std::move(Err)); |
804 | } |
805 | } |
806 | |
807 | private: |
808 | HandlerT Handler; |
809 | }; |
810 | |
811 | template <typename ChannelT, typename HandlerT> |
812 | class ResponseHandlerImpl<ChannelT, Error, HandlerT> |
813 | : public ResponseHandler<ChannelT> { |
814 | public: |
815 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} |
816 | |
817 | // Handle the result by deserializing it from the channel then passing it |
818 | // to the user defined handler. |
819 | Error handleResponse(ChannelT &C) override { |
820 | Error Result = Error::success(); |
821 | if (auto Err = |
822 | SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result)) |
823 | return Err; |
824 | if (auto Err = C.endReceiveMessage()) |
825 | return Err; |
826 | return Handler(std::move(Result)); |
827 | } |
828 | |
829 | // Abandon this response by calling the handler with an 'abandoned response' |
830 | // error. |
831 | void abandon() override { |
832 | if (auto Err = Handler(this->createAbandonedResponseError())) { |
833 | // Handlers should not fail when passed an abandoned response error. |
834 | report_fatal_error(std::move(Err)); |
835 | } |
836 | } |
837 | |
838 | private: |
839 | HandlerT Handler; |
840 | }; |
841 | |
842 | // Create a ResponseHandler from a given user handler. |
843 | template <typename ChannelT, typename FuncRetT, typename HandlerT> |
844 | std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) { |
845 | return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>( |
846 | std::move(H)); |
847 | } |
848 | |
849 | // Helper for wrapping member functions up as functors. This is useful for |
850 | // installing methods as result handlers. |
851 | template <typename ClassT, typename RetT, typename... ArgTs> |
852 | class MemberFnWrapper { |
853 | public: |
854 | using MethodT = RetT (ClassT::*)(ArgTs...); |
855 | MemberFnWrapper(ClassT &Instance, MethodT Method) |
856 | : Instance(Instance), Method(Method) {} |
857 | RetT operator()(ArgTs &&... Args) { |
858 | return (Instance.*Method)(std::move(Args)...); |
859 | } |
860 | |
861 | private: |
862 | ClassT &Instance; |
863 | MethodT Method; |
864 | }; |
865 | |
866 | // Helper that provides a Functor for deserializing arguments. |
867 | template <typename... ArgTs> class ReadArgs { |
868 | public: |
869 | Error operator()() { return Error::success(); } |
870 | }; |
871 | |
872 | template <typename ArgT, typename... ArgTs> |
873 | class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> { |
874 | public: |
875 | ReadArgs(ArgT &Arg, ArgTs &... Args) |
876 | : ReadArgs<ArgTs...>(Args...), Arg(Arg) {} |
877 | |
878 | Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) { |
879 | this->Arg = std::move(ArgVal); |
880 | return ReadArgs<ArgTs...>::operator()(ArgVals...); |
881 | } |
882 | |
883 | private: |
884 | ArgT &Arg; |
885 | }; |
886 | |
887 | // Manage sequence numbers. |
888 | template <typename SequenceNumberT> class SequenceNumberManager { |
889 | public: |
890 | // Reset, making all sequence numbers available. |
891 | void reset() { |
892 | std::lock_guard<std::mutex> Lock(SeqNoLock); |
893 | NextSequenceNumber = 0; |
894 | FreeSequenceNumbers.clear(); |
895 | } |
896 | |
897 | // Get the next available sequence number. Will re-use numbers that have |
898 | // been released. |
899 | SequenceNumberT getSequenceNumber() { |
900 | std::lock_guard<std::mutex> Lock(SeqNoLock); |
901 | if (FreeSequenceNumbers.empty()) |
902 | return NextSequenceNumber++; |
903 | auto SequenceNumber = FreeSequenceNumbers.back(); |
904 | FreeSequenceNumbers.pop_back(); |
905 | return SequenceNumber; |
906 | } |
907 | |
908 | // Release a sequence number, making it available for re-use. |
909 | void releaseSequenceNumber(SequenceNumberT SequenceNumber) { |
910 | std::lock_guard<std::mutex> Lock(SeqNoLock); |
911 | FreeSequenceNumbers.push_back(SequenceNumber); |
912 | } |
913 | |
914 | private: |
915 | std::mutex SeqNoLock; |
916 | SequenceNumberT NextSequenceNumber = 0; |
917 | std::vector<SequenceNumberT> FreeSequenceNumbers; |
918 | }; |
919 | |
920 | // Checks that predicate P holds for each corresponding pair of type arguments |
921 | // from T1 and T2 tuple. |
922 | template <template <class, class> class P, typename T1Tuple, typename T2Tuple> |
923 | class RPCArgTypeCheckHelper; |
924 | |
925 | template <template <class, class> class P> |
926 | class RPCArgTypeCheckHelper<P, std::tuple<>, std::tuple<>> { |
927 | public: |
928 | static const bool value = true; |
929 | }; |
930 | |
931 | template <template <class, class> class P, typename T, typename... Ts, |
932 | typename U, typename... Us> |
933 | class RPCArgTypeCheckHelper<P, std::tuple<T, Ts...>, std::tuple<U, Us...>> { |
934 | public: |
935 | static const bool value = |
936 | P<T, U>::value && |
937 | RPCArgTypeCheckHelper<P, std::tuple<Ts...>, std::tuple<Us...>>::value; |
938 | }; |
939 | |
940 | template <template <class, class> class P, typename T1Sig, typename T2Sig> |
941 | class RPCArgTypeCheck { |
942 | public: |
943 | using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type; |
944 | using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type; |
945 | |
946 | static_assert(std::tuple_size<T1Tuple>::value >= |
947 | std::tuple_size<T2Tuple>::value, |
948 | "Too many arguments to RPC call"); |
949 | static_assert(std::tuple_size<T1Tuple>::value <= |
950 | std::tuple_size<T2Tuple>::value, |
951 | "Too few arguments to RPC call"); |
952 | |
953 | static const bool value = RPCArgTypeCheckHelper<P, T1Tuple, T2Tuple>::value; |
954 | }; |
955 | |
956 | template <typename ChannelT, typename WireT, typename ConcreteT> |
957 | class CanSerialize { |
958 | private: |
959 | using S = SerializationTraits<ChannelT, WireT, ConcreteT>; |
960 | |
961 | template <typename T> |
962 | static std::true_type |
963 | check(typename std::enable_if< |
964 | std::is_same<decltype(T::serialize(std::declval<ChannelT &>(), |
965 | std::declval<const ConcreteT &>())), |
966 | Error>::value, |
967 | void *>::type); |
968 | |
969 | template <typename> static std::false_type check(...); |
970 | |
971 | public: |
972 | static const bool value = decltype(check<S>(0))::value; |
973 | }; |
974 | |
975 | template <typename ChannelT, typename WireT, typename ConcreteT> |
976 | class CanDeserialize { |
977 | private: |
978 | using S = SerializationTraits<ChannelT, WireT, ConcreteT>; |
979 | |
980 | template <typename T> |
981 | static std::true_type |
982 | check(typename std::enable_if< |
983 | std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(), |
984 | std::declval<ConcreteT &>())), |
985 | Error>::value, |
986 | void *>::type); |
987 | |
988 | template <typename> static std::false_type check(...); |
989 | |
990 | public: |
991 | static const bool value = decltype(check<S>(0))::value; |
992 | }; |
993 | |
994 | /// Contains primitive utilities for defining, calling and handling calls to |
995 | /// remote procedures. ChannelT is a bidirectional stream conforming to the |
996 | /// RPCChannel interface (see RPCChannel.h), FunctionIdT is a procedure |
997 | /// identifier type that must be serializable on ChannelT, and SequenceNumberT |
998 | /// is an integral type that will be used to number in-flight function calls. |
999 | /// |
1000 | /// These utilities support the construction of very primitive RPC utilities. |
1001 | /// Their intent is to ensure correct serialization and deserialization of |
1002 | /// procedure arguments, and to keep the client and server's view of the API in |
1003 | /// sync. |
1004 | template <typename ImplT, typename ChannelT, typename FunctionIdT, |
1005 | typename SequenceNumberT> |
1006 | class RPCEndpointBase { |
1007 | protected: |
1008 | class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> { |
1009 | public: |
1010 | static const char *getName() { return "__orc_rpc$invalid"; } |
1011 | }; |
1012 | |
1013 | class OrcRPCResponse : public Function<OrcRPCResponse, void()> { |
1014 | public: |
1015 | static const char *getName() { return "__orc_rpc$response"; } |
1016 | }; |
1017 | |
1018 | class OrcRPCNegotiate |
1019 | : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> { |
1020 | public: |
1021 | static const char *getName() { return "__orc_rpc$negotiate"; } |
1022 | }; |
1023 | |
1024 | // Helper predicate for testing for the presence of SerializeTraits |
1025 | // serializers. |
1026 | template <typename WireT, typename ConcreteT> |
1027 | class CanSerializeCheck : detail::CanSerialize<ChannelT, WireT, ConcreteT> { |
1028 | public: |
1029 | using detail::CanSerialize<ChannelT, WireT, ConcreteT>::value; |
1030 | |
1031 | static_assert(value, "Missing serializer for argument (Can't serialize the " |
1032 | "first template type argument of CanSerializeCheck " |
1033 | "from the second)"); |
1034 | }; |
1035 | |
1036 | // Helper predicate for testing for the presence of SerializeTraits |
1037 | // deserializers. |
1038 | template <typename WireT, typename ConcreteT> |
1039 | class CanDeserializeCheck |
1040 | : detail::CanDeserialize<ChannelT, WireT, ConcreteT> { |
1041 | public: |
1042 | using detail::CanDeserialize<ChannelT, WireT, ConcreteT>::value; |
1043 | |
1044 | static_assert(value, "Missing deserializer for argument (Can't deserialize " |
1045 | "the second template type argument of " |
1046 | "CanDeserializeCheck from the first)"); |
1047 | }; |
1048 | |
1049 | public: |
1050 | /// Construct an RPC instance on a channel. |
1051 | RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation) |
1052 | : C(C), LazyAutoNegotiation(LazyAutoNegotiation) { |
1053 | // Hold ResponseId in a special variable, since we expect Response to be |
1054 | // called relatively frequently, and want to avoid the map lookup. |
1055 | ResponseId = FnIdAllocator.getResponseId(); |
1056 | RemoteFunctionIds[OrcRPCResponse::getPrototype()] = ResponseId; |
1057 | |
1058 | // Register the negotiate function id and handler. |
1059 | auto NegotiateId = FnIdAllocator.getNegotiateId(); |
1060 | RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId; |
1061 | Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>( |
1062 | [this](const std::string &Name) { return handleNegotiate(Name); }); |
1063 | } |
1064 | |
1065 | |
1066 | /// Negotiate a function id for Func with the other end of the channel. |
1067 | template <typename Func> Error negotiateFunction(bool Retry = false) { |
1068 | return getRemoteFunctionId<Func>(true, Retry).takeError(); |
1069 | } |
1070 | |
1071 | /// Append a call Func, does not call send on the channel. |
1072 | /// The first argument specifies a user-defined handler to be run when the |
1073 | /// function returns. The handler should take an Expected<Func::ReturnType>, |
1074 | /// or an Error (if Func::ReturnType is void). The handler will be called |
1075 | /// with an error if the return value is abandoned due to a channel error. |
1076 | template <typename Func, typename HandlerT, typename... ArgTs> |
1077 | Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) { |
1078 | |
1079 | static_assert( |
1080 | detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type, |
1081 | void(ArgTs...)>::value, |
1082 | ""); |
1083 | |
1084 | // Look up the function ID. |
1085 | FunctionIdT FnId; |
1086 | if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false)) |
1087 | FnId = *FnIdOrErr; |
1088 | else { |
1089 | // Negotiation failed. Notify the handler then return the negotiate-failed |
1090 | // error. |
1091 | cantFail(Handler(make_error<ResponseAbandoned>())); |
1092 | return FnIdOrErr.takeError(); |
1093 | } |
1094 | |
1095 | SequenceNumberT SeqNo; // initialized in locked scope below. |
1096 | { |
1097 | // Lock the pending responses map and sequence number manager. |
1098 | std::lock_guard<std::mutex> Lock(ResponsesMutex); |
1099 | |
1100 | // Allocate a sequence number. |
1101 | SeqNo = SequenceNumberMgr.getSequenceNumber(); |
1102 | assert(!PendingResponses.count(SeqNo) &&(static_cast <bool> (!PendingResponses.count(SeqNo) && "Sequence number already allocated") ? void (0) : __assert_fail ("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1103, __extension__ __PRETTY_FUNCTION__)) |
1103 | "Sequence number already allocated")(static_cast <bool> (!PendingResponses.count(SeqNo) && "Sequence number already allocated") ? void (0) : __assert_fail ("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1103, __extension__ __PRETTY_FUNCTION__)); |
1104 | |
1105 | // Install the user handler. |
1106 | PendingResponses[SeqNo] = |
1107 | detail::createResponseHandler<ChannelT, typename Func::ReturnType>( |
1108 | std::move(Handler)); |
1109 | } |
1110 | |
1111 | // Open the function call message. |
1112 | if (auto Err = C.startSendMessage(FnId, SeqNo)) { |
1113 | abandonPendingResponses(); |
1114 | return Err; |
1115 | } |
1116 | |
1117 | // Serialize the call arguments. |
1118 | if (auto Err = detail::HandlerTraits<typename Func::Type>::serializeArgs( |
1119 | C, Args...)) { |
1120 | abandonPendingResponses(); |
1121 | return Err; |
1122 | } |
1123 | |
1124 | // Close the function call messagee. |
1125 | if (auto Err = C.endSendMessage()) { |
1126 | abandonPendingResponses(); |
1127 | return Err; |
1128 | } |
1129 | |
1130 | return Error::success(); |
1131 | } |
1132 | |
1133 | Error sendAppendedCalls() { return C.send(); }; |
1134 | |
1135 | template <typename Func, typename HandlerT, typename... ArgTs> |
1136 | Error callAsync(HandlerT Handler, const ArgTs &... Args) { |
1137 | if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...)) |
1138 | return Err; |
1139 | return C.send(); |
1140 | } |
1141 | |
1142 | /// Handle one incoming call. |
1143 | Error handleOne() { |
1144 | FunctionIdT FnId; |
1145 | SequenceNumberT SeqNo; |
1146 | if (auto Err = C.startReceiveMessage(FnId, SeqNo)) { |
1147 | abandonPendingResponses(); |
1148 | return Err; |
1149 | } |
1150 | if (FnId == ResponseId) |
1151 | return handleResponse(SeqNo); |
1152 | auto I = Handlers.find(FnId); |
1153 | if (I != Handlers.end()) |
1154 | return I->second(C, SeqNo); |
1155 | |
1156 | // else: No handler found. Report error to client? |
1157 | return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId, |
1158 | SeqNo); |
1159 | } |
1160 | |
1161 | /// Helper for handling setter procedures - this method returns a functor that |
1162 | /// sets the variables referred to by Args... to values deserialized from the |
1163 | /// channel. |
1164 | /// E.g. |
1165 | /// |
1166 | /// typedef Function<0, bool, int> Func1; |
1167 | /// |
1168 | /// ... |
1169 | /// bool B; |
1170 | /// int I; |
1171 | /// if (auto Err = expect<Func1>(Channel, readArgs(B, I))) |
1172 | /// /* Handle Args */ ; |
1173 | /// |
1174 | template <typename... ArgTs> |
1175 | static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) { |
1176 | return detail::ReadArgs<ArgTs...>(Args...); |
1177 | } |
1178 | |
1179 | /// Abandon all outstanding result handlers. |
1180 | /// |
1181 | /// This will call all currently registered result handlers to receive an |
1182 | /// "abandoned" error as their argument. This is used internally by the RPC |
1183 | /// in error situations, but can also be called directly by clients who are |
1184 | /// disconnecting from the remote and don't or can't expect responses to their |
1185 | /// outstanding calls. (Especially for outstanding blocking calls, calling |
1186 | /// this function may be necessary to avoid dead threads). |
1187 | void abandonPendingResponses() { |
1188 | // Lock the pending responses map and sequence number manager. |
1189 | std::lock_guard<std::mutex> Lock(ResponsesMutex); |
1190 | |
1191 | for (auto &KV : PendingResponses) |
1192 | KV.second->abandon(); |
1193 | PendingResponses.clear(); |
1194 | SequenceNumberMgr.reset(); |
1195 | } |
1196 | |
1197 | /// Remove the handler for the given function. |
1198 | /// A handler must currently be registered for this function. |
1199 | template <typename Func> |
1200 | void removeHandler() { |
1201 | auto IdItr = LocalFunctionIds.find(Func::getPrototype()); |
1202 | assert(IdItr != LocalFunctionIds.end() &&(static_cast <bool> (IdItr != LocalFunctionIds.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1203, __extension__ __PRETTY_FUNCTION__)) |
1203 | "Function does not have a registered handler")(static_cast <bool> (IdItr != LocalFunctionIds.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1203, __extension__ __PRETTY_FUNCTION__)); |
1204 | auto HandlerItr = Handlers.find(IdItr->second); |
1205 | assert(HandlerItr != Handlers.end() &&(static_cast <bool> (HandlerItr != Handlers.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("HandlerItr != Handlers.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1206, __extension__ __PRETTY_FUNCTION__)) |
1206 | "Function does not have a registered handler")(static_cast <bool> (HandlerItr != Handlers.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("HandlerItr != Handlers.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1206, __extension__ __PRETTY_FUNCTION__)); |
1207 | Handlers.erase(HandlerItr); |
1208 | } |
1209 | |
1210 | /// Clear all handlers. |
1211 | void clearHandlers() { |
1212 | Handlers.clear(); |
1213 | } |
1214 | |
1215 | protected: |
1216 | |
1217 | FunctionIdT getInvalidFunctionId() const { |
1218 | return FnIdAllocator.getInvalidId(); |
1219 | } |
1220 | |
1221 | /// Add the given handler to the handler map and make it available for |
1222 | /// autonegotiation and execution. |
1223 | template <typename Func, typename HandlerT> |
1224 | void addHandlerImpl(HandlerT Handler) { |
1225 | |
1226 | static_assert(detail::RPCArgTypeCheck< |
1227 | CanDeserializeCheck, typename Func::Type, |
1228 | typename detail::HandlerTraits<HandlerT>::Type>::value, |
1229 | ""); |
1230 | |
1231 | FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>(); |
1232 | LocalFunctionIds[Func::getPrototype()] = NewFnId; |
1233 | Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler)); |
1234 | } |
1235 | |
1236 | template <typename Func, typename HandlerT> |
1237 | void addAsyncHandlerImpl(HandlerT Handler) { |
1238 | |
1239 | static_assert(detail::RPCArgTypeCheck< |
1240 | CanDeserializeCheck, typename Func::Type, |
1241 | typename detail::AsyncHandlerTraits< |
1242 | typename detail::HandlerTraits<HandlerT>::Type |
1243 | >::Type>::value, |
1244 | ""); |
1245 | |
1246 | FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>(); |
1247 | LocalFunctionIds[Func::getPrototype()] = NewFnId; |
1248 | Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler)); |
1249 | } |
1250 | |
1251 | Error handleResponse(SequenceNumberT SeqNo) { |
1252 | using Handler = typename decltype(PendingResponses)::mapped_type; |
1253 | Handler PRHandler; |
1254 | |
1255 | { |
1256 | // Lock the pending responses map and sequence number manager. |
1257 | std::unique_lock<std::mutex> Lock(ResponsesMutex); |
1258 | auto I = PendingResponses.find(SeqNo); |
1259 | |
1260 | if (I != PendingResponses.end()) { |
1261 | PRHandler = std::move(I->second); |
1262 | PendingResponses.erase(I); |
1263 | SequenceNumberMgr.releaseSequenceNumber(SeqNo); |
1264 | } else { |
1265 | // Unlock the pending results map to prevent recursive lock. |
1266 | Lock.unlock(); |
1267 | abandonPendingResponses(); |
1268 | return make_error< |
1269 | InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo); |
1270 | } |
1271 | } |
1272 | |
1273 | assert(PRHandler &&(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out" ) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1274, __extension__ __PRETTY_FUNCTION__)) |
1274 | "If we didn't find a response handler we should have bailed out")(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out" ) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1274, __extension__ __PRETTY_FUNCTION__)); |
1275 | |
1276 | if (auto Err = PRHandler->handleResponse(C)) { |
1277 | abandonPendingResponses(); |
1278 | return Err; |
1279 | } |
1280 | |
1281 | return Error::success(); |
1282 | } |
1283 | |
1284 | FunctionIdT handleNegotiate(const std::string &Name) { |
1285 | auto I = LocalFunctionIds.find(Name); |
1286 | if (I == LocalFunctionIds.end()) |
1287 | return getInvalidFunctionId(); |
1288 | return I->second; |
1289 | } |
1290 | |
1291 | // Find the remote FunctionId for the given function. |
1292 | template <typename Func> |
1293 | Expected<FunctionIdT> getRemoteFunctionId(bool NegotiateIfNotInMap, |
1294 | bool NegotiateIfInvalid) { |
1295 | bool DoNegotiate; |
1296 | |
1297 | // Check if we already have a function id... |
1298 | auto I = RemoteFunctionIds.find(Func::getPrototype()); |
1299 | if (I != RemoteFunctionIds.end()) { |
1300 | // If it's valid there's nothing left to do. |
1301 | if (I->second != getInvalidFunctionId()) |
1302 | return I->second; |
1303 | DoNegotiate = NegotiateIfInvalid; |
1304 | } else |
1305 | DoNegotiate = NegotiateIfNotInMap; |
1306 | |
1307 | // We don't have a function id for Func yet, but we're allowed to try to |
1308 | // negotiate one. |
1309 | if (DoNegotiate) { |
1310 | auto &Impl = static_cast<ImplT &>(*this); |
1311 | if (auto RemoteIdOrErr = |
1312 | Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) { |
1313 | RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr; |
1314 | if (*RemoteIdOrErr == getInvalidFunctionId()) |
1315 | return make_error<CouldNotNegotiate>(Func::getPrototype()); |
1316 | return *RemoteIdOrErr; |
1317 | } else |
1318 | return RemoteIdOrErr.takeError(); |
1319 | } |
1320 | |
1321 | // No key was available in the map and we weren't allowed to try to |
1322 | // negotiate one, so return an unknown function error. |
1323 | return make_error<CouldNotNegotiate>(Func::getPrototype()); |
1324 | } |
1325 | |
1326 | using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>; |
1327 | |
1328 | // Wrap the given user handler in the necessary argument-deserialization code, |
1329 | // result-serialization code, and call to the launch policy (if present). |
1330 | template <typename Func, typename HandlerT> |
1331 | WrappedHandlerFn wrapHandler(HandlerT Handler) { |
1332 | return [this, Handler](ChannelT &Channel, |
1333 | SequenceNumberT SeqNo) mutable -> Error { |
1334 | // Start by deserializing the arguments. |
1335 | using ArgsTuple = |
1336 | typename detail::FunctionArgsTuple< |
1337 | typename detail::HandlerTraits<HandlerT>::Type>::Type; |
1338 | auto Args = std::make_shared<ArgsTuple>(); |
1339 | |
1340 | if (auto Err = |
1341 | detail::HandlerTraits<typename Func::Type>::deserializeArgs( |
1342 | Channel, *Args)) |
1343 | return Err; |
1344 | |
1345 | // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning |
1346 | // for RPCArgs. Void cast RPCArgs to work around this for now. |
1347 | // FIXME: Remove this workaround once we can assume a working GCC version. |
1348 | (void)Args; |
1349 | |
1350 | // End receieve message, unlocking the channel for reading. |
1351 | if (auto Err = Channel.endReceiveMessage()) |
1352 | return Err; |
1353 | |
1354 | using HTraits = detail::HandlerTraits<HandlerT>; |
1355 | using FuncReturn = typename Func::ReturnType; |
1356 | return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo, |
1357 | HTraits::unpackAndRun(Handler, *Args)); |
1358 | }; |
1359 | } |
1360 | |
1361 | // Wrap the given user handler in the necessary argument-deserialization code, |
1362 | // result-serialization code, and call to the launch policy (if present). |
1363 | template <typename Func, typename HandlerT> |
1364 | WrappedHandlerFn wrapAsyncHandler(HandlerT Handler) { |
1365 | return [this, Handler](ChannelT &Channel, |
1366 | SequenceNumberT SeqNo) mutable -> Error { |
1367 | // Start by deserializing the arguments. |
1368 | using AHTraits = detail::AsyncHandlerTraits< |
1369 | typename detail::HandlerTraits<HandlerT>::Type>; |
1370 | using ArgsTuple = |
1371 | typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type; |
1372 | auto Args = std::make_shared<ArgsTuple>(); |
1373 | |
1374 | if (auto Err = |
1375 | detail::HandlerTraits<typename Func::Type>::deserializeArgs( |
1376 | Channel, *Args)) |
1377 | return Err; |
1378 | |
1379 | // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning |
1380 | // for RPCArgs. Void cast RPCArgs to work around this for now. |
1381 | // FIXME: Remove this workaround once we can assume a working GCC version. |
1382 | (void)Args; |
1383 | |
1384 | // End receieve message, unlocking the channel for reading. |
1385 | if (auto Err = Channel.endReceiveMessage()) |
1386 | return Err; |
1387 | |
1388 | using HTraits = detail::HandlerTraits<HandlerT>; |
1389 | using FuncReturn = typename Func::ReturnType; |
1390 | auto Responder = |
1391 | [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error { |
1392 | return detail::respond<FuncReturn>(C, ResponseId, SeqNo, |
1393 | std::move(RetVal)); |
1394 | }; |
1395 | |
1396 | return HTraits::unpackAndRunAsync(Handler, Responder, *Args); |
1397 | }; |
1398 | } |
1399 | |
1400 | ChannelT &C; |
1401 | |
1402 | bool LazyAutoNegotiation; |
1403 | |
1404 | RPCFunctionIdAllocator<FunctionIdT> FnIdAllocator; |
1405 | |
1406 | FunctionIdT ResponseId; |
1407 | std::map<std::string, FunctionIdT> LocalFunctionIds; |
1408 | std::map<const char *, FunctionIdT> RemoteFunctionIds; |
1409 | |
1410 | std::map<FunctionIdT, WrappedHandlerFn> Handlers; |
1411 | |
1412 | std::mutex ResponsesMutex; |
1413 | detail::SequenceNumberManager<SequenceNumberT> SequenceNumberMgr; |
1414 | std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>> |
1415 | PendingResponses; |
1416 | }; |
1417 | |
1418 | } // end namespace detail |
1419 | |
1420 | template <typename ChannelT, typename FunctionIdT = uint32_t, |
1421 | typename SequenceNumberT = uint32_t> |
1422 | class MultiThreadedRPCEndpoint |
1423 | : public detail::RPCEndpointBase< |
1424 | MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, |
1425 | ChannelT, FunctionIdT, SequenceNumberT> { |
1426 | private: |
1427 | using BaseClass = |
1428 | detail::RPCEndpointBase< |
1429 | MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, |
1430 | ChannelT, FunctionIdT, SequenceNumberT>; |
1431 | |
1432 | public: |
1433 | MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) |
1434 | : BaseClass(C, LazyAutoNegotiation) {} |
1435 | |
1436 | /// Add a handler for the given RPC function. |
1437 | /// This installs the given handler functor for the given RPC Function, and |
1438 | /// makes the RPC function available for negotiation/calling from the remote. |
1439 | template <typename Func, typename HandlerT> |
1440 | void addHandler(HandlerT Handler) { |
1441 | return this->template addHandlerImpl<Func>(std::move(Handler)); |
1442 | } |
1443 | |
1444 | /// Add a class-method as a handler. |
1445 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> |
1446 | void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { |
1447 | addHandler<Func>( |
1448 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); |
1449 | } |
1450 | |
1451 | template <typename Func, typename HandlerT> |
1452 | void addAsyncHandler(HandlerT Handler) { |
1453 | return this->template addAsyncHandlerImpl<Func>(std::move(Handler)); |
1454 | } |
1455 | |
1456 | /// Add a class-method as a handler. |
1457 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> |
1458 | void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { |
1459 | addAsyncHandler<Func>( |
1460 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); |
1461 | } |
1462 | |
1463 | /// Return type for non-blocking call primitives. |
1464 | template <typename Func> |
1465 | using NonBlockingCallResult = typename detail::ResultTraits< |
1466 | typename Func::ReturnType>::ReturnFutureType; |
1467 | |
1468 | /// Call Func on Channel C. Does not block, does not call send. Returns a pair |
1469 | /// of a future result and the sequence number assigned to the result. |
1470 | /// |
1471 | /// This utility function is primarily used for single-threaded mode support, |
1472 | /// where the sequence number can be used to wait for the corresponding |
1473 | /// result. In multi-threaded mode the appendCallNB method, which does not |
1474 | /// return the sequence numeber, should be preferred. |
1475 | template <typename Func, typename... ArgTs> |
1476 | Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) { |
1477 | using RTraits = detail::ResultTraits<typename Func::ReturnType>; |
1478 | using ErrorReturn = typename RTraits::ErrorReturnType; |
1479 | using ErrorReturnPromise = typename RTraits::ReturnPromiseType; |
1480 | |
1481 | // FIXME: Stack allocate and move this into the handler once LLVM builds |
1482 | // with C++14. |
1483 | auto Promise = std::make_shared<ErrorReturnPromise>(); |
1484 | auto FutureResult = Promise->get_future(); |
1485 | |
1486 | if (auto Err = this->template appendCallAsync<Func>( |
1487 | [Promise](ErrorReturn RetOrErr) { |
1488 | Promise->set_value(std::move(RetOrErr)); |
1489 | return Error::success(); |
1490 | }, |
1491 | Args...)) { |
1492 | RTraits::consumeAbandoned(FutureResult.get()); |
1493 | return std::move(Err); |
1494 | } |
1495 | return std::move(FutureResult); |
1496 | } |
1497 | |
1498 | /// The same as appendCallNBWithSeq, except that it calls C.send() to |
1499 | /// flush the channel after serializing the call. |
1500 | template <typename Func, typename... ArgTs> |
1501 | Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) { |
1502 | auto Result = appendCallNB<Func>(Args...); |
1503 | if (!Result) |
1504 | return Result; |
1505 | if (auto Err = this->C.send()) { |
1506 | this->abandonPendingResponses(); |
1507 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( |
1508 | std::move(Result->get())); |
1509 | return std::move(Err); |
1510 | } |
1511 | return Result; |
1512 | } |
1513 | |
1514 | /// Call Func on Channel C. Blocks waiting for a result. Returns an Error |
1515 | /// for void functions or an Expected<T> for functions returning a T. |
1516 | /// |
1517 | /// This function is for use in threaded code where another thread is |
1518 | /// handling responses and incoming calls. |
1519 | template <typename Func, typename... ArgTs, |
1520 | typename AltRetT = typename Func::ReturnType> |
1521 | typename detail::ResultTraits<AltRetT>::ErrorReturnType |
1522 | callB(const ArgTs &... Args) { |
1523 | if (auto FutureResOrErr = callNB<Func>(Args...)) |
1524 | return FutureResOrErr->get(); |
1525 | else |
1526 | return FutureResOrErr.takeError(); |
1527 | } |
1528 | |
1529 | /// Handle incoming RPC calls. |
1530 | Error handlerLoop() { |
1531 | while (true) |
1532 | if (auto Err = this->handleOne()) |
1533 | return Err; |
1534 | return Error::success(); |
1535 | } |
1536 | }; |
1537 | |
1538 | template <typename ChannelT, typename FunctionIdT = uint32_t, |
1539 | typename SequenceNumberT = uint32_t> |
1540 | class SingleThreadedRPCEndpoint |
1541 | : public detail::RPCEndpointBase< |
1542 | SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, |
1543 | ChannelT, FunctionIdT, SequenceNumberT> { |
1544 | private: |
1545 | using BaseClass = |
1546 | detail::RPCEndpointBase< |
1547 | SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, |
1548 | ChannelT, FunctionIdT, SequenceNumberT>; |
1549 | |
1550 | public: |
1551 | SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) |
1552 | : BaseClass(C, LazyAutoNegotiation) {} |
1553 | |
1554 | template <typename Func, typename HandlerT> |
1555 | void addHandler(HandlerT Handler) { |
1556 | return this->template addHandlerImpl<Func>(std::move(Handler)); |
1557 | } |
1558 | |
1559 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> |
1560 | void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { |
1561 | addHandler<Func>( |
1562 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); |
1563 | } |
1564 | |
1565 | template <typename Func, typename HandlerT> |
1566 | void addAsyncHandler(HandlerT Handler) { |
1567 | return this->template addAsyncHandlerImpl<Func>(std::move(Handler)); |
1568 | } |
1569 | |
1570 | /// Add a class-method as a handler. |
1571 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> |
1572 | void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { |
1573 | addAsyncHandler<Func>( |
1574 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); |
1575 | } |
1576 | |
1577 | template <typename Func, typename... ArgTs, |
1578 | typename AltRetT = typename Func::ReturnType> |
1579 | typename detail::ResultTraits<AltRetT>::ErrorReturnType |
1580 | callB(const ArgTs &... Args) { |
1581 | bool ReceivedResponse = false; |
1582 | using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType; |
1583 | auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue(); |
1584 | |
1585 | // We have to 'Check' result (which we know is in a success state at this |
1586 | // point) so that it can be overwritten in the async handler. |
1587 | (void)!!Result; |
1588 | |
1589 | if (auto Err = this->template appendCallAsync<Func>( |
1590 | [&](ResultType R) { |
1591 | Result = std::move(R); |
1592 | ReceivedResponse = true; |
1593 | return Error::success(); |
1594 | }, |
1595 | Args...)) { |
1596 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( |
1597 | std::move(Result)); |
1598 | return std::move(Err); |
1599 | } |
1600 | |
1601 | while (!ReceivedResponse) { |
1602 | if (auto Err = this->handleOne()) { |
1603 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( |
1604 | std::move(Result)); |
1605 | return std::move(Err); |
1606 | } |
1607 | } |
1608 | |
1609 | return Result; |
1610 | } |
1611 | }; |
1612 | |
1613 | /// Asynchronous dispatch for a function on an RPC endpoint. |
1614 | template <typename RPCClass, typename Func> |
1615 | class RPCAsyncDispatch { |
1616 | public: |
1617 | RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {} |
1618 | |
1619 | template <typename HandlerT, typename... ArgTs> |
1620 | Error operator()(HandlerT Handler, const ArgTs &... Args) const { |
1621 | return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...); |
1622 | } |
1623 | |
1624 | private: |
1625 | RPCClass &Endpoint; |
1626 | }; |
1627 | |
1628 | /// Construct an asynchronous dispatcher from an RPC endpoint and a Func. |
1629 | template <typename Func, typename RPCEndpointT> |
1630 | RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) { |
1631 | return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint); |
1632 | } |
1633 | |
1634 | /// \brief Allows a set of asynchrounous calls to be dispatched, and then |
1635 | /// waited on as a group. |
1636 | class ParallelCallGroup { |
1637 | public: |
1638 | |
1639 | ParallelCallGroup() = default; |
1640 | ParallelCallGroup(const ParallelCallGroup &) = delete; |
1641 | ParallelCallGroup &operator=(const ParallelCallGroup &) = delete; |
1642 | |
1643 | /// \brief Make as asynchronous call. |
1644 | template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs> |
1645 | Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler, |
1646 | const ArgTs &... Args) { |
1647 | // Increment the count of outstanding calls. This has to happen before |
1648 | // we invoke the call, as the handler may (depending on scheduling) |
1649 | // be run immediately on another thread, and we don't want the decrement |
1650 | // in the wrapped handler below to run before the increment. |
1651 | { |
1652 | std::unique_lock<std::mutex> Lock(M); |
1653 | ++NumOutstandingCalls; |
1654 | } |
1655 | |
1656 | // Wrap the user handler in a lambda that will decrement the |
1657 | // outstanding calls count, then poke the condition variable. |
1658 | using ArgType = typename detail::ResponseHandlerArg< |
1659 | typename detail::HandlerTraits<HandlerT>::Type>::ArgType; |
1660 | // FIXME: Move handler into wrapped handler once we have C++14. |
1661 | auto WrappedHandler = [this, Handler](ArgType Arg) { |
1662 | auto Err = Handler(std::move(Arg)); |
1663 | std::unique_lock<std::mutex> Lock(M); |
1664 | --NumOutstandingCalls; |
1665 | CV.notify_all(); |
1666 | return Err; |
1667 | }; |
1668 | |
1669 | return AsyncDispatch(std::move(WrappedHandler), Args...); |
1670 | } |
1671 | |
1672 | /// \brief Blocks until all calls have been completed and their return value |
1673 | /// handlers run. |
1674 | void wait() { |
1675 | std::unique_lock<std::mutex> Lock(M); |
1676 | while (NumOutstandingCalls > 0) |
1677 | CV.wait(Lock); |
1678 | } |
1679 | |
1680 | private: |
1681 | std::mutex M; |
1682 | std::condition_variable CV; |
1683 | uint32_t NumOutstandingCalls = 0; |
1684 | }; |
1685 | |
1686 | /// @brief Convenience class for grouping RPC Functions into APIs that can be |
1687 | /// negotiated as a block. |
1688 | /// |
1689 | template <typename... Funcs> |
1690 | class APICalls { |
1691 | public: |
1692 | |
1693 | /// @brief Test whether this API contains Function F. |
1694 | template <typename F> |
1695 | class Contains { |
1696 | public: |
1697 | static const bool value = false; |
1698 | }; |
1699 | |
1700 | /// @brief Negotiate all functions in this API. |
1701 | template <typename RPCEndpoint> |
1702 | static Error negotiate(RPCEndpoint &R) { |
1703 | return Error::success(); |
1704 | } |
1705 | }; |
1706 | |
1707 | template <typename Func, typename... Funcs> |
1708 | class APICalls<Func, Funcs...> { |
1709 | public: |
1710 | |
1711 | template <typename F> |
1712 | class Contains { |
1713 | public: |
1714 | static const bool value = std::is_same<F, Func>::value | |
1715 | APICalls<Funcs...>::template Contains<F>::value; |
1716 | }; |
1717 | |
1718 | template <typename RPCEndpoint> |
1719 | static Error negotiate(RPCEndpoint &R) { |
1720 | if (auto Err = R.template negotiateFunction<Func>()) |
1721 | return Err; |
1722 | return APICalls<Funcs...>::negotiate(R); |
1723 | } |
1724 | |
1725 | }; |
1726 | |
1727 | template <typename... InnerFuncs, typename... Funcs> |
1728 | class APICalls<APICalls<InnerFuncs...>, Funcs...> { |
1729 | public: |
1730 | |
1731 | template <typename F> |
1732 | class Contains { |
1733 | public: |
1734 | static const bool value = |
1735 | APICalls<InnerFuncs...>::template Contains<F>::value | |
1736 | APICalls<Funcs...>::template Contains<F>::value; |
1737 | }; |
1738 | |
1739 | template <typename RPCEndpoint> |
1740 | static Error negotiate(RPCEndpoint &R) { |
1741 | if (auto Err = APICalls<InnerFuncs...>::negotiate(R)) |
1742 | return Err; |
1743 | return APICalls<Funcs...>::negotiate(R); |
1744 | } |
1745 | |
1746 | }; |
1747 | |
1748 | } // end namespace rpc |
1749 | } // end namespace orc |
1750 | } // end namespace llvm |
1751 | |
1752 | #endif |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file defines an API used to report recoverable errors. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_ERROR_H |
15 | #define LLVM_SUPPORT_ERROR_H |
16 | |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ADT/STLExtras.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/ADT/Twine.h" |
21 | #include "llvm/Config/abi-breaking.h" |
22 | #include "llvm/Support/AlignOf.h" |
23 | #include "llvm/Support/Compiler.h" |
24 | #include "llvm/Support/Debug.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/ErrorOr.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include <algorithm> |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | #include <cstdlib> |
32 | #include <functional> |
33 | #include <memory> |
34 | #include <new> |
35 | #include <string> |
36 | #include <system_error> |
37 | #include <type_traits> |
38 | #include <utility> |
39 | #include <vector> |
40 | |
41 | namespace llvm { |
42 | |
43 | class ErrorSuccess; |
44 | |
45 | /// Base class for error info classes. Do not extend this directly: Extend |
46 | /// the ErrorInfo template subclass instead. |
47 | class ErrorInfoBase { |
48 | public: |
49 | virtual ~ErrorInfoBase() = default; |
50 | |
51 | /// Print an error message to an output stream. |
52 | virtual void log(raw_ostream &OS) const = 0; |
53 | |
54 | /// Return the error message as a string. |
55 | virtual std::string message() const { |
56 | std::string Msg; |
57 | raw_string_ostream OS(Msg); |
58 | log(OS); |
59 | return OS.str(); |
60 | } |
61 | |
62 | /// Convert this error to a std::error_code. |
63 | /// |
64 | /// This is a temporary crutch to enable interaction with code still |
65 | /// using std::error_code. It will be removed in the future. |
66 | virtual std::error_code convertToErrorCode() const = 0; |
67 | |
68 | // Returns the class ID for this type. |
69 | static const void *classID() { return &ID; } |
70 | |
71 | // Returns the class ID for the dynamic type of this ErrorInfoBase instance. |
72 | virtual const void *dynamicClassID() const = 0; |
73 | |
74 | // Check whether this instance is a subclass of the class identified by |
75 | // ClassID. |
76 | virtual bool isA(const void *const ClassID) const { |
77 | return ClassID == classID(); |
78 | } |
79 | |
80 | // Check whether this instance is a subclass of ErrorInfoT. |
81 | template <typename ErrorInfoT> bool isA() const { |
82 | return isA(ErrorInfoT::classID()); |
83 | } |
84 | |
85 | private: |
86 | virtual void anchor(); |
87 | |
88 | static char ID; |
89 | }; |
90 | |
91 | /// Lightweight error class with error context and mandatory checking. |
92 | /// |
93 | /// Instances of this class wrap a ErrorInfoBase pointer. Failure states |
94 | /// are represented by setting the pointer to a ErrorInfoBase subclass |
95 | /// instance containing information describing the failure. Success is |
96 | /// represented by a null pointer value. |
97 | /// |
98 | /// Instances of Error also contains a 'Checked' flag, which must be set |
99 | /// before the destructor is called, otherwise the destructor will trigger a |
100 | /// runtime error. This enforces at runtime the requirement that all Error |
101 | /// instances be checked or returned to the caller. |
102 | /// |
103 | /// There are two ways to set the checked flag, depending on what state the |
104 | /// Error instance is in. For Error instances indicating success, it |
105 | /// is sufficient to invoke the boolean conversion operator. E.g.: |
106 | /// |
107 | /// @code{.cpp} |
108 | /// Error foo(<...>); |
109 | /// |
110 | /// if (auto E = foo(<...>)) |
111 | /// return E; // <- Return E if it is in the error state. |
112 | /// // We have verified that E was in the success state. It can now be safely |
113 | /// // destroyed. |
114 | /// @endcode |
115 | /// |
116 | /// A success value *can not* be dropped. For example, just calling 'foo(<...>)' |
117 | /// without testing the return value will raise a runtime error, even if foo |
118 | /// returns success. |
119 | /// |
120 | /// For Error instances representing failure, you must use either the |
121 | /// handleErrors or handleAllErrors function with a typed handler. E.g.: |
122 | /// |
123 | /// @code{.cpp} |
124 | /// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { |
125 | /// // Custom error info. |
126 | /// }; |
127 | /// |
128 | /// Error foo(<...>) { return make_error<MyErrorInfo>(...); } |
129 | /// |
130 | /// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. |
131 | /// auto NewE = |
132 | /// handleErrors(E, |
133 | /// [](const MyErrorInfo &M) { |
134 | /// // Deal with the error. |
135 | /// }, |
136 | /// [](std::unique_ptr<OtherError> M) -> Error { |
137 | /// if (canHandle(*M)) { |
138 | /// // handle error. |
139 | /// return Error::success(); |
140 | /// } |
141 | /// // Couldn't handle this error instance. Pass it up the stack. |
142 | /// return Error(std::move(M)); |
143 | /// ); |
144 | /// // Note - we must check or return NewE in case any of the handlers |
145 | /// // returned a new error. |
146 | /// @endcode |
147 | /// |
148 | /// The handleAllErrors function is identical to handleErrors, except |
149 | /// that it has a void return type, and requires all errors to be handled and |
150 | /// no new errors be returned. It prevents errors (assuming they can all be |
151 | /// handled) from having to be bubbled all the way to the top-level. |
152 | /// |
153 | /// *All* Error instances must be checked before destruction, even if |
154 | /// they're moved-assigned or constructed from Success values that have already |
155 | /// been checked. This enforces checking through all levels of the call stack. |
156 | class LLVM_NODISCARD[[clang::warn_unused_result]] Error { |
157 | // ErrorList needs to be able to yank ErrorInfoBase pointers out of this |
158 | // class to add to the error list. |
159 | friend class ErrorList; |
160 | |
161 | // handleErrors needs to be able to set the Checked flag. |
162 | template <typename... HandlerTs> |
163 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
164 | |
165 | // Expected<T> needs to be able to steal the payload when constructed from an |
166 | // error. |
167 | template <typename T> friend class Expected; |
168 | |
169 | protected: |
170 | /// Create a success value. Prefer using 'Error::success()' for readability |
171 | Error() { |
172 | setPtr(nullptr); |
173 | setChecked(false); |
174 | } |
175 | |
176 | public: |
177 | /// Create a success value. |
178 | static ErrorSuccess success(); |
179 | |
180 | // Errors are not copy-constructable. |
181 | Error(const Error &Other) = delete; |
182 | |
183 | /// Move-construct an error value. The newly constructed error is considered |
184 | /// unchecked, even if the source error had been checked. The original error |
185 | /// becomes a checked Success value, regardless of its original state. |
186 | Error(Error &&Other) { |
187 | setChecked(true); |
188 | *this = std::move(Other); |
189 | } |
190 | |
191 | /// Create an error value. Prefer using the 'make_error' function, but |
192 | /// this constructor can be useful when "re-throwing" errors from handlers. |
193 | Error(std::unique_ptr<ErrorInfoBase> Payload) { |
194 | setPtr(Payload.release()); |
195 | setChecked(false); |
196 | } |
197 | |
198 | // Errors are not copy-assignable. |
199 | Error &operator=(const Error &Other) = delete; |
200 | |
201 | /// Move-assign an error value. The current error must represent success, you |
202 | /// you cannot overwrite an unhandled error. The current error is then |
203 | /// considered unchecked. The source error becomes a checked success value, |
204 | /// regardless of its original state. |
205 | Error &operator=(Error &&Other) { |
206 | // Don't allow overwriting of unchecked values. |
207 | assertIsChecked(); |
208 | setPtr(Other.getPtr()); |
209 | |
210 | // This Error is unchecked, even if the source error was checked. |
211 | setChecked(false); |
212 | |
213 | // Null out Other's payload and set its checked bit. |
214 | Other.setPtr(nullptr); |
215 | Other.setChecked(true); |
216 | |
217 | return *this; |
218 | } |
219 | |
220 | /// Destroy a Error. Fails with a call to abort() if the error is |
221 | /// unchecked. |
222 | ~Error() { |
223 | assertIsChecked(); |
224 | delete getPtr(); |
225 | } |
226 | |
227 | /// Bool conversion. Returns true if this Error is in a failure state, |
228 | /// and false if it is in an accept state. If the error is in a Success state |
229 | /// it will be considered checked. |
230 | explicit operator bool() { |
231 | setChecked(getPtr() == nullptr); |
232 | return getPtr() != nullptr; |
233 | } |
234 | |
235 | /// Check whether one error is a subclass of another. |
236 | template <typename ErrT> bool isA() const { |
237 | return getPtr() && getPtr()->isA(ErrT::classID()); |
238 | } |
239 | |
240 | /// Returns the dynamic class id of this error, or null if this is a success |
241 | /// value. |
242 | const void* dynamicClassID() const { |
243 | if (!getPtr()) |
244 | return nullptr; |
245 | return getPtr()->dynamicClassID(); |
246 | } |
247 | |
248 | private: |
249 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
250 | // assertIsChecked() happens very frequently, but under normal circumstances |
251 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch |
252 | // of debug prints can cause the function to be too large for inlining. So |
253 | // it's important that we define this function out of line so that it can't be |
254 | // inlined. |
255 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
256 | void fatalUncheckedError() const; |
257 | #endif |
258 | |
259 | void assertIsChecked() { |
260 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
261 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) |
262 | fatalUncheckedError(); |
263 | #endif |
264 | } |
265 | |
266 | ErrorInfoBase *getPtr() const { |
267 | return reinterpret_cast<ErrorInfoBase*>( |
268 | reinterpret_cast<uintptr_t>(Payload) & |
269 | ~static_cast<uintptr_t>(0x1)); |
270 | } |
271 | |
272 | void setPtr(ErrorInfoBase *EI) { |
273 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
274 | Payload = reinterpret_cast<ErrorInfoBase*>( |
275 | (reinterpret_cast<uintptr_t>(EI) & |
276 | ~static_cast<uintptr_t>(0x1)) | |
277 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); |
278 | #else |
279 | Payload = EI; |
280 | #endif |
281 | } |
282 | |
283 | bool getChecked() const { |
284 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
285 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; |
286 | #else |
287 | return true; |
288 | #endif |
289 | } |
290 | |
291 | void setChecked(bool V) { |
292 | Payload = reinterpret_cast<ErrorInfoBase*>( |
293 | (reinterpret_cast<uintptr_t>(Payload) & |
294 | ~static_cast<uintptr_t>(0x1)) | |
295 | (V ? 0 : 1)); |
296 | } |
297 | |
298 | std::unique_ptr<ErrorInfoBase> takePayload() { |
299 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); |
300 | setPtr(nullptr); |
301 | setChecked(true); |
302 | return Tmp; |
303 | } |
304 | |
305 | ErrorInfoBase *Payload = nullptr; |
306 | }; |
307 | |
308 | /// Subclass of Error for the sole purpose of identifying the success path in |
309 | /// the type system. This allows to catch invalid conversion to Expected<T> at |
310 | /// compile time. |
311 | class ErrorSuccess : public Error {}; |
312 | |
313 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } |
314 | |
315 | /// Make a Error instance representing failure using the given error info |
316 | /// type. |
317 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { |
318 | return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); |
319 | } |
320 | |
321 | /// Base class for user error types. Users should declare their error types |
322 | /// like: |
323 | /// |
324 | /// class MyError : public ErrorInfo<MyError> { |
325 | /// .... |
326 | /// }; |
327 | /// |
328 | /// This class provides an implementation of the ErrorInfoBase::kind |
329 | /// method, which is used by the Error RTTI system. |
330 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> |
331 | class ErrorInfo : public ParentErrT { |
332 | public: |
333 | static const void *classID() { return &ThisErrT::ID; } |
334 | |
335 | const void *dynamicClassID() const override { return &ThisErrT::ID; } |
336 | |
337 | bool isA(const void *const ClassID) const override { |
338 | return ClassID == classID() || ParentErrT::isA(ClassID); |
339 | } |
340 | }; |
341 | |
342 | /// Special ErrorInfo subclass representing a list of ErrorInfos. |
343 | /// Instances of this class are constructed by joinError. |
344 | class ErrorList final : public ErrorInfo<ErrorList> { |
345 | // handleErrors needs to be able to iterate the payload list of an |
346 | // ErrorList. |
347 | template <typename... HandlerTs> |
348 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
349 | |
350 | // joinErrors is implemented in terms of join. |
351 | friend Error joinErrors(Error, Error); |
352 | |
353 | public: |
354 | void log(raw_ostream &OS) const override { |
355 | OS << "Multiple errors:\n"; |
356 | for (auto &ErrPayload : Payloads) { |
357 | ErrPayload->log(OS); |
358 | OS << "\n"; |
359 | } |
360 | } |
361 | |
362 | std::error_code convertToErrorCode() const override; |
363 | |
364 | // Used by ErrorInfo::classID. |
365 | static char ID; |
366 | |
367 | private: |
368 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, |
369 | std::unique_ptr<ErrorInfoBase> Payload2) { |
370 | assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)) |
371 | "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)); |
372 | Payloads.push_back(std::move(Payload1)); |
373 | Payloads.push_back(std::move(Payload2)); |
374 | } |
375 | |
376 | static Error join(Error E1, Error E2) { |
377 | if (!E1) |
378 | return E2; |
379 | if (!E2) |
380 | return E1; |
381 | if (E1.isA<ErrorList>()) { |
382 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); |
383 | if (E2.isA<ErrorList>()) { |
384 | auto E2Payload = E2.takePayload(); |
385 | auto &E2List = static_cast<ErrorList &>(*E2Payload); |
386 | for (auto &Payload : E2List.Payloads) |
387 | E1List.Payloads.push_back(std::move(Payload)); |
388 | } else |
389 | E1List.Payloads.push_back(E2.takePayload()); |
390 | |
391 | return E1; |
392 | } |
393 | if (E2.isA<ErrorList>()) { |
394 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); |
395 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); |
396 | return E2; |
397 | } |
398 | return Error(std::unique_ptr<ErrorList>( |
399 | new ErrorList(E1.takePayload(), E2.takePayload()))); |
400 | } |
401 | |
402 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; |
403 | }; |
404 | |
405 | /// Concatenate errors. The resulting Error is unchecked, and contains the |
406 | /// ErrorInfo(s), if any, contained in E1, followed by the |
407 | /// ErrorInfo(s), if any, contained in E2. |
408 | inline Error joinErrors(Error E1, Error E2) { |
409 | return ErrorList::join(std::move(E1), std::move(E2)); |
410 | } |
411 | |
412 | /// Tagged union holding either a T or a Error. |
413 | /// |
414 | /// This class parallels ErrorOr, but replaces error_code with Error. Since |
415 | /// Error cannot be copied, this class replaces getError() with |
416 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the |
417 | /// error class type. |
418 | template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected { |
419 | template <class T1> friend class ExpectedAsOutParameter; |
420 | template <class OtherT> friend class Expected; |
421 | |
422 | static const bool isRef = std::is_reference<T>::value; |
423 | |
424 | using wrap = ReferenceStorage<typename std::remove_reference<T>::type>; |
425 | |
426 | using error_type = std::unique_ptr<ErrorInfoBase>; |
427 | |
428 | public: |
429 | using storage_type = typename std::conditional<isRef, wrap, T>::type; |
430 | using value_type = T; |
431 | |
432 | private: |
433 | using reference = typename std::remove_reference<T>::type &; |
434 | using const_reference = const typename std::remove_reference<T>::type &; |
435 | using pointer = typename std::remove_reference<T>::type *; |
436 | using const_pointer = const typename std::remove_reference<T>::type *; |
437 | |
438 | public: |
439 | /// Create an Expected<T> error value from the given Error. |
440 | Expected(Error Err) |
441 | : HasError(true) |
442 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
443 | // Expected is unchecked upon construction in Debug builds. |
444 | , Unchecked(true) |
445 | #endif |
446 | { |
447 | assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value." ) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 447, __extension__ __PRETTY_FUNCTION__)); |
448 | new (getErrorStorage()) error_type(Err.takePayload()); |
449 | } |
450 | |
451 | /// Forbid to convert from Error::success() implicitly, this avoids having |
452 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise |
453 | /// but triggers the assertion above. |
454 | Expected(ErrorSuccess) = delete; |
455 | |
456 | /// Create an Expected<T> success value from the given OtherT value, which |
457 | /// must be convertible to T. |
458 | template <typename OtherT> |
459 | Expected(OtherT &&Val, |
460 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
461 | * = nullptr) |
462 | : HasError(false) |
463 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
464 | // Expected is unchecked upon construction in Debug builds. |
465 | , Unchecked(true) |
466 | #endif |
467 | { |
468 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); |
469 | } |
470 | |
471 | /// Move construct an Expected<T> value. |
472 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } |
473 | |
474 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
475 | /// must be convertible to T. |
476 | template <class OtherT> |
477 | Expected(Expected<OtherT> &&Other, |
478 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
479 | * = nullptr) { |
480 | moveConstruct(std::move(Other)); |
481 | } |
482 | |
483 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
484 | /// isn't convertible to T. |
485 | template <class OtherT> |
486 | explicit Expected( |
487 | Expected<OtherT> &&Other, |
488 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = |
489 | nullptr) { |
490 | moveConstruct(std::move(Other)); |
491 | } |
492 | |
493 | /// Move-assign from another Expected<T>. |
494 | Expected &operator=(Expected &&Other) { |
495 | moveAssign(std::move(Other)); |
496 | return *this; |
497 | } |
498 | |
499 | /// Destroy an Expected<T>. |
500 | ~Expected() { |
501 | assertIsChecked(); |
502 | if (!HasError) |
503 | getStorage()->~storage_type(); |
504 | else |
505 | getErrorStorage()->~error_type(); |
506 | } |
507 | |
508 | /// \brief Return false if there is an error. |
509 | explicit operator bool() { |
510 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
511 | Unchecked = HasError; |
512 | #endif |
513 | return !HasError; |
514 | } |
515 | |
516 | /// \brief Returns a reference to the stored T value. |
517 | reference get() { |
518 | assertIsChecked(); |
519 | return *getStorage(); |
520 | } |
521 | |
522 | /// \brief Returns a const reference to the stored T value. |
523 | const_reference get() const { |
524 | assertIsChecked(); |
525 | return const_cast<Expected<T> *>(this)->get(); |
526 | } |
527 | |
528 | /// \brief Check that this Expected<T> is an error of type ErrT. |
529 | template <typename ErrT> bool errorIsA() const { |
530 | return HasError && (*getErrorStorage())->template isA<ErrT>(); |
531 | } |
532 | |
533 | /// \brief Take ownership of the stored error. |
534 | /// After calling this the Expected<T> is in an indeterminate state that can |
535 | /// only be safely destructed. No further calls (beside the destructor) should |
536 | /// be made on the Expected<T> vaule. |
537 | Error takeError() { |
538 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
539 | Unchecked = false; |
540 | #endif |
541 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); |
542 | } |
543 | |
544 | /// \brief Returns a pointer to the stored T value. |
545 | pointer operator->() { |
546 | assertIsChecked(); |
547 | return toPointer(getStorage()); |
548 | } |
549 | |
550 | /// \brief Returns a const pointer to the stored T value. |
551 | const_pointer operator->() const { |
552 | assertIsChecked(); |
553 | return toPointer(getStorage()); |
554 | } |
555 | |
556 | /// \brief Returns a reference to the stored T value. |
557 | reference operator*() { |
558 | assertIsChecked(); |
559 | return *getStorage(); |
560 | } |
561 | |
562 | /// \brief Returns a const reference to the stored T value. |
563 | const_reference operator*() const { |
564 | assertIsChecked(); |
565 | return *getStorage(); |
566 | } |
567 | |
568 | private: |
569 | template <class T1> |
570 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { |
571 | return &a == &b; |
572 | } |
573 | |
574 | template <class T1, class T2> |
575 | static bool compareThisIfSameType(const T1 &a, const T2 &b) { |
576 | return false; |
577 | } |
578 | |
579 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { |
580 | HasError = Other.HasError; |
581 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
582 | Unchecked = true; |
583 | Other.Unchecked = false; |
584 | #endif |
585 | |
586 | if (!HasError) |
587 | new (getStorage()) storage_type(std::move(*Other.getStorage())); |
588 | else |
589 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); |
590 | } |
591 | |
592 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { |
593 | assertIsChecked(); |
594 | |
595 | if (compareThisIfSameType(*this, Other)) |
596 | return; |
597 | |
598 | this->~Expected(); |
599 | new (this) Expected(std::move(Other)); |
600 | } |
601 | |
602 | pointer toPointer(pointer Val) { return Val; } |
603 | |
604 | const_pointer toPointer(const_pointer Val) const { return Val; } |
605 | |
606 | pointer toPointer(wrap *Val) { return &Val->get(); } |
607 | |
608 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } |
609 | |
610 | storage_type *getStorage() { |
611 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 611, __extension__ __PRETTY_FUNCTION__)); |
612 | return reinterpret_cast<storage_type *>(TStorage.buffer); |
613 | } |
614 | |
615 | const storage_type *getStorage() const { |
616 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 616, __extension__ __PRETTY_FUNCTION__)); |
617 | return reinterpret_cast<const storage_type *>(TStorage.buffer); |
618 | } |
619 | |
620 | error_type *getErrorStorage() { |
621 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 621, __extension__ __PRETTY_FUNCTION__)); |
622 | return reinterpret_cast<error_type *>(ErrorStorage.buffer); |
623 | } |
624 | |
625 | const error_type *getErrorStorage() const { |
626 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 626, __extension__ __PRETTY_FUNCTION__)); |
627 | return reinterpret_cast<const error_type *>(ErrorStorage.buffer); |
628 | } |
629 | |
630 | // Used by ExpectedAsOutParameter to reset the checked flag. |
631 | void setUnchecked() { |
632 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
633 | Unchecked = true; |
634 | #endif |
635 | } |
636 | |
637 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
638 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
639 | LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) |
640 | void fatalUncheckedExpected() const { |
641 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; |
642 | if (HasError) { |
643 | dbgs() << "Unchecked Expected<T> contained error:\n"; |
644 | (*getErrorStorage())->log(dbgs()); |
645 | } else |
646 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " |
647 | "values in success mode must still be checked prior to being " |
648 | "destroyed).\n"; |
649 | abort(); |
650 | } |
651 | #endif |
652 | |
653 | void assertIsChecked() { |
654 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
655 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) |
656 | fatalUncheckedExpected(); |
657 | #endif |
658 | } |
659 | |
660 | union { |
661 | AlignedCharArrayUnion<storage_type> TStorage; |
662 | AlignedCharArrayUnion<error_type> ErrorStorage; |
663 | }; |
664 | bool HasError : 1; |
665 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
666 | bool Unchecked : 1; |
667 | #endif |
668 | }; |
669 | |
670 | /// Report a serious error, calling any installed error handler. See |
671 | /// ErrorHandling.h. |
672 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err, |
673 | bool gen_crash_diag = true); |
674 | |
675 | /// Report a fatal error if Err is a failure value. |
676 | /// |
677 | /// This function can be used to wrap calls to fallible functions ONLY when it |
678 | /// is known that the Error will always be a success value. E.g. |
679 | /// |
680 | /// @code{.cpp} |
681 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
682 | /// // true. If DoFallibleOperation is false then foo always returns |
683 | /// // Error::success(). |
684 | /// Error foo(bool DoFallibleOperation); |
685 | /// |
686 | /// cantFail(foo(false)); |
687 | /// @endcode |
688 | inline void cantFail(Error Err, const char *Msg = nullptr) { |
689 | if (Err) { |
690 | if (!Msg) |
691 | Msg = "Failure value returned from cantFail wrapped call"; |
692 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 692); |
693 | } |
694 | } |
695 | |
696 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
697 | /// returns the contained value. |
698 | /// |
699 | /// This function can be used to wrap calls to fallible functions ONLY when it |
700 | /// is known that the Error will always be a success value. E.g. |
701 | /// |
702 | /// @code{.cpp} |
703 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
704 | /// // true. If DoFallibleOperation is false then foo always returns an int. |
705 | /// Expected<int> foo(bool DoFallibleOperation); |
706 | /// |
707 | /// int X = cantFail(foo(false)); |
708 | /// @endcode |
709 | template <typename T> |
710 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { |
711 | if (ValOrErr) |
712 | return std::move(*ValOrErr); |
713 | else { |
714 | if (!Msg) |
715 | Msg = "Failure value returned from cantFail wrapped call"; |
716 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 716); |
717 | } |
718 | } |
719 | |
720 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
721 | /// returns the contained reference. |
722 | /// |
723 | /// This function can be used to wrap calls to fallible functions ONLY when it |
724 | /// is known that the Error will always be a success value. E.g. |
725 | /// |
726 | /// @code{.cpp} |
727 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
728 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. |
729 | /// Expected<Bar&> foo(bool DoFallibleOperation); |
730 | /// |
731 | /// Bar &X = cantFail(foo(false)); |
732 | /// @endcode |
733 | template <typename T> |
734 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { |
735 | if (ValOrErr) |
736 | return *ValOrErr; |
737 | else { |
738 | if (!Msg) |
739 | Msg = "Failure value returned from cantFail wrapped call"; |
740 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 740); |
741 | } |
742 | } |
743 | |
744 | /// Helper for testing applicability of, and applying, handlers for |
745 | /// ErrorInfo types. |
746 | template <typename HandlerT> |
747 | class ErrorHandlerTraits |
748 | : public ErrorHandlerTraits<decltype( |
749 | &std::remove_reference<HandlerT>::type::operator())> {}; |
750 | |
751 | // Specialization functions of the form 'Error (const ErrT&)'. |
752 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { |
753 | public: |
754 | static bool appliesTo(const ErrorInfoBase &E) { |
755 | return E.template isA<ErrT>(); |
756 | } |
757 | |
758 | template <typename HandlerT> |
759 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
760 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 760, __extension__ __PRETTY_FUNCTION__)); |
761 | return H(static_cast<ErrT &>(*E)); |
762 | } |
763 | }; |
764 | |
765 | // Specialization functions of the form 'void (const ErrT&)'. |
766 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { |
767 | public: |
768 | static bool appliesTo(const ErrorInfoBase &E) { |
769 | return E.template isA<ErrT>(); |
770 | } |
771 | |
772 | template <typename HandlerT> |
773 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
774 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 774, __extension__ __PRETTY_FUNCTION__)); |
775 | H(static_cast<ErrT &>(*E)); |
776 | return Error::success(); |
777 | } |
778 | }; |
779 | |
780 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. |
781 | template <typename ErrT> |
782 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { |
783 | public: |
784 | static bool appliesTo(const ErrorInfoBase &E) { |
785 | return E.template isA<ErrT>(); |
786 | } |
787 | |
788 | template <typename HandlerT> |
789 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
790 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 790, __extension__ __PRETTY_FUNCTION__)); |
791 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
792 | return H(std::move(SubE)); |
793 | } |
794 | }; |
795 | |
796 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. |
797 | template <typename ErrT> |
798 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { |
799 | public: |
800 | static bool appliesTo(const ErrorInfoBase &E) { |
801 | return E.template isA<ErrT>(); |
802 | } |
803 | |
804 | template <typename HandlerT> |
805 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
806 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h" , 806, __extension__ __PRETTY_FUNCTION__)); |
807 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
808 | H(std::move(SubE)); |
809 | return Error::success(); |
810 | } |
811 | }; |
812 | |
813 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
814 | template <typename C, typename RetT, typename ErrT> |
815 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> |
816 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
817 | |
818 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
819 | template <typename C, typename RetT, typename ErrT> |
820 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> |
821 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
822 | |
823 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
824 | template <typename C, typename RetT, typename ErrT> |
825 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> |
826 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
827 | |
828 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
829 | template <typename C, typename RetT, typename ErrT> |
830 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> |
831 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
832 | |
833 | /// Specialization for member functions of the form |
834 | /// 'RetT (std::unique_ptr<ErrT>)'. |
835 | template <typename C, typename RetT, typename ErrT> |
836 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> |
837 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
838 | |
839 | /// Specialization for member functions of the form |
840 | /// 'RetT (std::unique_ptr<ErrT>) const'. |
841 | template <typename C, typename RetT, typename ErrT> |
842 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> |
843 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
844 | |
845 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { |
846 | return Error(std::move(Payload)); |
847 | } |
848 | |
849 | template <typename HandlerT, typename... HandlerTs> |
850 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, |
851 | HandlerT &&Handler, HandlerTs &&... Handlers) { |
852 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) |
853 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), |
854 | std::move(Payload)); |
855 | return handleErrorImpl(std::move(Payload), |
856 | std::forward<HandlerTs>(Handlers)...); |
857 | } |
858 | |
859 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any |
860 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and |
861 | /// returned. |
862 | /// Because this function returns an error, its result must also be checked |
863 | /// or returned. If you intend to handle all errors use handleAllErrors |
864 | /// (which returns void, and will abort() on unhandled errors) instead. |
865 | template <typename... HandlerTs> |
866 | Error handleErrors(Error E, HandlerTs &&... Hs) { |
867 | if (!E) |
868 | return Error::success(); |
869 | |
870 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); |
871 | |
872 | if (Payload->isA<ErrorList>()) { |
873 | ErrorList &List = static_cast<ErrorList &>(*Payload); |
874 | Error R; |
875 | for (auto &P : List.Payloads) |
876 | R = ErrorList::join( |
877 | std::move(R), |
878 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); |
879 | return R; |
880 | } |
881 | |
882 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); |
883 | } |
884 | |
885 | /// Behaves the same as handleErrors, except that it requires that all |
886 | /// errors be handled by the given handlers. If any unhandled error remains |
887 | /// after the handlers have run, report_fatal_error() will be called. |
888 | template <typename... HandlerTs> |
889 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { |
890 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); |
891 | } |
892 | |
893 | /// Check that E is a non-error, then drop it. |
894 | /// If E is an error report_fatal_error will be called. |
895 | inline void handleAllErrors(Error E) { |
896 | cantFail(std::move(E)); |
897 | } |
898 | |
899 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. |
900 | /// |
901 | /// If the incoming value is a success value it is returned unmodified. If it |
902 | /// is a failure value then it the contained error is passed to handleErrors. |
903 | /// If handleErrors is able to handle the error then the RecoveryPath functor |
904 | /// is called to supply the final result. If handleErrors is not able to |
905 | /// handle all errors then the unhandled errors are returned. |
906 | /// |
907 | /// This utility enables the follow pattern: |
908 | /// |
909 | /// @code{.cpp} |
910 | /// enum FooStrategy { Aggressive, Conservative }; |
911 | /// Expected<Foo> foo(FooStrategy S); |
912 | /// |
913 | /// auto ResultOrErr = |
914 | /// handleExpected( |
915 | /// foo(Aggressive), |
916 | /// []() { return foo(Conservative); }, |
917 | /// [](AggressiveStrategyError&) { |
918 | /// // Implicitly conusme this - we'll recover by using a conservative |
919 | /// // strategy. |
920 | /// }); |
921 | /// |
922 | /// @endcode |
923 | template <typename T, typename RecoveryFtor, typename... HandlerTs> |
924 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, |
925 | HandlerTs &&... Handlers) { |
926 | if (ValOrErr) |
927 | return ValOrErr; |
928 | |
929 | if (auto Err = handleErrors(ValOrErr.takeError(), |
930 | std::forward<HandlerTs>(Handlers)...)) |
931 | return std::move(Err); |
932 | |
933 | return RecoveryPath(); |
934 | } |
935 | |
936 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner |
937 | /// will be printed before the first one is logged. A newline will be printed |
938 | /// after each error. |
939 | /// |
940 | /// This is useful in the base level of your program to allow clean termination |
941 | /// (allowing clean deallocation of resources, etc.), while reporting error |
942 | /// information to the user. |
943 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); |
944 | |
945 | /// Write all error messages (if any) in E to a string. The newline character |
946 | /// is used to separate error messages. |
947 | inline std::string toString(Error E) { |
948 | SmallVector<std::string, 2> Errors; |
949 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { |
950 | Errors.push_back(EI.message()); |
951 | }); |
952 | return join(Errors.begin(), Errors.end(), "\n"); |
953 | } |
954 | |
955 | /// Consume a Error without doing anything. This method should be used |
956 | /// only where an error can be considered a reasonable and expected return |
957 | /// value. |
958 | /// |
959 | /// Uses of this method are potentially indicative of design problems: If it's |
960 | /// legitimate to do nothing while processing an "error", the error-producer |
961 | /// might be more clearly refactored to return an Optional<T>. |
962 | inline void consumeError(Error Err) { |
963 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); |
964 | } |
965 | |
966 | /// Helper for Errors used as out-parameters. |
967 | /// |
968 | /// This helper is for use with the Error-as-out-parameter idiom, where an error |
969 | /// is passed to a function or method by reference, rather than being returned. |
970 | /// In such cases it is helpful to set the checked bit on entry to the function |
971 | /// so that the error can be written to (unchecked Errors abort on assignment) |
972 | /// and clear the checked bit on exit so that clients cannot accidentally forget |
973 | /// to check the result. This helper performs these actions automatically using |
974 | /// RAII: |
975 | /// |
976 | /// @code{.cpp} |
977 | /// Result foo(Error &Err) { |
978 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set |
979 | /// // <body of foo> |
980 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. |
981 | /// } |
982 | /// @endcode |
983 | /// |
984 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be |
985 | /// used with optional Errors (Error pointers that are allowed to be null). If |
986 | /// ErrorAsOutParameter took an Error reference, an instance would have to be |
987 | /// created inside every condition that verified that Error was non-null. By |
988 | /// taking an Error pointer we can just create one instance at the top of the |
989 | /// function. |
990 | class ErrorAsOutParameter { |
991 | public: |
992 | ErrorAsOutParameter(Error *Err) : Err(Err) { |
993 | // Raise the checked bit if Err is success. |
994 | if (Err) |
995 | (void)!!*Err; |
996 | } |
997 | |
998 | ~ErrorAsOutParameter() { |
999 | // Clear the checked bit. |
1000 | if (Err && !*Err) |
1001 | *Err = Error::success(); |
1002 | } |
1003 | |
1004 | private: |
1005 | Error *Err; |
1006 | }; |
1007 | |
1008 | /// Helper for Expected<T>s used as out-parameters. |
1009 | /// |
1010 | /// See ErrorAsOutParameter. |
1011 | template <typename T> |
1012 | class ExpectedAsOutParameter { |
1013 | public: |
1014 | ExpectedAsOutParameter(Expected<T> *ValOrErr) |
1015 | : ValOrErr(ValOrErr) { |
1016 | if (ValOrErr) |
1017 | (void)!!*ValOrErr; |
1018 | } |
1019 | |
1020 | ~ExpectedAsOutParameter() { |
1021 | if (ValOrErr) |
1022 | ValOrErr->setUnchecked(); |
1023 | } |
1024 | |
1025 | private: |
1026 | Expected<T> *ValOrErr; |
1027 | }; |
1028 | |
1029 | /// This class wraps a std::error_code in a Error. |
1030 | /// |
1031 | /// This is useful if you're writing an interface that returns a Error |
1032 | /// (or Expected) and you want to call code that still returns |
1033 | /// std::error_codes. |
1034 | class ECError : public ErrorInfo<ECError> { |
1035 | friend Error errorCodeToError(std::error_code); |
1036 | |
1037 | public: |
1038 | void setErrorCode(std::error_code EC) { this->EC = EC; } |
1039 | std::error_code convertToErrorCode() const override { return EC; } |
1040 | void log(raw_ostream &OS) const override { OS << EC.message(); } |
1041 | |
1042 | // Used by ErrorInfo::classID. |
1043 | static char ID; |
1044 | |
1045 | protected: |
1046 | ECError() = default; |
1047 | ECError(std::error_code EC) : EC(EC) {} |
1048 | |
1049 | std::error_code EC; |
1050 | }; |
1051 | |
1052 | /// The value returned by this function can be returned from convertToErrorCode |
1053 | /// for Error values where no sensible translation to std::error_code exists. |
1054 | /// It should only be used in this situation, and should never be used where a |
1055 | /// sensible conversion to std::error_code is available, as attempts to convert |
1056 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic |
1057 | ///error to try to convert such a value). |
1058 | std::error_code inconvertibleErrorCode(); |
1059 | |
1060 | /// Helper for converting an std::error_code to a Error. |
1061 | Error errorCodeToError(std::error_code EC); |
1062 | |
1063 | /// Helper for converting an ECError to a std::error_code. |
1064 | /// |
1065 | /// This method requires that Err be Error() or an ECError, otherwise it |
1066 | /// will trigger a call to abort(). |
1067 | std::error_code errorToErrorCode(Error Err); |
1068 | |
1069 | /// Convert an ErrorOr<T> to an Expected<T>. |
1070 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { |
1071 | if (auto EC = EO.getError()) |
1072 | return errorCodeToError(EC); |
1073 | return std::move(*EO); |
1074 | } |
1075 | |
1076 | /// Convert an Expected<T> to an ErrorOr<T>. |
1077 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { |
1078 | if (auto Err = E.takeError()) |
1079 | return errorToErrorCode(std::move(Err)); |
1080 | return std::move(*E); |
1081 | } |
1082 | |
1083 | /// This class wraps a string in an Error. |
1084 | /// |
1085 | /// StringError is useful in cases where the client is not expected to be able |
1086 | /// to consume the specific error message programmatically (for example, if the |
1087 | /// error message is to be presented to the user). |
1088 | class StringError : public ErrorInfo<StringError> { |
1089 | public: |
1090 | static char ID; |
1091 | |
1092 | StringError(const Twine &S, std::error_code EC); |
1093 | |
1094 | void log(raw_ostream &OS) const override; |
1095 | std::error_code convertToErrorCode() const override; |
1096 | |
1097 | const std::string &getMessage() const { return Msg; } |
1098 | |
1099 | private: |
1100 | std::string Msg; |
1101 | std::error_code EC; |
1102 | }; |
1103 | |
1104 | /// Helper for check-and-exit error handling. |
1105 | /// |
1106 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. |
1107 | /// |
1108 | class ExitOnError { |
1109 | public: |
1110 | /// Create an error on exit helper. |
1111 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) |
1112 | : Banner(std::move(Banner)), |
1113 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} |
1114 | |
1115 | /// Set the banner string for any errors caught by operator(). |
1116 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } |
1117 | |
1118 | /// Set the exit-code mapper function. |
1119 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { |
1120 | this->GetExitCode = std::move(GetExitCode); |
1121 | } |
1122 | |
1123 | /// Check Err. If it's in a failure state log the error(s) and exit. |
1124 | void operator()(Error Err) const { checkError(std::move(Err)); } |
1125 | |
1126 | /// Check E. If it's in a success state then return the contained value. If |
1127 | /// it's in a failure state log the error(s) and exit. |
1128 | template <typename T> T operator()(Expected<T> &&E) const { |
1129 | checkError(E.takeError()); |
1130 | return std::move(*E); |
1131 | } |
1132 | |
1133 | /// Check E. If it's in a success state then return the contained reference. If |
1134 | /// it's in a failure state log the error(s) and exit. |
1135 | template <typename T> T& operator()(Expected<T&> &&E) const { |
1136 | checkError(E.takeError()); |
1137 | return *E; |
1138 | } |
1139 | |
1140 | private: |
1141 | void checkError(Error Err) const { |
1142 | if (Err) { |
1143 | int ExitCode = GetExitCode(Err); |
1144 | logAllUnhandledErrors(std::move(Err), errs(), Banner); |
1145 | exit(ExitCode); |
1146 | } |
1147 | } |
1148 | |
1149 | std::string Banner; |
1150 | std::function<int(const Error &)> GetExitCode; |
1151 | }; |
1152 | |
1153 | } // end namespace llvm |
1154 | |
1155 | #endif // LLVM_SUPPORT_ERROR_H |
1 | //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file contains some templates that are useful if you are working with the | |||
11 | // STL at all. | |||
12 | // | |||
13 | // No library is required when using these functions. | |||
14 | // | |||
15 | //===----------------------------------------------------------------------===// | |||
16 | ||||
17 | #ifndef LLVM_ADT_STLEXTRAS_H | |||
18 | #define LLVM_ADT_STLEXTRAS_H | |||
19 | ||||
20 | #include "llvm/ADT/Optional.h" | |||
21 | #include "llvm/ADT/SmallVector.h" | |||
22 | #include "llvm/ADT/iterator.h" | |||
23 | #include "llvm/ADT/iterator_range.h" | |||
24 | #include "llvm/Support/ErrorHandling.h" | |||
25 | #include <algorithm> | |||
26 | #include <cassert> | |||
27 | #include <cstddef> | |||
28 | #include <cstdint> | |||
29 | #include <cstdlib> | |||
30 | #include <functional> | |||
31 | #include <initializer_list> | |||
32 | #include <iterator> | |||
33 | #include <limits> | |||
34 | #include <memory> | |||
35 | #include <tuple> | |||
36 | #include <type_traits> | |||
37 | #include <utility> | |||
38 | ||||
39 | namespace llvm { | |||
40 | ||||
41 | // Only used by compiler if both template types are the same. Useful when | |||
42 | // using SFINAE to test for the existence of member functions. | |||
43 | template <typename T, T> struct SameType; | |||
44 | ||||
45 | namespace detail { | |||
46 | ||||
47 | template <typename RangeT> | |||
48 | using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); | |||
49 | ||||
50 | template <typename RangeT> | |||
51 | using ValueOfRange = typename std::remove_reference<decltype( | |||
52 | *std::begin(std::declval<RangeT &>()))>::type; | |||
53 | ||||
54 | } // end namespace detail | |||
55 | ||||
56 | //===----------------------------------------------------------------------===// | |||
57 | // Extra additions to <functional> | |||
58 | //===----------------------------------------------------------------------===// | |||
59 | ||||
60 | template <class Ty> struct identity { | |||
61 | using argument_type = Ty; | |||
62 | ||||
63 | Ty &operator()(Ty &self) const { | |||
64 | return self; | |||
65 | } | |||
66 | const Ty &operator()(const Ty &self) const { | |||
67 | return self; | |||
68 | } | |||
69 | }; | |||
70 | ||||
71 | template <class Ty> struct less_ptr { | |||
72 | bool operator()(const Ty* left, const Ty* right) const { | |||
73 | return *left < *right; | |||
74 | } | |||
75 | }; | |||
76 | ||||
77 | template <class Ty> struct greater_ptr { | |||
78 | bool operator()(const Ty* left, const Ty* right) const { | |||
79 | return *right < *left; | |||
80 | } | |||
81 | }; | |||
82 | ||||
83 | /// An efficient, type-erasing, non-owning reference to a callable. This is | |||
84 | /// intended for use as the type of a function parameter that is not used | |||
85 | /// after the function in question returns. | |||
86 | /// | |||
87 | /// This class does not own the callable, so it is not in general safe to store | |||
88 | /// a function_ref. | |||
89 | template<typename Fn> class function_ref; | |||
90 | ||||
91 | template<typename Ret, typename ...Params> | |||
92 | class function_ref<Ret(Params...)> { | |||
93 | Ret (*callback)(intptr_t callable, Params ...params) = nullptr; | |||
94 | intptr_t callable; | |||
95 | ||||
96 | template<typename Callable> | |||
97 | static Ret callback_fn(intptr_t callable, Params ...params) { | |||
98 | return (*reinterpret_cast<Callable*>(callable))( | |||
99 | std::forward<Params>(params)...); | |||
100 | } | |||
101 | ||||
102 | public: | |||
103 | function_ref() = default; | |||
104 | ||||
105 | template <typename Callable> | |||
106 | function_ref(Callable &&callable, | |||
107 | typename std::enable_if< | |||
108 | !std::is_same<typename std::remove_reference<Callable>::type, | |||
109 | function_ref>::value>::type * = nullptr) | |||
110 | : callback(callback_fn<typename std::remove_reference<Callable>::type>), | |||
111 | callable(reinterpret_cast<intptr_t>(&callable)) {} | |||
112 | ||||
113 | Ret operator()(Params ...params) const { | |||
114 | return callback(callable, std::forward<Params>(params)...); | |||
115 | } | |||
116 | ||||
117 | operator bool() const { return callback; } | |||
118 | }; | |||
119 | ||||
120 | // deleter - Very very very simple method that is used to invoke operator | |||
121 | // delete on something. It is used like this: | |||
122 | // | |||
123 | // for_each(V.begin(), B.end(), deleter<Interval>); | |||
124 | template <class T> | |||
125 | inline void deleter(T *Ptr) { | |||
126 | delete Ptr; | |||
127 | } | |||
128 | ||||
129 | //===----------------------------------------------------------------------===// | |||
130 | // Extra additions to <iterator> | |||
131 | //===----------------------------------------------------------------------===// | |||
132 | ||||
133 | namespace adl_detail { | |||
134 | ||||
135 | using std::begin; | |||
136 | ||||
137 | template <typename ContainerTy> | |||
138 | auto adl_begin(ContainerTy &&container) | |||
139 | -> decltype(begin(std::forward<ContainerTy>(container))) { | |||
140 | return begin(std::forward<ContainerTy>(container)); | |||
141 | } | |||
142 | ||||
143 | using std::end; | |||
144 | ||||
145 | template <typename ContainerTy> | |||
146 | auto adl_end(ContainerTy &&container) | |||
147 | -> decltype(end(std::forward<ContainerTy>(container))) { | |||
148 | return end(std::forward<ContainerTy>(container)); | |||
149 | } | |||
150 | ||||
151 | using std::swap; | |||
152 | ||||
153 | template <typename T> | |||
154 | void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), | |||
155 | std::declval<T>()))) { | |||
156 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); | |||
157 | } | |||
158 | ||||
159 | } // end namespace adl_detail | |||
160 | ||||
161 | template <typename ContainerTy> | |||
162 | auto adl_begin(ContainerTy &&container) | |||
163 | -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { | |||
164 | return adl_detail::adl_begin(std::forward<ContainerTy>(container)); | |||
165 | } | |||
166 | ||||
167 | template <typename ContainerTy> | |||
168 | auto adl_end(ContainerTy &&container) | |||
169 | -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { | |||
170 | return adl_detail::adl_end(std::forward<ContainerTy>(container)); | |||
171 | } | |||
172 | ||||
173 | template <typename T> | |||
174 | void adl_swap(T &&lhs, T &&rhs) noexcept( | |||
175 | noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { | |||
176 | adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); | |||
177 | } | |||
178 | ||||
179 | // mapped_iterator - This is a simple iterator adapter that causes a function to | |||
180 | // be applied whenever operator* is invoked on the iterator. | |||
181 | ||||
182 | template <typename ItTy, typename FuncTy, | |||
183 | typename FuncReturnTy = | |||
184 | decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> | |||
185 | class mapped_iterator | |||
186 | : public iterator_adaptor_base< | |||
187 | mapped_iterator<ItTy, FuncTy>, ItTy, | |||
188 | typename std::iterator_traits<ItTy>::iterator_category, | |||
189 | typename std::remove_reference<FuncReturnTy>::type> { | |||
190 | public: | |||
191 | mapped_iterator(ItTy U, FuncTy F) | |||
192 | : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} | |||
193 | ||||
194 | ItTy getCurrent() { return this->I; } | |||
195 | ||||
196 | FuncReturnTy operator*() { return F(*this->I); } | |||
197 | ||||
198 | private: | |||
199 | FuncTy F; | |||
200 | }; | |||
201 | ||||
202 | // map_iterator - Provide a convenient way to create mapped_iterators, just like | |||
203 | // make_pair is useful for creating pairs... | |||
204 | template <class ItTy, class FuncTy> | |||
205 | inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { | |||
206 | return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); | |||
207 | } | |||
208 | ||||
209 | /// Helper to determine if type T has a member called rbegin(). | |||
210 | template <typename Ty> class has_rbegin_impl { | |||
211 | using yes = char[1]; | |||
212 | using no = char[2]; | |||
213 | ||||
214 | template <typename Inner> | |||
215 | static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); | |||
216 | ||||
217 | template <typename> | |||
218 | static no& test(...); | |||
219 | ||||
220 | public: | |||
221 | static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); | |||
222 | }; | |||
223 | ||||
224 | /// Metafunction to determine if T& or T has a member called rbegin(). | |||
225 | template <typename Ty> | |||
226 | struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { | |||
227 | }; | |||
228 | ||||
229 | // Returns an iterator_range over the given container which iterates in reverse. | |||
230 | // Note that the container must have rbegin()/rend() methods for this to work. | |||
231 | template <typename ContainerTy> | |||
232 | auto reverse(ContainerTy &&C, | |||
233 | typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = | |||
234 | nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { | |||
235 | return make_range(C.rbegin(), C.rend()); | |||
236 | } | |||
237 | ||||
238 | // Returns a std::reverse_iterator wrapped around the given iterator. | |||
239 | template <typename IteratorTy> | |||
240 | std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { | |||
241 | return std::reverse_iterator<IteratorTy>(It); | |||
242 | } | |||
243 | ||||
244 | // Returns an iterator_range over the given container which iterates in reverse. | |||
245 | // Note that the container must have begin()/end() methods which return | |||
246 | // bidirectional iterators for this to work. | |||
247 | template <typename ContainerTy> | |||
248 | auto reverse( | |||
249 | ContainerTy &&C, | |||
250 | typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) | |||
251 | -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), | |||
252 | llvm::make_reverse_iterator(std::begin(C)))) { | |||
253 | return make_range(llvm::make_reverse_iterator(std::end(C)), | |||
254 | llvm::make_reverse_iterator(std::begin(C))); | |||
255 | } | |||
256 | ||||
257 | /// An iterator adaptor that filters the elements of given inner iterators. | |||
258 | /// | |||
259 | /// The predicate parameter should be a callable object that accepts the wrapped | |||
260 | /// iterator's reference type and returns a bool. When incrementing or | |||
261 | /// decrementing the iterator, it will call the predicate on each element and | |||
262 | /// skip any where it returns false. | |||
263 | /// | |||
264 | /// \code | |||
265 | /// int A[] = { 1, 2, 3, 4 }; | |||
266 | /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); | |||
267 | /// // R contains { 1, 3 }. | |||
268 | /// \endcode | |||
269 | template <typename WrappedIteratorT, typename PredicateT> | |||
270 | class filter_iterator | |||
271 | : public iterator_adaptor_base< | |||
272 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, | |||
273 | typename std::common_type< | |||
274 | std::forward_iterator_tag, | |||
275 | typename std::iterator_traits< | |||
276 | WrappedIteratorT>::iterator_category>::type> { | |||
277 | using BaseT = iterator_adaptor_base< | |||
278 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, | |||
279 | typename std::common_type< | |||
280 | std::forward_iterator_tag, | |||
281 | typename std::iterator_traits<WrappedIteratorT>::iterator_category>:: | |||
282 | type>; | |||
283 | ||||
284 | struct PayloadType { | |||
285 | WrappedIteratorT End; | |||
286 | PredicateT Pred; | |||
287 | }; | |||
288 | ||||
289 | Optional<PayloadType> Payload; | |||
290 | ||||
291 | void findNextValid() { | |||
292 | assert(Payload && "Payload should be engaged when findNextValid is called")(static_cast <bool> (Payload && "Payload should be engaged when findNextValid is called" ) ? void (0) : __assert_fail ("Payload && \"Payload should be engaged when findNextValid is called\"" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 292, __extension__ __PRETTY_FUNCTION__)); | |||
293 | while (this->I != Payload->End && !Payload->Pred(*this->I)) | |||
294 | BaseT::operator++(); | |||
295 | } | |||
296 | ||||
297 | // Construct the begin iterator. The begin iterator requires to know where end | |||
298 | // is, so that it can properly stop when it hits end. | |||
299 | filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred) | |||
300 | : BaseT(std::move(Begin)), | |||
301 | Payload(PayloadType{std::move(End), std::move(Pred)}) { | |||
302 | findNextValid(); | |||
303 | } | |||
304 | ||||
305 | // Construct the end iterator. It's not incrementable, so Payload doesn't | |||
306 | // have to be engaged. | |||
307 | filter_iterator(WrappedIteratorT End) : BaseT(End) {} | |||
308 | ||||
309 | public: | |||
310 | using BaseT::operator++; | |||
311 | ||||
312 | filter_iterator &operator++() { | |||
313 | BaseT::operator++(); | |||
314 | findNextValid(); | |||
315 | return *this; | |||
316 | } | |||
317 | ||||
318 | template <typename RT, typename PT> | |||
319 | friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>> | |||
320 | make_filter_range(RT &&, PT); | |||
321 | }; | |||
322 | ||||
323 | /// Convenience function that takes a range of elements and a predicate, | |||
324 | /// and return a new filter_iterator range. | |||
325 | /// | |||
326 | /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the | |||
327 | /// lifetime of that temporary is not kept by the returned range object, and the | |||
328 | /// temporary is going to be dropped on the floor after the make_iterator_range | |||
329 | /// full expression that contains this function call. | |||
330 | template <typename RangeT, typename PredicateT> | |||
331 | iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> | |||
332 | make_filter_range(RangeT &&Range, PredicateT Pred) { | |||
333 | using FilterIteratorT = | |||
334 | filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; | |||
335 | return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)), | |||
336 | std::end(std::forward<RangeT>(Range)), | |||
337 | std::move(Pred)), | |||
338 | FilterIteratorT(std::end(std::forward<RangeT>(Range)))); | |||
339 | } | |||
340 | ||||
341 | // forward declarations required by zip_shortest/zip_first | |||
342 | template <typename R, typename UnaryPredicate> | |||
343 | bool all_of(R &&range, UnaryPredicate P); | |||
344 | ||||
345 | template <size_t... I> struct index_sequence; | |||
346 | ||||
347 | template <class... Ts> struct index_sequence_for; | |||
348 | ||||
349 | namespace detail { | |||
350 | ||||
351 | using std::declval; | |||
352 | ||||
353 | // We have to alias this since inlining the actual type at the usage site | |||
354 | // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. | |||
355 | template<typename... Iters> struct ZipTupleType { | |||
356 | using type = std::tuple<decltype(*declval<Iters>())...>; | |||
357 | }; | |||
358 | ||||
359 | template <typename ZipType, typename... Iters> | |||
360 | using zip_traits = iterator_facade_base< | |||
361 | ZipType, typename std::common_type<std::bidirectional_iterator_tag, | |||
362 | typename std::iterator_traits< | |||
363 | Iters>::iterator_category...>::type, | |||
364 | // ^ TODO: Implement random access methods. | |||
365 | typename ZipTupleType<Iters...>::type, | |||
366 | typename std::iterator_traits<typename std::tuple_element< | |||
367 | 0, std::tuple<Iters...>>::type>::difference_type, | |||
368 | // ^ FIXME: This follows boost::make_zip_iterator's assumption that all | |||
369 | // inner iterators have the same difference_type. It would fail if, for | |||
370 | // instance, the second field's difference_type were non-numeric while the | |||
371 | // first is. | |||
372 | typename ZipTupleType<Iters...>::type *, | |||
373 | typename ZipTupleType<Iters...>::type>; | |||
374 | ||||
375 | template <typename ZipType, typename... Iters> | |||
376 | struct zip_common : public zip_traits<ZipType, Iters...> { | |||
377 | using Base = zip_traits<ZipType, Iters...>; | |||
378 | using value_type = typename Base::value_type; | |||
379 | ||||
380 | std::tuple<Iters...> iterators; | |||
381 | ||||
382 | protected: | |||
383 | template <size_t... Ns> value_type deref(index_sequence<Ns...>) const { | |||
384 | return value_type(*std::get<Ns>(iterators)...); | |||
385 | } | |||
386 | ||||
387 | template <size_t... Ns> | |||
388 | decltype(iterators) tup_inc(index_sequence<Ns...>) const { | |||
389 | return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); | |||
390 | } | |||
391 | ||||
392 | template <size_t... Ns> | |||
393 | decltype(iterators) tup_dec(index_sequence<Ns...>) const { | |||
394 | return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); | |||
395 | } | |||
396 | ||||
397 | public: | |||
398 | zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} | |||
399 | ||||
400 | value_type operator*() { return deref(index_sequence_for<Iters...>{}); } | |||
401 | ||||
402 | const value_type operator*() const { | |||
403 | return deref(index_sequence_for<Iters...>{}); | |||
404 | } | |||
405 | ||||
406 | ZipType &operator++() { | |||
407 | iterators = tup_inc(index_sequence_for<Iters...>{}); | |||
408 | return *reinterpret_cast<ZipType *>(this); | |||
409 | } | |||
410 | ||||
411 | ZipType &operator--() { | |||
412 | static_assert(Base::IsBidirectional, | |||
413 | "All inner iterators must be at least bidirectional."); | |||
414 | iterators = tup_dec(index_sequence_for<Iters...>{}); | |||
415 | return *reinterpret_cast<ZipType *>(this); | |||
416 | } | |||
417 | }; | |||
418 | ||||
419 | template <typename... Iters> | |||
420 | struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { | |||
421 | using Base = zip_common<zip_first<Iters...>, Iters...>; | |||
422 | ||||
423 | bool operator==(const zip_first<Iters...> &other) const { | |||
424 | return std::get<0>(this->iterators) == std::get<0>(other.iterators); | |||
425 | } | |||
426 | ||||
427 | zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} | |||
428 | }; | |||
429 | ||||
430 | template <typename... Iters> | |||
431 | class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { | |||
432 | template <size_t... Ns> | |||
433 | bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const { | |||
434 | return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != | |||
435 | std::get<Ns>(other.iterators)...}, | |||
436 | identity<bool>{}); | |||
437 | } | |||
438 | ||||
439 | public: | |||
440 | using Base = zip_common<zip_shortest<Iters...>, Iters...>; | |||
441 | ||||
442 | zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} | |||
443 | ||||
444 | bool operator==(const zip_shortest<Iters...> &other) const { | |||
445 | return !test(other, index_sequence_for<Iters...>{}); | |||
446 | } | |||
447 | }; | |||
448 | ||||
449 | template <template <typename...> class ItType, typename... Args> class zippy { | |||
450 | public: | |||
451 | using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; | |||
452 | using iterator_category = typename iterator::iterator_category; | |||
453 | using value_type = typename iterator::value_type; | |||
454 | using difference_type = typename iterator::difference_type; | |||
455 | using pointer = typename iterator::pointer; | |||
456 | using reference = typename iterator::reference; | |||
457 | ||||
458 | private: | |||
459 | std::tuple<Args...> ts; | |||
460 | ||||
461 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const { | |||
462 | return iterator(std::begin(std::get<Ns>(ts))...); | |||
463 | } | |||
464 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const { | |||
465 | return iterator(std::end(std::get<Ns>(ts))...); | |||
466 | } | |||
467 | ||||
468 | public: | |||
469 | zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} | |||
470 | ||||
471 | iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); } | |||
472 | iterator end() const { return end_impl(index_sequence_for<Args...>{}); } | |||
473 | }; | |||
474 | ||||
475 | } // end namespace detail | |||
476 | ||||
477 | /// zip iterator for two or more iteratable types. | |||
478 | template <typename T, typename U, typename... Args> | |||
479 | detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, | |||
480 | Args &&... args) { | |||
481 | return detail::zippy<detail::zip_shortest, T, U, Args...>( | |||
482 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); | |||
483 | } | |||
484 | ||||
485 | /// zip iterator that, for the sake of efficiency, assumes the first iteratee to | |||
486 | /// be the shortest. | |||
487 | template <typename T, typename U, typename... Args> | |||
488 | detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, | |||
489 | Args &&... args) { | |||
490 | return detail::zippy<detail::zip_first, T, U, Args...>( | |||
491 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); | |||
492 | } | |||
493 | ||||
494 | /// Iterator wrapper that concatenates sequences together. | |||
495 | /// | |||
496 | /// This can concatenate different iterators, even with different types, into | |||
497 | /// a single iterator provided the value types of all the concatenated | |||
498 | /// iterators expose `reference` and `pointer` types that can be converted to | |||
499 | /// `ValueT &` and `ValueT *` respectively. It doesn't support more | |||
500 | /// interesting/customized pointer or reference types. | |||
501 | /// | |||
502 | /// Currently this only supports forward or higher iterator categories as | |||
503 | /// inputs and always exposes a forward iterator interface. | |||
504 | template <typename ValueT, typename... IterTs> | |||
505 | class concat_iterator | |||
506 | : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, | |||
507 | std::forward_iterator_tag, ValueT> { | |||
508 | using BaseT = typename concat_iterator::iterator_facade_base; | |||
509 | ||||
510 | /// We store both the current and end iterators for each concatenated | |||
511 | /// sequence in a tuple of pairs. | |||
512 | /// | |||
513 | /// Note that something like iterator_range seems nice at first here, but the | |||
514 | /// range properties are of little benefit and end up getting in the way | |||
515 | /// because we need to do mutation on the current iterators. | |||
516 | std::tuple<std::pair<IterTs, IterTs>...> IterPairs; | |||
517 | ||||
518 | /// Attempts to increment a specific iterator. | |||
519 | /// | |||
520 | /// Returns true if it was able to increment the iterator. Returns false if | |||
521 | /// the iterator is already at the end iterator. | |||
522 | template <size_t Index> bool incrementHelper() { | |||
523 | auto &IterPair = std::get<Index>(IterPairs); | |||
524 | if (IterPair.first == IterPair.second) | |||
525 | return false; | |||
526 | ||||
527 | ++IterPair.first; | |||
528 | return true; | |||
529 | } | |||
530 | ||||
531 | /// Increments the first non-end iterator. | |||
532 | /// | |||
533 | /// It is an error to call this with all iterators at the end. | |||
534 | template <size_t... Ns> void increment(index_sequence<Ns...>) { | |||
535 | // Build a sequence of functions to increment each iterator if possible. | |||
536 | bool (concat_iterator::*IncrementHelperFns[])() = { | |||
537 | &concat_iterator::incrementHelper<Ns>...}; | |||
538 | ||||
539 | // Loop over them, and stop as soon as we succeed at incrementing one. | |||
540 | for (auto &IncrementHelperFn : IncrementHelperFns) | |||
541 | if ((this->*IncrementHelperFn)()) | |||
542 | return; | |||
543 | ||||
544 | llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 544); | |||
545 | } | |||
546 | ||||
547 | /// Returns null if the specified iterator is at the end. Otherwise, | |||
548 | /// dereferences the iterator and returns the address of the resulting | |||
549 | /// reference. | |||
550 | template <size_t Index> ValueT *getHelper() const { | |||
551 | auto &IterPair = std::get<Index>(IterPairs); | |||
552 | if (IterPair.first == IterPair.second) | |||
553 | return nullptr; | |||
554 | ||||
555 | return &*IterPair.first; | |||
556 | } | |||
557 | ||||
558 | /// Finds the first non-end iterator, dereferences, and returns the resulting | |||
559 | /// reference. | |||
560 | /// | |||
561 | /// It is an error to call this with all iterators at the end. | |||
562 | template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const { | |||
563 | // Build a sequence of functions to get from iterator if possible. | |||
564 | ValueT *(concat_iterator::*GetHelperFns[])() const = { | |||
565 | &concat_iterator::getHelper<Ns>...}; | |||
566 | ||||
567 | // Loop over them, and return the first result we find. | |||
568 | for (auto &GetHelperFn : GetHelperFns) | |||
569 | if (ValueT *P = (this->*GetHelperFn)()) | |||
570 | return *P; | |||
571 | ||||
572 | llvm_unreachable("Attempted to get a pointer from an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to get a pointer from an end concat iterator!" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 572); | |||
573 | } | |||
574 | ||||
575 | public: | |||
576 | /// Constructs an iterator from a squence of ranges. | |||
577 | /// | |||
578 | /// We need the full range to know how to switch between each of the | |||
579 | /// iterators. | |||
580 | template <typename... RangeTs> | |||
581 | explicit concat_iterator(RangeTs &&... Ranges) | |||
582 | : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {} | |||
583 | ||||
584 | using BaseT::operator++; | |||
585 | ||||
586 | concat_iterator &operator++() { | |||
587 | increment(index_sequence_for<IterTs...>()); | |||
588 | return *this; | |||
589 | } | |||
590 | ||||
591 | ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); } | |||
592 | ||||
593 | bool operator==(const concat_iterator &RHS) const { | |||
594 | return IterPairs == RHS.IterPairs; | |||
595 | } | |||
596 | }; | |||
597 | ||||
598 | namespace detail { | |||
599 | ||||
600 | /// Helper to store a sequence of ranges being concatenated and access them. | |||
601 | /// | |||
602 | /// This is designed to facilitate providing actual storage when temporaries | |||
603 | /// are passed into the constructor such that we can use it as part of range | |||
604 | /// based for loops. | |||
605 | template <typename ValueT, typename... RangeTs> class concat_range { | |||
606 | public: | |||
607 | using iterator = | |||
608 | concat_iterator<ValueT, | |||
609 | decltype(std::begin(std::declval<RangeTs &>()))...>; | |||
610 | ||||
611 | private: | |||
612 | std::tuple<RangeTs...> Ranges; | |||
613 | ||||
614 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) { | |||
615 | return iterator(std::get<Ns>(Ranges)...); | |||
616 | } | |||
617 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) { | |||
618 | return iterator(make_range(std::end(std::get<Ns>(Ranges)), | |||
619 | std::end(std::get<Ns>(Ranges)))...); | |||
620 | } | |||
621 | ||||
622 | public: | |||
623 | concat_range(RangeTs &&... Ranges) | |||
624 | : Ranges(std::forward<RangeTs>(Ranges)...) {} | |||
625 | ||||
626 | iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); } | |||
627 | iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); } | |||
628 | }; | |||
629 | ||||
630 | } // end namespace detail | |||
631 | ||||
632 | /// Concatenated range across two or more ranges. | |||
633 | /// | |||
634 | /// The desired value type must be explicitly specified. | |||
635 | template <typename ValueT, typename... RangeTs> | |||
636 | detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { | |||
637 | static_assert(sizeof...(RangeTs) > 1, | |||
638 | "Need more than one range to concatenate!"); | |||
639 | return detail::concat_range<ValueT, RangeTs...>( | |||
640 | std::forward<RangeTs>(Ranges)...); | |||
641 | } | |||
642 | ||||
643 | //===----------------------------------------------------------------------===// | |||
644 | // Extra additions to <utility> | |||
645 | //===----------------------------------------------------------------------===// | |||
646 | ||||
647 | /// \brief Function object to check whether the first component of a std::pair | |||
648 | /// compares less than the first component of another std::pair. | |||
649 | struct less_first { | |||
650 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { | |||
651 | return lhs.first < rhs.first; | |||
652 | } | |||
653 | }; | |||
654 | ||||
655 | /// \brief Function object to check whether the second component of a std::pair | |||
656 | /// compares less than the second component of another std::pair. | |||
657 | struct less_second { | |||
658 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { | |||
659 | return lhs.second < rhs.second; | |||
660 | } | |||
661 | }; | |||
662 | ||||
663 | // A subset of N3658. More stuff can be added as-needed. | |||
664 | ||||
665 | /// \brief Represents a compile-time sequence of integers. | |||
666 | template <class T, T... I> struct integer_sequence { | |||
667 | using value_type = T; | |||
668 | ||||
669 | static constexpr size_t size() { return sizeof...(I); } | |||
670 | }; | |||
671 | ||||
672 | /// \brief Alias for the common case of a sequence of size_ts. | |||
673 | template <size_t... I> | |||
674 | struct index_sequence : integer_sequence<std::size_t, I...> {}; | |||
675 | ||||
676 | template <std::size_t N, std::size_t... I> | |||
677 | struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; | |||
678 | template <std::size_t... I> | |||
679 | struct build_index_impl<0, I...> : index_sequence<I...> {}; | |||
680 | ||||
681 | /// \brief Creates a compile-time integer sequence for a parameter pack. | |||
682 | template <class... Ts> | |||
683 | struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; | |||
684 | ||||
685 | /// Utility type to build an inheritance chain that makes it easy to rank | |||
686 | /// overload candidates. | |||
687 | template <int N> struct rank : rank<N - 1> {}; | |||
688 | template <> struct rank<0> {}; | |||
689 | ||||
690 | /// \brief traits class for checking whether type T is one of any of the given | |||
691 | /// types in the variadic list. | |||
692 | template <typename T, typename... Ts> struct is_one_of { | |||
693 | static const bool value = false; | |||
694 | }; | |||
695 | ||||
696 | template <typename T, typename U, typename... Ts> | |||
697 | struct is_one_of<T, U, Ts...> { | |||
698 | static const bool value = | |||
699 | std::is_same<T, U>::value || is_one_of<T, Ts...>::value; | |||
700 | }; | |||
701 | ||||
702 | /// \brief traits class for checking whether type T is a base class for all | |||
703 | /// the given types in the variadic list. | |||
704 | template <typename T, typename... Ts> struct are_base_of { | |||
705 | static const bool value = true; | |||
706 | }; | |||
707 | ||||
708 | template <typename T, typename U, typename... Ts> | |||
709 | struct are_base_of<T, U, Ts...> { | |||
710 | static const bool value = | |||
711 | std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; | |||
712 | }; | |||
713 | ||||
714 | //===----------------------------------------------------------------------===// | |||
715 | // Extra additions for arrays | |||
716 | //===----------------------------------------------------------------------===// | |||
717 | ||||
718 | /// Find the length of an array. | |||
719 | template <class T, std::size_t N> | |||
720 | constexpr inline size_t array_lengthof(T (&)[N]) { | |||
721 | return N; | |||
722 | } | |||
723 | ||||
724 | /// Adapt std::less<T> for array_pod_sort. | |||
725 | template<typename T> | |||
726 | inline int array_pod_sort_comparator(const void *P1, const void *P2) { | |||
727 | if (std::less<T>()(*reinterpret_cast<const T*>(P1), | |||
728 | *reinterpret_cast<const T*>(P2))) | |||
729 | return -1; | |||
730 | if (std::less<T>()(*reinterpret_cast<const T*>(P2), | |||
731 | *reinterpret_cast<const T*>(P1))) | |||
732 | return 1; | |||
733 | return 0; | |||
734 | } | |||
735 | ||||
736 | /// get_array_pod_sort_comparator - This is an internal helper function used to | |||
737 | /// get type deduction of T right. | |||
738 | template<typename T> | |||
739 | inline int (*get_array_pod_sort_comparator(const T &)) | |||
740 | (const void*, const void*) { | |||
741 | return array_pod_sort_comparator<T>; | |||
742 | } | |||
743 | ||||
744 | /// array_pod_sort - This sorts an array with the specified start and end | |||
745 | /// extent. This is just like std::sort, except that it calls qsort instead of | |||
746 | /// using an inlined template. qsort is slightly slower than std::sort, but | |||
747 | /// most sorts are not performance critical in LLVM and std::sort has to be | |||
748 | /// template instantiated for each type, leading to significant measured code | |||
749 | /// bloat. This function should generally be used instead of std::sort where | |||
750 | /// possible. | |||
751 | /// | |||
752 | /// This function assumes that you have simple POD-like types that can be | |||
753 | /// compared with std::less and can be moved with memcpy. If this isn't true, | |||
754 | /// you should use std::sort. | |||
755 | /// | |||
756 | /// NOTE: If qsort_r were portable, we could allow a custom comparator and | |||
757 | /// default to std::less. | |||
758 | template<class IteratorTy> | |||
759 | inline void array_pod_sort(IteratorTy Start, IteratorTy End) { | |||
760 | // Don't inefficiently call qsort with one element or trigger undefined | |||
761 | // behavior with an empty sequence. | |||
762 | auto NElts = End - Start; | |||
763 | if (NElts <= 1) return; | |||
764 | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); | |||
765 | } | |||
766 | ||||
767 | template <class IteratorTy> | |||
768 | inline void array_pod_sort( | |||
769 | IteratorTy Start, IteratorTy End, | |||
770 | int (*Compare)( | |||
771 | const typename std::iterator_traits<IteratorTy>::value_type *, | |||
772 | const typename std::iterator_traits<IteratorTy>::value_type *)) { | |||
773 | // Don't inefficiently call qsort with one element or trigger undefined | |||
774 | // behavior with an empty sequence. | |||
775 | auto NElts = End - Start; | |||
776 | if (NElts <= 1) return; | |||
777 | qsort(&*Start, NElts, sizeof(*Start), | |||
778 | reinterpret_cast<int (*)(const void *, const void *)>(Compare)); | |||
779 | } | |||
780 | ||||
781 | //===----------------------------------------------------------------------===// | |||
782 | // Extra additions to <algorithm> | |||
783 | //===----------------------------------------------------------------------===// | |||
784 | ||||
785 | /// For a container of pointers, deletes the pointers and then clears the | |||
786 | /// container. | |||
787 | template<typename Container> | |||
788 | void DeleteContainerPointers(Container &C) { | |||
789 | for (auto V : C) | |||
790 | delete V; | |||
791 | C.clear(); | |||
792 | } | |||
793 | ||||
794 | /// In a container of pairs (usually a map) whose second element is a pointer, | |||
795 | /// deletes the second elements and then clears the container. | |||
796 | template<typename Container> | |||
797 | void DeleteContainerSeconds(Container &C) { | |||
798 | for (auto &V : C) | |||
799 | delete V.second; | |||
800 | C.clear(); | |||
801 | } | |||
802 | ||||
803 | /// Provide wrappers to std::for_each which take ranges instead of having to | |||
804 | /// pass begin/end explicitly. | |||
805 | template <typename R, typename UnaryPredicate> | |||
806 | UnaryPredicate for_each(R &&Range, UnaryPredicate P) { | |||
807 | return std::for_each(adl_begin(Range), adl_end(Range), P); | |||
808 | } | |||
809 | ||||
810 | /// Provide wrappers to std::all_of which take ranges instead of having to pass | |||
811 | /// begin/end explicitly. | |||
812 | template <typename R, typename UnaryPredicate> | |||
813 | bool all_of(R &&Range, UnaryPredicate P) { | |||
814 | return std::all_of(adl_begin(Range), adl_end(Range), P); | |||
815 | } | |||
816 | ||||
817 | /// Provide wrappers to std::any_of which take ranges instead of having to pass | |||
818 | /// begin/end explicitly. | |||
819 | template <typename R, typename UnaryPredicate> | |||
820 | bool any_of(R &&Range, UnaryPredicate P) { | |||
821 | return std::any_of(adl_begin(Range), adl_end(Range), P); | |||
822 | } | |||
823 | ||||
824 | /// Provide wrappers to std::none_of which take ranges instead of having to pass | |||
825 | /// begin/end explicitly. | |||
826 | template <typename R, typename UnaryPredicate> | |||
827 | bool none_of(R &&Range, UnaryPredicate P) { | |||
828 | return std::none_of(adl_begin(Range), adl_end(Range), P); | |||
829 | } | |||
830 | ||||
831 | /// Provide wrappers to std::find which take ranges instead of having to pass | |||
832 | /// begin/end explicitly. | |||
833 | template <typename R, typename T> | |||
834 | auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { | |||
835 | return std::find(adl_begin(Range), adl_end(Range), Val); | |||
836 | } | |||
837 | ||||
838 | /// Provide wrappers to std::find_if which take ranges instead of having to pass | |||
839 | /// begin/end explicitly. | |||
840 | template <typename R, typename UnaryPredicate> | |||
841 | auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { | |||
842 | return std::find_if(adl_begin(Range), adl_end(Range), P); | |||
843 | } | |||
844 | ||||
845 | template <typename R, typename UnaryPredicate> | |||
846 | auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { | |||
847 | return std::find_if_not(adl_begin(Range), adl_end(Range), P); | |||
848 | } | |||
849 | ||||
850 | /// Provide wrappers to std::remove_if which take ranges instead of having to | |||
851 | /// pass begin/end explicitly. | |||
852 | template <typename R, typename UnaryPredicate> | |||
853 | auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { | |||
854 | return std::remove_if(adl_begin(Range), adl_end(Range), P); | |||
855 | } | |||
856 | ||||
857 | /// Provide wrappers to std::copy_if which take ranges instead of having to | |||
858 | /// pass begin/end explicitly. | |||
859 | template <typename R, typename OutputIt, typename UnaryPredicate> | |||
860 | OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { | |||
861 | return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); | |||
862 | } | |||
863 | ||||
864 | /// Wrapper function around std::find to detect if an element exists | |||
865 | /// in a container. | |||
866 | template <typename R, typename E> | |||
867 | bool is_contained(R &&Range, const E &Element) { | |||
868 | return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); | |||
869 | } | |||
870 | ||||
871 | /// Wrapper function around std::count to count the number of times an element | |||
872 | /// \p Element occurs in the given range \p Range. | |||
873 | template <typename R, typename E> | |||
874 | auto count(R &&Range, const E &Element) -> | |||
875 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { | |||
876 | return std::count(adl_begin(Range), adl_end(Range), Element); | |||
877 | } | |||
878 | ||||
879 | /// Wrapper function around std::count_if to count the number of times an | |||
880 | /// element satisfying a given predicate occurs in a range. | |||
881 | template <typename R, typename UnaryPredicate> | |||
882 | auto count_if(R &&Range, UnaryPredicate P) -> | |||
883 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { | |||
884 | return std::count_if(adl_begin(Range), adl_end(Range), P); | |||
885 | } | |||
886 | ||||
887 | /// Wrapper function around std::transform to apply a function to a range and | |||
888 | /// store the result elsewhere. | |||
889 | template <typename R, typename OutputIt, typename UnaryPredicate> | |||
890 | OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { | |||
891 | return std::transform(adl_begin(Range), adl_end(Range), d_first, P); | |||
892 | } | |||
893 | ||||
894 | /// Provide wrappers to std::partition which take ranges instead of having to | |||
895 | /// pass begin/end explicitly. | |||
896 | template <typename R, typename UnaryPredicate> | |||
897 | auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { | |||
898 | return std::partition(adl_begin(Range), adl_end(Range), P); | |||
899 | } | |||
900 | ||||
901 | /// Provide wrappers to std::lower_bound which take ranges instead of having to | |||
902 | /// pass begin/end explicitly. | |||
903 | template <typename R, typename ForwardIt> | |||
904 | auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { | |||
905 | return std::lower_bound(adl_begin(Range), adl_end(Range), I); | |||
906 | } | |||
907 | ||||
908 | /// \brief Given a range of type R, iterate the entire range and return a | |||
909 | /// SmallVector with elements of the vector. This is useful, for example, | |||
910 | /// when you want to iterate a range and then sort the results. | |||
911 | template <unsigned Size, typename R> | |||
912 | SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size> | |||
913 | to_vector(R &&Range) { | |||
914 | return {adl_begin(Range), adl_end(Range)}; | |||
915 | } | |||
916 | ||||
917 | /// Provide a container algorithm similar to C++ Library Fundamentals v2's | |||
918 | /// `erase_if` which is equivalent to: | |||
919 | /// | |||
920 | /// C.erase(remove_if(C, pred), C.end()); | |||
921 | /// | |||
922 | /// This version works for any container with an erase method call accepting | |||
923 | /// two iterators. | |||
924 | template <typename Container, typename UnaryPredicate> | |||
925 | void erase_if(Container &C, UnaryPredicate P) { | |||
926 | C.erase(remove_if(C, P), C.end()); | |||
927 | } | |||
928 | ||||
929 | //===----------------------------------------------------------------------===// | |||
930 | // Extra additions to <memory> | |||
931 | //===----------------------------------------------------------------------===// | |||
932 | ||||
933 | // Implement make_unique according to N3656. | |||
934 | ||||
935 | /// \brief Constructs a `new T()` with the given args and returns a | |||
936 | /// `unique_ptr<T>` which owns the object. | |||
937 | /// | |||
938 | /// Example: | |||
939 | /// | |||
940 | /// auto p = make_unique<int>(); | |||
941 | /// auto p = make_unique<std::tuple<int, int>>(0, 1); | |||
942 | template <class T, class... Args> | |||
943 | typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type | |||
944 | make_unique(Args &&... args) { | |||
945 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); | |||
| ||||
946 | } | |||
947 | ||||
948 | /// \brief Constructs a `new T[n]` with the given args and returns a | |||
949 | /// `unique_ptr<T[]>` which owns the object. | |||
950 | /// | |||
951 | /// \param n size of the new array. | |||
952 | /// | |||
953 | /// Example: | |||
954 | /// | |||
955 | /// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. | |||
956 | template <class T> | |||
957 | typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, | |||
958 | std::unique_ptr<T>>::type | |||
959 | make_unique(size_t n) { | |||
960 | return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); | |||
961 | } | |||
962 | ||||
963 | /// This function isn't used and is only here to provide better compile errors. | |||
964 | template <class T, class... Args> | |||
965 | typename std::enable_if<std::extent<T>::value != 0>::type | |||
966 | make_unique(Args &&...) = delete; | |||
967 | ||||
968 | struct FreeDeleter { | |||
969 | void operator()(void* v) { | |||
970 | ::free(v); | |||
971 | } | |||
972 | }; | |||
973 | ||||
974 | template<typename First, typename Second> | |||
975 | struct pair_hash { | |||
976 | size_t operator()(const std::pair<First, Second> &P) const { | |||
977 | return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); | |||
978 | } | |||
979 | }; | |||
980 | ||||
981 | /// A functor like C++14's std::less<void> in its absence. | |||
982 | struct less { | |||
983 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { | |||
984 | return std::forward<A>(a) < std::forward<B>(b); | |||
985 | } | |||
986 | }; | |||
987 | ||||
988 | /// A functor like C++14's std::equal<void> in its absence. | |||
989 | struct equal { | |||
990 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { | |||
991 | return std::forward<A>(a) == std::forward<B>(b); | |||
992 | } | |||
993 | }; | |||
994 | ||||
995 | /// Binary functor that adapts to any other binary functor after dereferencing | |||
996 | /// operands. | |||
997 | template <typename T> struct deref { | |||
998 | T func; | |||
999 | ||||
1000 | // Could be further improved to cope with non-derivable functors and | |||
1001 | // non-binary functors (should be a variadic template member function | |||
1002 | // operator()). | |||
1003 | template <typename A, typename B> | |||
1004 | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { | |||
1005 | assert(lhs)(static_cast <bool> (lhs) ? void (0) : __assert_fail ("lhs" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 1005, __extension__ __PRETTY_FUNCTION__)); | |||
1006 | assert(rhs)(static_cast <bool> (rhs) ? void (0) : __assert_fail ("rhs" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 1006, __extension__ __PRETTY_FUNCTION__)); | |||
1007 | return func(*lhs, *rhs); | |||
1008 | } | |||
1009 | }; | |||
1010 | ||||
1011 | namespace detail { | |||
1012 | ||||
1013 | template <typename R> class enumerator_iter; | |||
1014 | ||||
1015 | template <typename R> struct result_pair { | |||
1016 | friend class enumerator_iter<R>; | |||
1017 | ||||
1018 | result_pair() = default; | |||
1019 | result_pair(std::size_t Index, IterOfRange<R> Iter) | |||
1020 | : Index(Index), Iter(Iter) {} | |||
1021 | ||||
1022 | result_pair<R> &operator=(const result_pair<R> &Other) { | |||
1023 | Index = Other.Index; | |||
1024 | Iter = Other.Iter; | |||
1025 | return *this; | |||
1026 | } | |||
1027 | ||||
1028 | std::size_t index() const { return Index; } | |||
1029 | const ValueOfRange<R> &value() const { return *Iter; } | |||
1030 | ValueOfRange<R> &value() { return *Iter; } | |||
1031 | ||||
1032 | private: | |||
1033 | std::size_t Index = std::numeric_limits<std::size_t>::max(); | |||
1034 | IterOfRange<R> Iter; | |||
1035 | }; | |||
1036 | ||||
1037 | template <typename R> | |||
1038 | class enumerator_iter | |||
1039 | : public iterator_facade_base< | |||
1040 | enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, | |||
1041 | typename std::iterator_traits<IterOfRange<R>>::difference_type, | |||
1042 | typename std::iterator_traits<IterOfRange<R>>::pointer, | |||
1043 | typename std::iterator_traits<IterOfRange<R>>::reference> { | |||
1044 | using result_type = result_pair<R>; | |||
1045 | ||||
1046 | public: | |||
1047 | explicit enumerator_iter(IterOfRange<R> EndIter) | |||
1048 | : Result(std::numeric_limits<size_t>::max(), EndIter) {} | |||
1049 | ||||
1050 | enumerator_iter(std::size_t Index, IterOfRange<R> Iter) | |||
1051 | : Result(Index, Iter) {} | |||
1052 | ||||
1053 | result_type &operator*() { return Result; } | |||
1054 | const result_type &operator*() const { return Result; } | |||
1055 | ||||
1056 | enumerator_iter<R> &operator++() { | |||
1057 | assert(Result.Index != std::numeric_limits<size_t>::max())(static_cast <bool> (Result.Index != std::numeric_limits <size_t>::max()) ? void (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()" , "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ADT/STLExtras.h" , 1057, __extension__ __PRETTY_FUNCTION__)); | |||
1058 | ++Result.Iter; | |||
1059 | ++Result.Index; | |||
1060 | return *this; | |||
1061 | } | |||
1062 | ||||
1063 | bool operator==(const enumerator_iter<R> &RHS) const { | |||
1064 | // Don't compare indices here, only iterators. It's possible for an end | |||
1065 | // iterator to have different indices depending on whether it was created | |||
1066 | // by calling std::end() versus incrementing a valid iterator. | |||
1067 | return Result.Iter == RHS.Result.Iter; | |||
1068 | } | |||
1069 | ||||
1070 | enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { | |||
1071 | Result = Other.Result; | |||
1072 | return *this; | |||
1073 | } | |||
1074 | ||||
1075 | private: | |||
1076 | result_type Result; | |||
1077 | }; | |||
1078 | ||||
1079 | template <typename R> class enumerator { | |||
1080 | public: | |||
1081 | explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} | |||
1082 | ||||
1083 | enumerator_iter<R> begin() { | |||
1084 | return enumerator_iter<R>(0, std::begin(TheRange)); | |||
1085 | } | |||
1086 | ||||
1087 | enumerator_iter<R> end() { | |||
1088 | return enumerator_iter<R>(std::end(TheRange)); | |||
1089 | } | |||
1090 | ||||
1091 | private: | |||
1092 | R TheRange; | |||
1093 | }; | |||
1094 | ||||
1095 | } // end namespace detail | |||
1096 | ||||
1097 | /// Given an input range, returns a new range whose values are are pair (A,B) | |||
1098 | /// such that A is the 0-based index of the item in the sequence, and B is | |||
1099 | /// the value from the original sequence. Example: | |||
1100 | /// | |||
1101 | /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; | |||
1102 | /// for (auto X : enumerate(Items)) { | |||
1103 | /// printf("Item %d - %c\n", X.index(), X.value()); | |||
1104 | /// } | |||
1105 | /// | |||
1106 | /// Output: | |||
1107 | /// Item 0 - A | |||
1108 | /// Item 1 - B | |||
1109 | /// Item 2 - C | |||
1110 | /// Item 3 - D | |||
1111 | /// | |||
1112 | template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { | |||
1113 | return detail::enumerator<R>(std::forward<R>(TheRange)); | |||
1114 | } | |||
1115 | ||||
1116 | namespace detail { | |||
1117 | ||||
1118 | template <typename F, typename Tuple, std::size_t... I> | |||
1119 | auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence<I...>) | |||
1120 | -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { | |||
1121 | return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); | |||
1122 | } | |||
1123 | ||||
1124 | } // end namespace detail | |||
1125 | ||||
1126 | /// Given an input tuple (a1, a2, ..., an), pass the arguments of the | |||
1127 | /// tuple variadically to f as if by calling f(a1, a2, ..., an) and | |||
1128 | /// return the result. | |||
1129 | template <typename F, typename Tuple> | |||
1130 | auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( | |||
1131 | std::forward<F>(f), std::forward<Tuple>(t), | |||
1132 | build_index_impl< | |||
1133 | std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { | |||
1134 | using Indices = build_index_impl< | |||
1135 | std::tuple_size<typename std::decay<Tuple>::type>::value>; | |||
1136 | ||||
1137 | return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), | |||
1138 | Indices{}); | |||
1139 | } | |||
1140 | ||||
1141 | } // end namespace llvm | |||
1142 | ||||
1143 | #endif // LLVM_ADT_STLEXTRAS_H |