Bug Summary

File:tools/lli/lli.cpp
Warning:line 1154, column 14
2nd function call argument is an uninitialized value

Annotated Source Code

/build/llvm-toolchain-snapshot-6.0~svn319013/tools/lli/lli.cpp

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
66using namespace llvm;
67
68#define DEBUG_TYPE"lli" "lli"
69
70namespace {
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//
191class LLIObjectCache : public ObjectCache {
192public:
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
234private:
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.
262static 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
295CodeGenOpt::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
309LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
310static void reportError(SMDiagnostic Err, const char *ProgName) {
311 Err.print(ProgName, errs());
312 exit(1);
313}
314
315//===----------------------------------------------------------------------===//
316// main Driver function
317//
318int 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)
1
Assuming 'argc' is <= 1
2
Taking false branch
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)
3
Assuming the condition is false
4
Taking false branch
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)
5
Assuming 'Mod' is non-null
6
Taking false branch
347 reportError(Err, argv[0]);
348
349 if (UseJITKind == JITKind::OrcLazy) {
7
Assuming the condition is false
8
Taking false branch
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) {
9
Assuming the condition is false
10
Taking false branch
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) {
11
Assuming the condition is false
12
Taking false branch
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())
13
Assuming the condition is false
14
Taking false branch
384 builder.setRelocationModel(RelocModel);
385 if (CMModel.getNumOccurrences())
15
Assuming the condition is false
16
Taking false branch
386 builder.setCodeModel(CMModel);
387 builder.setErrorStr(&ErrorMsg);
388 builder.setEngineKind(ForceInterpreter
17
Assuming the condition is false
18
'?' condition is false
389 ? EngineKind::Interpreter
390 : EngineKind::JIT);
391 builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement);
19
Assuming the condition is false
392
393 // If we are supposed to override the target triple, do so now.
394 if (!TargetTriple.empty())
20
Assuming the condition is false
21
Taking false branch
395 Mod->setTargetTriple(Triple::normalize(TargetTriple));
396
397 // Enable MCJIT if desired.
398 RTDyldMemoryManager *RTDyldMM = nullptr;
399 if (!ForceInterpreter) {
22
Taking true branch
400 if (RemoteMCJIT)
23
Assuming the condition is false
24
Taking false branch
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)
25
Assuming the condition is false
26
Taking false branch
419 Options.FloatABIType = FloatABIForCalls;
420
421 builder.setTargetOptions(Options);
422
423 std::unique_ptr<ExecutionEngine> EE(builder.create());
424 if (!EE) {
27
Taking false branch
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) {
28
Assuming the condition is false
29
Taking false branch
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) {
30
Assuming 'i' is equal to 'e'
31
Loop condition is false. Execution continues on line 451
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) {
32
Assuming 'i' is equal to 'e'
33
Loop condition is false. Execution continues on line 463
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) {
34
Assuming 'i' is equal to 'e'
35
Loop condition is false. Execution continues on line 489
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()) {
36
Assuming the condition is false
37
Taking false branch
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) {
38
Assuming the condition is false
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()) {
39
Assuming the condition is false
40
Taking false branch
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"))
41
Assuming the condition is false
42
Taking false branch
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) {
43
Assuming 'EntryFn' is non-null
44
Taking false branch
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) {
45
Assuming the condition is true
46
Taking true branch
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()) {
47
Assuming the condition is false
48
Taking false branch
545 errs() << "-remote-mcjit requires -mcjit-remote-process.\n";
546 exit(1);
547 } else if (!sys::fs::can_execute(ChildExecPath)) {
49
Assuming the condition is false
50
Taking false branch
548 errs() << "Unable to find usable child executable: '" << ChildExecPath
549 << "'\n";
550 return -1;
551 }
552#endif
553 }
554
555 if (!RemoteMCJIT) {
51
Assuming the condition is false
52
Taking false branch
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) {
53
Taking false branch
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());
54
Calling 'OrcRemoteTargetClient::terminateSession'
649 }
650
651 return Result;
652}
653
654std::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}

/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h

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
45namespace llvm {
46namespace orc {
47namespace 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.
56class OrcRemoteTargetClient
57 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
58public:
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>(); }
55
Calling 'SingleThreadedRPCEndpoint::callB'
555
556private:
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

/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCUtils.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
31namespace llvm {
32namespace orc {
33namespace rpc {
34
35/// Base class of all fatal RPC errors (those that necessarily result in the
36/// termination of the RPC session).
37class RPCFatalError : public ErrorInfo<RPCFatalError> {
38public:
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.
44class ConnectionClosed : public ErrorInfo<ConnectionClosed> {
45public:
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.
57template <typename FnIdT, typename SeqNoT>
58class BadFunctionCall
59 : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
60public:
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
75private:
76 FnIdT FnId;
77 SeqNoT SeqNo;
78};
79
80template <typename FnIdT, typename SeqNoT>
81char 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.
90template <typename SeqNoT>
91class InvalidSequenceNumberForResponse
92 : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
93public:
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 }
106private:
107 SeqNoT SeqNo;
108};
109
110template <typename SeqNoT>
111char 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.
116class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> {
117public:
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.
126class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> {
127public:
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; }
134private:
135 std::string Signature;
136};
137
138template <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.
143template <typename DerivedFunc, typename RetT, typename... ArgTs>
144class Function<DerivedFunc, RetT(ArgTs...)> {
145public:
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
162private:
163 static std::mutex NameMutex;
164 static std::string Name;
165};
166
167template <typename DerivedFunc, typename RetT, typename... ArgTs>
168std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex;
169
170template <typename DerivedFunc, typename RetT, typename... ArgTs>
171std::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.
190template <typename T, typename = void> class RPCFunctionIdAllocator;
191
192/// This specialization of RPCFunctionIdAllocator provides a default
193/// implementation for integral types.
194template <typename T>
195class RPCFunctionIdAllocator<
196 T, typename std::enable_if<std::is_integral<T>::value>::type> {
197public:
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
204private:
205 T NextId = 3;
206};
207
208namespace detail {
209
210// FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation
211// supports classes without default constructors.
212#ifdef _MSC_VER
213
214namespace 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.
220class MSVCPError : public Error {
221public:
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.
235template <typename T> class MSVCPExpected : public Expected<T> {
236public:
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.
278template <typename T> class FunctionArgsTuple;
279
280template <typename RetT, typename... ArgTs>
281class FunctionArgsTuple<RetT(ArgTs...)> {
282public:
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.
289template <typename RetT> class ResultTraits {
290public:
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.
321template <> class ResultTraits<void> {
322public:
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.
356template <> 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.
362template <typename RetT>
363class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {};
364
365// Determines whether an RPC function's defined error return type supports
366// error return value.
367template <typename T>
368class SupportsErrorReturn {
369public:
370 static const bool value = false;
371};
372
373template <>
374class SupportsErrorReturn<Error> {
375public:
376 static const bool value = true;
377};
378
379template <typename T>
380class SupportsErrorReturn<Expected<T>> {
381public:
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.
387template <bool FuncSupportsErrorReturn>
388class RespondHelper;
389
390// RespondHelper specialization for functions that support error returns.
391template <>
392class RespondHelper<true> {
393public:
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.
434template <>
435class RespondHelper<false> {
436public:
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.
475template <typename WireRetT, typename HandlerRetT, typename ChannelT,
476 typename FunctionIdT, typename SequenceNumberT>
477Error 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.
485template <typename WireRetT, typename ChannelT, typename FunctionIdT,
486 typename SequenceNumberT>
487Error 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.
494template <typename T> class WrappedHandlerReturn {
495public:
496 using Type = Expected<T>;
497};
498
499template <typename T> class WrappedHandlerReturn<Expected<T>> {
500public:
501 using Type = Expected<T>;
502};
503
504template <> class WrappedHandlerReturn<void> {
505public:
506 using Type = Error;
507};
508
509template <> class WrappedHandlerReturn<Error> {
510public:
511 using Type = Error;
512};
513
514template <> class WrappedHandlerReturn<ErrorSuccess> {
515public:
516 using Type = Error;
517};
518
519// Traits class that strips the response function from the list of handler
520// arguments.
521template <typename FnT> class AsyncHandlerTraits;
522
523template <typename ResultT, typename... ArgTs>
524class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> {
525public:
526 using Type = Error(ArgTs...);
527 using ResultType = Expected<ResultT>;
528};
529
530template <typename... ArgTs>
531class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> {
532public:
533 using Type = Error(ArgTs...);
534 using ResultType = Error;
535};
536
537template <typename... ArgTs>
538class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> {
539public:
540 using Type = Error(ArgTs...);
541 using ResultType = Error;
542};
543
544template <typename... ArgTs>
545class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> {
546public:
547 using Type = Error(ArgTs...);
548 using ResultType = Error;
549};
550
551template <typename ResponseHandlerT, typename... ArgTs>
552class 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.
560template <typename HandlerT>
561class HandlerTraits : public HandlerTraits<decltype(
562 &std::remove_reference<HandlerT>::type::operator())> {
563};
564
565// Traits for handlers with a given function type.
566template <typename RetT, typename... ArgTs>
567class HandlerTraits<RetT(ArgTs...)> {
568public:
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
622private:
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.
651template <typename RetT, typename... ArgTs>
652class HandlerTraits<RetT(*)(ArgTs...)>
653 : public HandlerTraits<RetT(ArgTs...)> {};
654
655// Handler traits for class methods (especially call operators for lambdas).
656template <typename Class, typename RetT, typename... ArgTs>
657class HandlerTraits<RetT (Class::*)(ArgTs...)>
658 : public HandlerTraits<RetT(ArgTs...)> {};
659
660// Handler traits for const class methods (especially call operators for
661// lambdas).
662template <typename Class, typename RetT, typename... ArgTs>
663class HandlerTraits<RetT (Class::*)(ArgTs...) const>
664 : public HandlerTraits<RetT(ArgTs...)> {};
665
666// Utility to peel the Expected wrapper off a response handler error type.
667template <typename HandlerT> class ResponseHandlerArg;
668
669template <typename ArgT> class ResponseHandlerArg<Error(Expected<ArgT>)> {
670public:
671 using ArgType = Expected<ArgT>;
672 using UnwrappedArgType = ArgT;
673};
674
675template <typename ArgT>
676class ResponseHandlerArg<ErrorSuccess(Expected<ArgT>)> {
677public:
678 using ArgType = Expected<ArgT>;
679 using UnwrappedArgType = ArgT;
680};
681
682template <> class ResponseHandlerArg<Error(Error)> {
683public:
684 using ArgType = Error;
685};
686
687template <> class ResponseHandlerArg<ErrorSuccess(Error)> {
688public:
689 using ArgType = Error;
690};
691
692// ResponseHandler represents a handler for a not-yet-received function call
693// result.
694template <typename ChannelT> class ResponseHandler {
695public:
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.
714template <typename ChannelT, typename FuncRetT, typename HandlerT>
715class ResponseHandlerImpl : public ResponseHandler<ChannelT> {
716public:
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
743private:
744 HandlerT Handler;
745};
746
747// ResponseHandler subclass for RPC functions with void returns.
748template <typename ChannelT, typename HandlerT>
749class ResponseHandlerImpl<ChannelT, void, HandlerT>
750 : public ResponseHandler<ChannelT> {
751public:
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
772private:
773 HandlerT Handler;
774};
775
776template <typename ChannelT, typename FuncRetT, typename HandlerT>
777class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT>
778 : public ResponseHandler<ChannelT> {
779public:
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
807private:
808 HandlerT Handler;
809};
810
811template <typename ChannelT, typename HandlerT>
812class ResponseHandlerImpl<ChannelT, Error, HandlerT>
813 : public ResponseHandler<ChannelT> {
814public:
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
838private:
839 HandlerT Handler;
840};
841
842// Create a ResponseHandler from a given user handler.
843template <typename ChannelT, typename FuncRetT, typename HandlerT>
844std::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.
851template <typename ClassT, typename RetT, typename... ArgTs>
852class MemberFnWrapper {
853public:
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
861private:
862 ClassT &Instance;
863 MethodT Method;
864};
865
866// Helper that provides a Functor for deserializing arguments.
867template <typename... ArgTs> class ReadArgs {
868public:
869 Error operator()() { return Error::success(); }
870};
871
872template <typename ArgT, typename... ArgTs>
873class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
874public:
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
883private:
884 ArgT &Arg;
885};
886
887// Manage sequence numbers.
888template <typename SequenceNumberT> class SequenceNumberManager {
889public:
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
914private:
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.
922template <template <class, class> class P, typename T1Tuple, typename T2Tuple>
923class RPCArgTypeCheckHelper;
924
925template <template <class, class> class P>
926class RPCArgTypeCheckHelper<P, std::tuple<>, std::tuple<>> {
927public:
928 static const bool value = true;
929};
930
931template <template <class, class> class P, typename T, typename... Ts,
932 typename U, typename... Us>
933class RPCArgTypeCheckHelper<P, std::tuple<T, Ts...>, std::tuple<U, Us...>> {
934public:
935 static const bool value =
936 P<T, U>::value &&
937 RPCArgTypeCheckHelper<P, std::tuple<Ts...>, std::tuple<Us...>>::value;
938};
939
940template <template <class, class> class P, typename T1Sig, typename T2Sig>
941class RPCArgTypeCheck {
942public:
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
956template <typename ChannelT, typename WireT, typename ConcreteT>
957class CanSerialize {
958private:
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
971public:
972 static const bool value = decltype(check<S>(0))::value;
973};
974
975template <typename ChannelT, typename WireT, typename ConcreteT>
976class CanDeserialize {
977private:
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
990public:
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.
1004template <typename ImplT, typename ChannelT, typename FunctionIdT,
1005 typename SequenceNumberT>
1006class RPCEndpointBase {
1007protected:
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
1049public:
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;
60
'SeqNo' declared without an initial value
1146 if (auto Err = C.startReceiveMessage(FnId, SeqNo)) {
61
Calling 'RawByteChannel::startReceiveMessage'
139
Returning from 'RawByteChannel::startReceiveMessage'
140
Taking false branch
1147 abandonPendingResponses();
1148 return Err;
1149 }
1150 if (FnId == ResponseId)
141
Taking false branch
1151 return handleResponse(SeqNo);
1152 auto I = Handlers.find(FnId);
1153 if (I != Handlers.end())
142
Assuming the condition is true
143
Taking true branch
1154 return I->second(C, SeqNo);
144
2nd function call argument is an uninitialized value
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
1215protected:
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
1420template <typename ChannelT, typename FunctionIdT = uint32_t,
1421 typename SequenceNumberT = uint32_t>
1422class MultiThreadedRPCEndpoint
1423 : public detail::RPCEndpointBase<
1424 MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1425 ChannelT, FunctionIdT, SequenceNumberT> {
1426private:
1427 using BaseClass =
1428 detail::RPCEndpointBase<
1429 MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1430 ChannelT, FunctionIdT, SequenceNumberT>;
1431
1432public:
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
1538template <typename ChannelT, typename FunctionIdT = uint32_t,
1539 typename SequenceNumberT = uint32_t>
1540class SingleThreadedRPCEndpoint
1541 : public detail::RPCEndpointBase<
1542 SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1543 ChannelT, FunctionIdT, SequenceNumberT> {
1544private:
1545 using BaseClass =
1546 detail::RPCEndpointBase<
1547 SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1548 ChannelT, FunctionIdT, SequenceNumberT>;
1549
1550public:
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>(
56
Taking false branch
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) {
57
Assuming 'ReceivedResponse' is 0
58
Loop condition is true. Entering loop body
1602 if (auto Err = this->handleOne()) {
59
Calling 'RPCEndpointBase::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.
1614template <typename RPCClass, typename Func>
1615class RPCAsyncDispatch {
1616public:
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
1624private:
1625 RPCClass &Endpoint;
1626};
1627
1628/// Construct an asynchronous dispatcher from an RPC endpoint and a Func.
1629template <typename Func, typename RPCEndpointT>
1630RPCAsyncDispatch<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.
1636class ParallelCallGroup {
1637public:
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
1680private:
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///
1689template <typename... Funcs>
1690class APICalls {
1691public:
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
1707template <typename Func, typename... Funcs>
1708class APICalls<Func, Funcs...> {
1709public:
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
1727template <typename... InnerFuncs, typename... Funcs>
1728class APICalls<APICalls<InnerFuncs...>, Funcs...> {
1729public:
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

/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RawByteChannel.h

1//===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- 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#ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
11#define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
12
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
15#include "llvm/Support/Endian.h"
16#include "llvm/Support/Error.h"
17#include <cstdint>
18#include <mutex>
19#include <string>
20#include <type_traits>
21
22namespace llvm {
23namespace orc {
24namespace rpc {
25
26/// Interface for byte-streams to be used with RPC.
27class RawByteChannel {
28public:
29 virtual ~RawByteChannel() = default;
30
31 /// Read Size bytes from the stream into *Dst.
32 virtual Error readBytes(char *Dst, unsigned Size) = 0;
33
34 /// Read size bytes from *Src and append them to the stream.
35 virtual Error appendBytes(const char *Src, unsigned Size) = 0;
36
37 /// Flush the stream if possible.
38 virtual Error send() = 0;
39
40 /// Notify the channel that we're starting a message send.
41 /// Locks the channel for writing.
42 template <typename FunctionIdT, typename SequenceIdT>
43 Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) {
44 writeLock.lock();
45 if (auto Err = serializeSeq(*this, FnId, SeqNo)) {
46 writeLock.unlock();
47 return Err;
48 }
49 return Error::success();
50 }
51
52 /// Notify the channel that we're ending a message send.
53 /// Unlocks the channel for writing.
54 Error endSendMessage() {
55 writeLock.unlock();
56 return Error::success();
57 }
58
59 /// Notify the channel that we're starting a message receive.
60 /// Locks the channel for reading.
61 template <typename FunctionIdT, typename SequenceNumberT>
62 Error startReceiveMessage(FunctionIdT &FnId, SequenceNumberT &SeqNo) {
63 readLock.lock();
62
Calling 'mutex::lock'
65
Returning from 'mutex::lock'
64 if (auto Err = deserializeSeq(*this, FnId, SeqNo)) {
66
Calling 'deserializeSeq'
92
Returning from 'deserializeSeq'
93
Calling move constructor for 'Error'
117
Returning from move constructor for 'Error'
118
Calling 'Error::operator bool'
127
Returning from 'Error::operator bool'
128
Taking false branch
65 readLock.unlock();
66 return Err;
67 }
129
Calling '~Error'
136
Returning from '~Error'
68 return Error::success();
137
Calling 'Error::success'
138
Returning from 'Error::success'
69 }
70
71 /// Notify the channel that we're ending a message receive.
72 /// Unlocks the channel for reading.
73 Error endReceiveMessage() {
74 readLock.unlock();
75 return Error::success();
76 }
77
78 /// Get the lock for stream reading.
79 std::mutex &getReadLock() { return readLock; }
80
81 /// Get the lock for stream writing.
82 std::mutex &getWriteLock() { return writeLock; }
83
84private:
85 std::mutex readLock, writeLock;
86};
87
88template <typename ChannelT, typename T>
89class SerializationTraits<
90 ChannelT, T, T,
91 typename std::enable_if<
92 std::is_base_of<RawByteChannel, ChannelT>::value &&
93 (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value ||
94 std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
95 std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
96 std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
97 std::is_same<T, char>::value)>::type> {
98public:
99 static Error serialize(ChannelT &C, T V) {
100 support::endian::byte_swap<T, support::big>(V);
101 return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
102 };
103
104 static Error deserialize(ChannelT &C, T &V) {
105 if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
106 return Err;
107 support::endian::byte_swap<T, support::big>(V);
108 return Error::success();
109 };
110};
111
112template <typename ChannelT>
113class SerializationTraits<ChannelT, bool, bool,
114 typename std::enable_if<std::is_base_of<
115 RawByteChannel, ChannelT>::value>::type> {
116public:
117 static Error serialize(ChannelT &C, bool V) {
118 uint8_t Tmp = V ? 1 : 0;
119 if (auto Err =
120 C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1))
121 return Err;
122 return Error::success();
123 }
124
125 static Error deserialize(ChannelT &C, bool &V) {
126 uint8_t Tmp = 0;
127 if (auto Err = C.readBytes(reinterpret_cast<char *>(&Tmp), 1))
128 return Err;
129 V = Tmp != 0;
130 return Error::success();
131 }
132};
133
134template <typename ChannelT>
135class SerializationTraits<ChannelT, std::string, StringRef,
136 typename std::enable_if<std::is_base_of<
137 RawByteChannel, ChannelT>::value>::type> {
138public:
139 /// RPC channel serialization for std::strings.
140 static Error serialize(RawByteChannel &C, StringRef S) {
141 if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
142 return Err;
143 return C.appendBytes((const char *)S.data(), S.size());
144 }
145};
146
147template <typename ChannelT, typename T>
148class SerializationTraits<ChannelT, std::string, T,
149 typename std::enable_if<
150 std::is_base_of<RawByteChannel, ChannelT>::value &&
151 (std::is_same<T, const char*>::value ||
152 std::is_same<T, char*>::value)>::type> {
153public:
154 static Error serialize(RawByteChannel &C, const char *S) {
155 return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
156 S);
157 }
158};
159
160template <typename ChannelT>
161class SerializationTraits<ChannelT, std::string, std::string,
162 typename std::enable_if<std::is_base_of<
163 RawByteChannel, ChannelT>::value>::type> {
164public:
165 /// RPC channel serialization for std::strings.
166 static Error serialize(RawByteChannel &C, const std::string &S) {
167 return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
168 S);
169 }
170
171 /// RPC channel deserialization for std::strings.
172 static Error deserialize(RawByteChannel &C, std::string &S) {
173 uint64_t Count = 0;
174 if (auto Err = deserializeSeq(C, Count))
175 return Err;
176 S.resize(Count);
177 return C.readBytes(&S[0], Count);
178 }
179};
180
181} // end namespace rpc
182} // end namespace orc
183} // end namespace llvm
184
185#endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H

/usr/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/std_mutex.h

1// std::mutex implementation -*- C++ -*-
2
3// Copyright (C) 2003-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/std_mutex.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{mutex}
28 */
29
30#ifndef _GLIBCXX_MUTEX_H1
31#define _GLIBCXX_MUTEX_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201103L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#include <system_error>
40#include <bits/functexcept.h>
41#include <bits/gthr.h>
42#include <bits/move.h> // for std::swap
43
44#ifdef _GLIBCXX_USE_C99_STDINT_TR11
45
46namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50 /**
51 * @defgroup mutexes Mutexes
52 * @ingroup concurrency
53 *
54 * Classes for mutex support.
55 * @{
56 */
57
58#ifdef _GLIBCXX_HAS_GTHREADS1
59 // Common base class for std::mutex and std::timed_mutex
60 class __mutex_base
61 {
62 protected:
63 typedef __gthread_mutex_t __native_type;
64
65#ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
66 __native_type _M_mutex = __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
67
68 constexpr __mutex_base() noexcept = default;
69#else
70 __native_type _M_mutex;
71
72 __mutex_base() noexcept
73 {
74 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
75 __GTHREAD_MUTEX_INIT_FUNCTION__gthread_mutex_init_function(&_M_mutex);
76 }
77
78 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
79#endif
80
81 __mutex_base(const __mutex_base&) = delete;
82 __mutex_base& operator=(const __mutex_base&) = delete;
83 };
84
85 /// The standard mutex type.
86 class mutex : private __mutex_base
87 {
88 public:
89 typedef __native_type* native_handle_type;
90
91#ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
92 constexpr
93#endif
94 mutex() noexcept = default;
95 ~mutex() = default;
96
97 mutex(const mutex&) = delete;
98 mutex& operator=(const mutex&) = delete;
99
100 void
101 lock()
102 {
103 int __e = __gthread_mutex_lock(&_M_mutex);
104
105 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
106 if (__e)
63
Assuming '__e' is 0
64
Taking false branch
107 __throw_system_error(__e);
108 }
109
110 bool
111 try_lock() noexcept
112 {
113 // XXX EINVAL, EAGAIN, EBUSY
114 return !__gthread_mutex_trylock(&_M_mutex);
115 }
116
117 void
118 unlock()
119 {
120 // XXX EINVAL, EAGAIN, EPERM
121 __gthread_mutex_unlock(&_M_mutex);
122 }
123
124 native_handle_type
125 native_handle() noexcept
126 { return &_M_mutex; }
127 };
128
129#endif // _GLIBCXX_HAS_GTHREADS
130
131 /// Do not acquire ownership of the mutex.
132 struct defer_lock_t { explicit defer_lock_t() = default; };
133
134 /// Try to acquire ownership of the mutex without blocking.
135 struct try_to_lock_t { explicit try_to_lock_t() = default; };
136
137 /// Assume the calling thread has already obtained mutex ownership
138 /// and manage it.
139 struct adopt_lock_t { explicit adopt_lock_t() = default; };
140
141 /// Tag used to prevent a scoped lock from acquiring ownership of a mutex.
142 _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { };
143
144 /// Tag used to prevent a scoped lock from blocking if a mutex is locked.
145 _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { };
146
147 /// Tag used to make a scoped lock take ownership of a locked mutex.
148 _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { };
149
150 /** @brief A simple scoped lock type.
151 *
152 * A lock_guard controls mutex ownership within a scope, releasing
153 * ownership in the destructor.
154 */
155 template<typename _Mutex>
156 class lock_guard
157 {
158 public:
159 typedef _Mutex mutex_type;
160
161 explicit lock_guard(mutex_type& __m) : _M_device(__m)
162 { _M_device.lock(); }
163
164 lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)
165 { } // calling thread owns mutex
166
167 ~lock_guard()
168 { _M_device.unlock(); }
169
170 lock_guard(const lock_guard&) = delete;
171 lock_guard& operator=(const lock_guard&) = delete;
172
173 private:
174 mutex_type& _M_device;
175 };
176
177 /** @brief A movable scoped lock type.
178 *
179 * A unique_lock controls mutex ownership within a scope. Ownership of the
180 * mutex can be delayed until after construction and can be transferred
181 * to another unique_lock by move construction or move assignment. If a
182 * mutex lock is owned when the destructor runs ownership will be released.
183 */
184 template<typename _Mutex>
185 class unique_lock
186 {
187 public:
188 typedef _Mutex mutex_type;
189
190 unique_lock() noexcept
191 : _M_device(0), _M_owns(false)
192 { }
193
194 explicit unique_lock(mutex_type& __m)
195 : _M_device(std::__addressof(__m)), _M_owns(false)
196 {
197 lock();
198 _M_owns = true;
199 }
200
201 unique_lock(mutex_type& __m, defer_lock_t) noexcept
202 : _M_device(std::__addressof(__m)), _M_owns(false)
203 { }
204
205 unique_lock(mutex_type& __m, try_to_lock_t)
206 : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
207 { }
208
209 unique_lock(mutex_type& __m, adopt_lock_t) noexcept
210 : _M_device(std::__addressof(__m)), _M_owns(true)
211 {
212 // XXX calling thread owns mutex
213 }
214
215 template<typename _Clock, typename _Duration>
216 unique_lock(mutex_type& __m,
217 const chrono::time_point<_Clock, _Duration>& __atime)
218 : _M_device(std::__addressof(__m)),
219 _M_owns(_M_device->try_lock_until(__atime))
220 { }
221
222 template<typename _Rep, typename _Period>
223 unique_lock(mutex_type& __m,
224 const chrono::duration<_Rep, _Period>& __rtime)
225 : _M_device(std::__addressof(__m)),
226 _M_owns(_M_device->try_lock_for(__rtime))
227 { }
228
229 ~unique_lock()
230 {
231 if (_M_owns)
232 unlock();
233 }
234
235 unique_lock(const unique_lock&) = delete;
236 unique_lock& operator=(const unique_lock&) = delete;
237
238 unique_lock(unique_lock&& __u) noexcept
239 : _M_device(__u._M_device), _M_owns(__u._M_owns)
240 {
241 __u._M_device = 0;
242 __u._M_owns = false;
243 }
244
245 unique_lock& operator=(unique_lock&& __u) noexcept
246 {
247 if(_M_owns)
248 unlock();
249
250 unique_lock(std::move(__u)).swap(*this);
251
252 __u._M_device = 0;
253 __u._M_owns = false;
254
255 return *this;
256 }
257
258 void
259 lock()
260 {
261 if (!_M_device)
262 __throw_system_error(int(errc::operation_not_permitted));
263 else if (_M_owns)
264 __throw_system_error(int(errc::resource_deadlock_would_occur));
265 else
266 {
267 _M_device->lock();
268 _M_owns = true;
269 }
270 }
271
272 bool
273 try_lock()
274 {
275 if (!_M_device)
276 __throw_system_error(int(errc::operation_not_permitted));
277 else if (_M_owns)
278 __throw_system_error(int(errc::resource_deadlock_would_occur));
279 else
280 {
281 _M_owns = _M_device->try_lock();
282 return _M_owns;
283 }
284 }
285
286 template<typename _Clock, typename _Duration>
287 bool
288 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
289 {
290 if (!_M_device)
291 __throw_system_error(int(errc::operation_not_permitted));
292 else if (_M_owns)
293 __throw_system_error(int(errc::resource_deadlock_would_occur));
294 else
295 {
296 _M_owns = _M_device->try_lock_until(__atime);
297 return _M_owns;
298 }
299 }
300
301 template<typename _Rep, typename _Period>
302 bool
303 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
304 {
305 if (!_M_device)
306 __throw_system_error(int(errc::operation_not_permitted));
307 else if (_M_owns)
308 __throw_system_error(int(errc::resource_deadlock_would_occur));
309 else
310 {
311 _M_owns = _M_device->try_lock_for(__rtime);
312 return _M_owns;
313 }
314 }
315
316 void
317 unlock()
318 {
319 if (!_M_owns)
320 __throw_system_error(int(errc::operation_not_permitted));
321 else if (_M_device)
322 {
323 _M_device->unlock();
324 _M_owns = false;
325 }
326 }
327
328 void
329 swap(unique_lock& __u) noexcept
330 {
331 std::swap(_M_device, __u._M_device);
332 std::swap(_M_owns, __u._M_owns);
333 }
334
335 mutex_type*
336 release() noexcept
337 {
338 mutex_type* __ret = _M_device;
339 _M_device = 0;
340 _M_owns = false;
341 return __ret;
342 }
343
344 bool
345 owns_lock() const noexcept
346 { return _M_owns; }
347
348 explicit operator bool() const noexcept
349 { return owns_lock(); }
350
351 mutex_type*
352 mutex() const noexcept
353 { return _M_device; }
354
355 private:
356 mutex_type* _M_device;
357 bool _M_owns; // XXX use atomic_bool
358 };
359
360 /// Swap overload for unique_lock objects.
361 template<typename _Mutex>
362 inline void
363 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
364 { __x.swap(__y); }
365
366 // @} group mutexes
367_GLIBCXX_END_NAMESPACE_VERSION
368} // namespace
369#endif // _GLIBCXX_USE_C99_STDINT_TR1
370
371#endif // C++11
372
373#endif // _GLIBCXX_MUTEX_H

/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h

1//===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- 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#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
11#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
12
13#include "OrcError.h"
14#include "llvm/Support/thread.h"
15#include <map>
16#include <mutex>
17#include <sstream>
18
19namespace llvm {
20namespace orc {
21namespace rpc {
22
23template <typename T>
24class RPCTypeName;
25
26/// TypeNameSequence is a utility for rendering sequences of types to a string
27/// by rendering each type, separated by ", ".
28template <typename... ArgTs> class RPCTypeNameSequence {};
29
30/// Render an empty TypeNameSequence to an ostream.
31template <typename OStream>
32OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
33 return OS;
34}
35
36/// Render a TypeNameSequence of a single type to an ostream.
37template <typename OStream, typename ArgT>
38OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
39 OS << RPCTypeName<ArgT>::getName();
40 return OS;
41}
42
43/// Render a TypeNameSequence of more than one type to an ostream.
44template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
45OStream&
46operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
47 OS << RPCTypeName<ArgT1>::getName() << ", "
48 << RPCTypeNameSequence<ArgT2, ArgTs...>();
49 return OS;
50}
51
52template <>
53class RPCTypeName<void> {
54public:
55 static const char* getName() { return "void"; }
56};
57
58template <>
59class RPCTypeName<int8_t> {
60public:
61 static const char* getName() { return "int8_t"; }
62};
63
64template <>
65class RPCTypeName<uint8_t> {
66public:
67 static const char* getName() { return "uint8_t"; }
68};
69
70template <>
71class RPCTypeName<int16_t> {
72public:
73 static const char* getName() { return "int16_t"; }
74};
75
76template <>
77class RPCTypeName<uint16_t> {
78public:
79 static const char* getName() { return "uint16_t"; }
80};
81
82template <>
83class RPCTypeName<int32_t> {
84public:
85 static const char* getName() { return "int32_t"; }
86};
87
88template <>
89class RPCTypeName<uint32_t> {
90public:
91 static const char* getName() { return "uint32_t"; }
92};
93
94template <>
95class RPCTypeName<int64_t> {
96public:
97 static const char* getName() { return "int64_t"; }
98};
99
100template <>
101class RPCTypeName<uint64_t> {
102public:
103 static const char* getName() { return "uint64_t"; }
104};
105
106template <>
107class RPCTypeName<bool> {
108public:
109 static const char* getName() { return "bool"; }
110};
111
112template <>
113class RPCTypeName<std::string> {
114public:
115 static const char* getName() { return "std::string"; }
116};
117
118template <>
119class RPCTypeName<Error> {
120public:
121 static const char* getName() { return "Error"; }
122};
123
124template <typename T>
125class RPCTypeName<Expected<T>> {
126public:
127 static const char* getName() {
128 std::lock_guard<std::mutex> Lock(NameMutex);
129 if (Name.empty())
130 raw_string_ostream(Name) << "Expected<"
131 << RPCTypeNameSequence<T>()
132 << ">";
133 return Name.data();
134 }
135
136private:
137 static std::mutex NameMutex;
138 static std::string Name;
139};
140
141template <typename T>
142std::mutex RPCTypeName<Expected<T>>::NameMutex;
143
144template <typename T>
145std::string RPCTypeName<Expected<T>>::Name;
146
147template <typename T1, typename T2>
148class RPCTypeName<std::pair<T1, T2>> {
149public:
150 static const char* getName() {
151 std::lock_guard<std::mutex> Lock(NameMutex);
152 if (Name.empty())
153 raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
154 << ">";
155 return Name.data();
156 }
157private:
158 static std::mutex NameMutex;
159 static std::string Name;
160};
161
162template <typename T1, typename T2>
163std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
164template <typename T1, typename T2>
165std::string RPCTypeName<std::pair<T1, T2>>::Name;
166
167template <typename... ArgTs>
168class RPCTypeName<std::tuple<ArgTs...>> {
169public:
170 static const char* getName() {
171 std::lock_guard<std::mutex> Lock(NameMutex);
172 if (Name.empty())
173 raw_string_ostream(Name) << "std::tuple<"
174 << RPCTypeNameSequence<ArgTs...>() << ">";
175 return Name.data();
176 }
177private:
178 static std::mutex NameMutex;
179 static std::string Name;
180};
181
182template <typename... ArgTs>
183std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
184template <typename... ArgTs>
185std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
186
187template <typename T>
188class RPCTypeName<std::vector<T>> {
189public:
190 static const char*getName() {
191 std::lock_guard<std::mutex> Lock(NameMutex);
192 if (Name.empty())
193 raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
194 << ">";
195 return Name.data();
196 }
197
198private:
199 static std::mutex NameMutex;
200 static std::string Name;
201};
202
203template <typename T>
204std::mutex RPCTypeName<std::vector<T>>::NameMutex;
205template <typename T>
206std::string RPCTypeName<std::vector<T>>::Name;
207
208
209/// The SerializationTraits<ChannelT, T> class describes how to serialize and
210/// deserialize an instance of type T to/from an abstract channel of type
211/// ChannelT. It also provides a representation of the type's name via the
212/// getName method.
213///
214/// Specializations of this class should provide the following functions:
215///
216/// @code{.cpp}
217///
218/// static const char* getName();
219/// static Error serialize(ChannelT&, const T&);
220/// static Error deserialize(ChannelT&, T&);
221///
222/// @endcode
223///
224/// The third argument of SerializationTraits is intended to support SFINAE.
225/// E.g.:
226///
227/// @code{.cpp}
228///
229/// class MyVirtualChannel { ... };
230///
231/// template <DerivedChannelT>
232/// class SerializationTraits<DerivedChannelT, bool,
233/// typename std::enable_if<
234/// std::is_base_of<VirtChannel, DerivedChannel>::value
235/// >::type> {
236/// public:
237/// static const char* getName() { ... };
238/// }
239///
240/// @endcode
241template <typename ChannelT, typename WireType,
242 typename ConcreteType = WireType, typename = void>
243class SerializationTraits;
244
245template <typename ChannelT>
246class SequenceTraits {
247public:
248 static Error emitSeparator(ChannelT &C) { return Error::success(); }
249 static Error consumeSeparator(ChannelT &C) { return Error::success(); }
250};
251
252/// Utility class for serializing sequences of values of varying types.
253/// Specializations of this class contain 'serialize' and 'deserialize' methods
254/// for the given channel. The ArgTs... list will determine the "over-the-wire"
255/// types to be serialized. The serialize and deserialize methods take a list
256/// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
257/// but may be different types from ArgTs, provided that for each CArgT there
258/// is a SerializationTraits specialization
259/// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
260/// caller argument to over-the-wire value.
261template <typename ChannelT, typename... ArgTs>
262class SequenceSerialization;
263
264template <typename ChannelT>
265class SequenceSerialization<ChannelT> {
266public:
267 static Error serialize(ChannelT &C) { return Error::success(); }
268 static Error deserialize(ChannelT &C) { return Error::success(); }
269};
270
271template <typename ChannelT, typename ArgT>
272class SequenceSerialization<ChannelT, ArgT> {
273public:
274
275 template <typename CArgT>
276 static Error serialize(ChannelT &C, CArgT &&CArg) {
277 return SerializationTraits<ChannelT, ArgT,
278 typename std::decay<CArgT>::type>::
279 serialize(C, std::forward<CArgT>(CArg));
280 }
281
282 template <typename CArgT>
283 static Error deserialize(ChannelT &C, CArgT &CArg) {
284 return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
285 }
286};
287
288template <typename ChannelT, typename ArgT, typename... ArgTs>
289class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
290public:
291
292 template <typename CArgT, typename... CArgTs>
293 static Error serialize(ChannelT &C, CArgT &&CArg,
294 CArgTs &&... CArgs) {
295 if (auto Err =
296 SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
297 serialize(C, std::forward<CArgT>(CArg)))
298 return Err;
299 if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
300 return Err;
301 return SequenceSerialization<ChannelT, ArgTs...>::
302 serialize(C, std::forward<CArgTs>(CArgs)...);
303 }
304
305 template <typename CArgT, typename... CArgTs>
306 static Error deserialize(ChannelT &C, CArgT &CArg,
307 CArgTs &... CArgs) {
308 if (auto Err =
80
Calling 'Error::operator bool'
85
Returning from 'Error::operator bool'
86
Taking true branch
309 SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
68
Calling move constructor for 'Error'
79
Returning from move constructor for 'Error'
310 return Err;
87
Calling '~Error'
90
Returning from '~Error'
311 if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
312 return Err;
313 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
314 }
315};
316
317template <typename ChannelT, typename... ArgTs>
318Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
319 return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
320 serialize(C, std::forward<ArgTs>(Args)...);
321}
322
323template <typename ChannelT, typename... ArgTs>
324Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
325 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
67
Calling 'SequenceSerialization::deserialize'
91
Returning from 'SequenceSerialization::deserialize'
326}
327
328template <typename ChannelT>
329class SerializationTraits<ChannelT, Error> {
330public:
331
332 using WrappedErrorSerializer =
333 std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
334
335 using WrappedErrorDeserializer =
336 std::function<Error(ChannelT &C, Error &Err)>;
337
338 template <typename ErrorInfoT, typename SerializeFtor,
339 typename DeserializeFtor>
340 static void registerErrorType(std::string Name, SerializeFtor Serialize,
341 DeserializeFtor Deserialize) {
342 assert(!Name.empty() &&(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value"
) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 343, __extension__ __PRETTY_FUNCTION__))
343 "The empty string is reserved for the Success value")(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value"
) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 343, __extension__ __PRETTY_FUNCTION__))
;
344
345 const std::string *KeyName = nullptr;
346 {
347 // We're abusing the stability of std::map here: We take a reference to the
348 // key of the deserializers map to save us from duplicating the string in
349 // the serializer. This should be changed to use a stringpool if we switch
350 // to a map type that may move keys in memory.
351 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
352 auto I =
353 Deserializers.insert(Deserializers.begin(),
354 std::make_pair(std::move(Name),
355 std::move(Deserialize)));
356 KeyName = &I->first;
357 }
358
359 {
360 assert(KeyName != nullptr && "No keyname pointer")(static_cast <bool> (KeyName != nullptr && "No keyname pointer"
) ? void (0) : __assert_fail ("KeyName != nullptr && \"No keyname pointer\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 360, __extension__ __PRETTY_FUNCTION__))
;
361 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
362 // FIXME: Move capture Serialize once we have C++14.
363 Serializers[ErrorInfoT::classID()] =
364 [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
365 assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT
::classID() && "Serializer called for wrong error type"
) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 366, __extension__ __PRETTY_FUNCTION__))
366 "Serializer called for wrong error type")(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT
::classID() && "Serializer called for wrong error type"
) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 366, __extension__ __PRETTY_FUNCTION__))
;
367 if (auto Err = serializeSeq(C, *KeyName))
368 return Err;
369 return Serialize(C, static_cast<const ErrorInfoT &>(EIB));
370 };
371 }
372 }
373
374 static Error serialize(ChannelT &C, Error &&Err) {
375 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
376
377 if (!Err)
378 return serializeSeq(C, std::string());
379
380 return handleErrors(std::move(Err),
381 [&C](const ErrorInfoBase &EIB) {
382 auto SI = Serializers.find(EIB.dynamicClassID());
383 if (SI == Serializers.end())
384 return serializeAsStringError(C, EIB);
385 return (SI->second)(C, EIB);
386 });
387 }
388
389 static Error deserialize(ChannelT &C, Error &Err) {
390 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
391
392 std::string Key;
393 if (auto Err = deserializeSeq(C, Key))
394 return Err;
395
396 if (Key.empty()) {
397 ErrorAsOutParameter EAO(&Err);
398 Err = Error::success();
399 return Error::success();
400 }
401
402 auto DI = Deserializers.find(Key);
403 assert(DI != Deserializers.end() && "No deserializer for error type")(static_cast <bool> (DI != Deserializers.end() &&
"No deserializer for error type") ? void (0) : __assert_fail
("DI != Deserializers.end() && \"No deserializer for error type\""
, "/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 403, __extension__ __PRETTY_FUNCTION__))
;
404 return (DI->second)(C, Err);
405 }
406
407private:
408
409 static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
410 std::string ErrMsg;
411 {
412 raw_string_ostream ErrMsgStream(ErrMsg);
413 EIB.log(ErrMsgStream);
414 }
415 return serialize(C, make_error<StringError>(std::move(ErrMsg),
416 inconvertibleErrorCode()));
417 }
418
419 static std::recursive_mutex SerializersMutex;
420 static std::recursive_mutex DeserializersMutex;
421 static std::map<const void*, WrappedErrorSerializer> Serializers;
422 static std::map<std::string, WrappedErrorDeserializer> Deserializers;
423};
424
425template <typename ChannelT>
426std::recursive_mutex SerializationTraits<ChannelT, Error>::SerializersMutex;
427
428template <typename ChannelT>
429std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
430
431template <typename ChannelT>
432std::map<const void*,
433 typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
434SerializationTraits<ChannelT, Error>::Serializers;
435
436template <typename ChannelT>
437std::map<std::string,
438 typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
439SerializationTraits<ChannelT, Error>::Deserializers;
440
441/// Registers a serializer and deserializer for the given error type on the
442/// given channel type.
443template <typename ChannelT, typename ErrorInfoT, typename SerializeFtor,
444 typename DeserializeFtor>
445void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize,
446 DeserializeFtor &&Deserialize) {
447 SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>(
448 std::move(Name),
449 std::forward<SerializeFtor>(Serialize),
450 std::forward<DeserializeFtor>(Deserialize));
451}
452
453/// Registers serialization/deserialization for StringError.
454template <typename ChannelT>
455void registerStringError() {
456 static bool AlreadyRegistered = false;
457 if (!AlreadyRegistered) {
458 registerErrorSerialization<ChannelT, StringError>(
459 "StringError",
460 [](ChannelT &C, const StringError &SE) {
461 return serializeSeq(C, SE.getMessage());
462 },
463 [](ChannelT &C, Error &Err) -> Error {
464 ErrorAsOutParameter EAO(&Err);
465 std::string Msg;
466 if (auto E2 = deserializeSeq(C, Msg))
467 return E2;
468 Err =
469 make_error<StringError>(std::move(Msg),
470 orcError(
471 OrcErrorCode::UnknownErrorCodeFromRemote));
472 return Error::success();
473 });
474 AlreadyRegistered = true;
475 }
476}
477
478/// SerializationTraits for Expected<T1> from an Expected<T2>.
479template <typename ChannelT, typename T1, typename T2>
480class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
481public:
482
483 static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
484 if (ValOrErr) {
485 if (auto Err = serializeSeq(C, true))
486 return Err;
487 return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr);
488 }
489 if (auto Err = serializeSeq(C, false))
490 return Err;
491 return serializeSeq(C, ValOrErr.takeError());
492 }
493
494 static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) {
495 ExpectedAsOutParameter<T2> EAO(&ValOrErr);
496 bool HasValue;
497 if (auto Err = deserializeSeq(C, HasValue))
498 return Err;
499 if (HasValue)
500 return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr);
501 Error Err = Error::success();
502 if (auto E2 = deserializeSeq(C, Err))
503 return E2;
504 ValOrErr = std::move(Err);
505 return Error::success();
506 }
507};
508
509/// SerializationTraits for Expected<T1> from a T2.
510template <typename ChannelT, typename T1, typename T2>
511class SerializationTraits<ChannelT, Expected<T1>, T2> {
512public:
513
514 static Error serialize(ChannelT &C, T2 &&Val) {
515 return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
516 }
517};
518
519/// SerializationTraits for Expected<T1> from an Error.
520template <typename ChannelT, typename T>
521class SerializationTraits<ChannelT, Expected<T>, Error> {
522public:
523
524 static Error serialize(ChannelT &C, Error &&Err) {
525 return serializeSeq(C, Expected<T>(std::move(Err)));
526 }
527};
528
529/// SerializationTraits default specialization for std::pair.
530template <typename ChannelT, typename T1, typename T2>
531class SerializationTraits<ChannelT, std::pair<T1, T2>> {
532public:
533 static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
534 return serializeSeq(C, V.first, V.second);
535 }
536
537 static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
538 return deserializeSeq(C, V.first, V.second);
539 }
540};
541
542/// SerializationTraits default specialization for std::tuple.
543template <typename ChannelT, typename... ArgTs>
544class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
545public:
546
547 /// RPC channel serialization for std::tuple.
548 static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
549 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
550 }
551
552 /// RPC channel deserialization for std::tuple.
553 static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
554 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
555 }
556
557private:
558 // Serialization helper for std::tuple.
559 template <size_t... Is>
560 static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
561 llvm::index_sequence<Is...> _) {
562 return serializeSeq(C, std::get<Is>(V)...);
563 }
564
565 // Serialization helper for std::tuple.
566 template <size_t... Is>
567 static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
568 llvm::index_sequence<Is...> _) {
569 return deserializeSeq(C, std::get<Is>(V)...);
570 }
571};
572
573/// SerializationTraits default specialization for std::vector.
574template <typename ChannelT, typename T>
575class SerializationTraits<ChannelT, std::vector<T>> {
576public:
577
578 /// Serialize a std::vector<T> from std::vector<T>.
579 static Error serialize(ChannelT &C, const std::vector<T> &V) {
580 if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
581 return Err;
582
583 for (const auto &E : V)
584 if (auto Err = serializeSeq(C, E))
585 return Err;
586
587 return Error::success();
588 }
589
590 /// Deserialize a std::vector<T> to a std::vector<T>.
591 static Error deserialize(ChannelT &C, std::vector<T> &V) {
592 uint64_t Count = 0;
593 if (auto Err = deserializeSeq(C, Count))
594 return Err;
595
596 V.resize(Count);
597 for (auto &E : V)
598 if (auto Err = deserializeSeq(C, E))
599 return Err;
600
601 return Error::success();
602 }
603};
604
605} // end namespace rpc
606} // end namespace orc
607} // end namespace llvm
608
609#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H

/build/llvm-toolchain-snapshot-6.0~svn319013/include/llvm/Support/Error.h

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
41namespace llvm {
42
43class ErrorSuccess;
44
45/// Base class for error info classes. Do not extend this directly: Extend
46/// the ErrorInfo template subclass instead.
47class ErrorInfoBase {
48public:
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
85private:
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.
156class 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
169protected:
170 /// Create a success value. Prefer using 'Error::success()' for readability
171 Error() {
172 setPtr(nullptr);
173 setChecked(false);
174 }
175
176public:
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);
94
Calling 'Error::setChecked'
96
Returning from 'Error::setChecked'
188 *this = std::move(Other);
69
Calling 'move'
70
Returning from 'move'
71
Calling move assignment operator for 'Error'
78
Returning from move assignment operator for 'Error'
97
Calling 'move'
98
Returning from 'move'
99
Calling move assignment operator for 'Error'
116
Returning from move assignment operator for 'Error'
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();
100
Calling 'Error::assertIsChecked'
103
Returning from 'Error::assertIsChecked'
208 setPtr(Other.getPtr());
72
Calling 'Error::getPtr'
73
Returning from 'Error::getPtr'
74
Calling 'Error::setPtr'
75
Returning from 'Error::setPtr'
104
Calling 'Error::getPtr'
105
Returning from 'Error::getPtr'
106
Calling 'Error::setPtr'
107
Returning from 'Error::setPtr'
209
210 // This Error is unchecked, even if the source error was checked.
211 setChecked(false);
108
Calling 'Error::setChecked'
110
Returning from 'Error::setChecked'
212
213 // Null out Other's payload and set its checked bit.
214 Other.setPtr(nullptr);
76
Calling 'Error::setPtr'
77
Returning from 'Error::setPtr'
111
Calling 'Error::setPtr'
112
Returning from 'Error::setPtr'
215 Other.setChecked(true);
113
Calling 'Error::setChecked'
115
Returning from 'Error::setChecked'
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();
130
Calling 'Error::assertIsChecked'
133
Returning from 'Error::assertIsChecked'
224 delete getPtr();
88
Calling 'Error::getPtr'
89
Returning from 'Error::getPtr'
134
Calling 'Error::getPtr'
135
Returning from 'Error::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);
81
Calling 'Error::getPtr'
82
Returning from 'Error::getPtr'
119
Calling 'Error::getPtr'
120
Returning from 'Error::getPtr'
121
Calling 'Error::setChecked'
124
Returning from 'Error::setChecked'
232 return getPtr() != nullptr;
83
Calling 'Error::getPtr'
84
Returning from 'Error::getPtr'
125
Calling 'Error::getPtr'
126
Returning from 'Error::getPtr'
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
248private:
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))
101
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
102
Taking false branch
131
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
132
Taking false branch
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));
95
'?' condition is true
109
'?' condition is false
114
'?' condition is true
122
Assuming 'V' is 0
123
'?' condition is false
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.
311class ErrorSuccess : public Error {};
312
313inline ErrorSuccess Error::success() { return ErrorSuccess(); }
314
315/// Make a Error instance representing failure using the given error info
316/// type.
317template <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.
330template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
331class ErrorInfo : public ParentErrT {
332public:
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.
344class 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
353public:
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
367private:
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.
408inline 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.
418template <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
428public:
429 using storage_type = typename std::conditional<isRef, wrap, T>::type;
430 using value_type = T;
431
432private:
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
438public:
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
568private:
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.
672LLVM_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
688inline 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
709template <typename T>
710T 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
733template <typename T>
734T& 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.
746template <typename HandlerT>
747class ErrorHandlerTraits
748 : public ErrorHandlerTraits<decltype(
749 &std::remove_reference<HandlerT>::type::operator())> {};
750
751// Specialization functions of the form 'Error (const ErrT&)'.
752template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
753public:
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&)'.
766template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
767public:
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>)'.
781template <typename ErrT>
782class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
783public:
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>)'.
797template <typename ErrT>
798class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
799public:
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&)'.
814template <typename C, typename RetT, typename ErrT>
815class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
816 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
817
818// Specialization for member functions of the form 'RetT (const ErrT&) const'.
819template <typename C, typename RetT, typename ErrT>
820class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
821 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
822
823// Specialization for member functions of the form 'RetT (const ErrT&)'.
824template <typename C, typename RetT, typename ErrT>
825class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
826 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
827
828// Specialization for member functions of the form 'RetT (const ErrT&) const'.
829template <typename C, typename RetT, typename ErrT>
830class 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>)'.
835template <typename C, typename RetT, typename ErrT>
836class 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'.
841template <typename C, typename RetT, typename ErrT>
842class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
843 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
844
845inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
846 return Error(std::move(Payload));
847}
848
849template <typename HandlerT, typename... HandlerTs>
850Error 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.
865template <typename... HandlerTs>
866Error 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.
888template <typename... HandlerTs>
889void 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.
895inline 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
923template <typename T, typename RecoveryFtor, typename... HandlerTs>
924Expected<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.
943void 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.
947inline 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>.
962inline 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.
990class ErrorAsOutParameter {
991public:
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
1004private:
1005 Error *Err;
1006};
1007
1008/// Helper for Expected<T>s used as out-parameters.
1009///
1010/// See ErrorAsOutParameter.
1011template <typename T>
1012class ExpectedAsOutParameter {
1013public:
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
1025private:
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.
1034class ECError : public ErrorInfo<ECError> {
1035 friend Error errorCodeToError(std::error_code);
1036
1037public:
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
1045protected:
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).
1058std::error_code inconvertibleErrorCode();
1059
1060/// Helper for converting an std::error_code to a Error.
1061Error 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().
1067std::error_code errorToErrorCode(Error Err);
1068
1069/// Convert an ErrorOr<T> to an Expected<T>.
1070template <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>.
1077template <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).
1088class StringError : public ErrorInfo<StringError> {
1089public:
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
1099private:
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///
1108class ExitOnError {
1109public:
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
1140private:
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