File: | tools/lli/lli.cpp |
Warning: | line 420, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "RemoteJITUtils.h" | |||
17 | #include "llvm/ADT/StringExtras.h" | |||
18 | #include "llvm/ADT/Triple.h" | |||
19 | #include "llvm/Bitcode/BitcodeReader.h" | |||
20 | #include "llvm/CodeGen/CommandFlags.inc" | |||
21 | #include "llvm/CodeGen/LinkAllCodegenComponents.h" | |||
22 | #include "llvm/Config/llvm-config.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/ExecutionUtils.h" | |||
29 | #include "llvm/ExecutionEngine/Orc/LLJIT.h" | |||
30 | #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" | |||
31 | #include "llvm/ExecutionEngine/OrcMCJITReplacement.h" | |||
32 | #include "llvm/ExecutionEngine/SectionMemoryManager.h" | |||
33 | #include "llvm/IR/IRBuilder.h" | |||
34 | #include "llvm/IR/LLVMContext.h" | |||
35 | #include "llvm/IR/Module.h" | |||
36 | #include "llvm/IR/Type.h" | |||
37 | #include "llvm/IR/TypeBuilder.h" | |||
38 | #include "llvm/IR/Verifier.h" | |||
39 | #include "llvm/IRReader/IRReader.h" | |||
40 | #include "llvm/Object/Archive.h" | |||
41 | #include "llvm/Object/ObjectFile.h" | |||
42 | #include "llvm/Support/CommandLine.h" | |||
43 | #include "llvm/Support/Debug.h" | |||
44 | #include "llvm/Support/DynamicLibrary.h" | |||
45 | #include "llvm/Support/Format.h" | |||
46 | #include "llvm/Support/InitLLVM.h" | |||
47 | #include "llvm/Support/ManagedStatic.h" | |||
48 | #include "llvm/Support/MathExtras.h" | |||
49 | #include "llvm/Support/Memory.h" | |||
50 | #include "llvm/Support/MemoryBuffer.h" | |||
51 | #include "llvm/Support/Path.h" | |||
52 | #include "llvm/Support/PluginLoader.h" | |||
53 | #include "llvm/Support/Process.h" | |||
54 | #include "llvm/Support/Program.h" | |||
55 | #include "llvm/Support/SourceMgr.h" | |||
56 | #include "llvm/Support/TargetSelect.h" | |||
57 | #include "llvm/Support/WithColor.h" | |||
58 | #include "llvm/Support/raw_ostream.h" | |||
59 | #include "llvm/Transforms/Instrumentation.h" | |||
60 | #include <cerrno> | |||
61 | ||||
62 | #ifdef __CYGWIN__ | |||
63 | #include <cygwin/version.h> | |||
64 | #if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 | |||
65 | #define DO_NOTHING_ATEXIT 1 | |||
66 | #endif | |||
67 | #endif | |||
68 | ||||
69 | using namespace llvm; | |||
70 | ||||
71 | #define DEBUG_TYPE"lli" "lli" | |||
72 | ||||
73 | namespace { | |||
74 | ||||
75 | enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy }; | |||
76 | ||||
77 | cl::opt<std::string> | |||
78 | InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-")); | |||
79 | ||||
80 | cl::list<std::string> | |||
81 | InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>...")); | |||
82 | ||||
83 | cl::opt<bool> ForceInterpreter("force-interpreter", | |||
84 | cl::desc("Force interpretation: disable JIT"), | |||
85 | cl::init(false)); | |||
86 | ||||
87 | cl::opt<JITKind> UseJITKind("jit-kind", | |||
88 | cl::desc("Choose underlying JIT kind."), | |||
89 | cl::init(JITKind::MCJIT), | |||
90 | cl::values( | |||
91 | clEnumValN(JITKind::MCJIT, "mcjit",llvm::cl::OptionEnumValue { "mcjit", int(JITKind::MCJIT), "MCJIT" } | |||
92 | "MCJIT")llvm::cl::OptionEnumValue { "mcjit", int(JITKind::MCJIT), "MCJIT" }, | |||
93 | clEnumValN(JITKind::OrcMCJITReplacement,llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" } | |||
94 | "orc-mcjit",llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" } | |||
95 | "Orc-based MCJIT replacement")llvm::cl::OptionEnumValue { "orc-mcjit", int(JITKind::OrcMCJITReplacement ), "Orc-based MCJIT replacement" }, | |||
96 | clEnumValN(JITKind::OrcLazy,llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." } | |||
97 | "orc-lazy",llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." } | |||
98 | "Orc-based lazy JIT.")llvm::cl::OptionEnumValue { "orc-lazy", int(JITKind::OrcLazy) , "Orc-based lazy JIT." })); | |||
99 | ||||
100 | // The MCJIT supports building for a target address space separate from | |||
101 | // the JIT compilation process. Use a forked process and a copying | |||
102 | // memory manager with IPC to execute using this functionality. | |||
103 | cl::opt<bool> RemoteMCJIT("remote-mcjit", | |||
104 | cl::desc("Execute MCJIT'ed code in a separate process."), | |||
105 | cl::init(false)); | |||
106 | ||||
107 | // Manually specify the child process for remote execution. This overrides | |||
108 | // the simulated remote execution that allocates address space for child | |||
109 | // execution. The child process will be executed and will communicate with | |||
110 | // lli via stdin/stdout pipes. | |||
111 | cl::opt<std::string> | |||
112 | ChildExecPath("mcjit-remote-process", | |||
113 | cl::desc("Specify the filename of the process to launch " | |||
114 | "for remote MCJIT execution. If none is specified," | |||
115 | "\n\tremote execution will be simulated in-process."), | |||
116 | cl::value_desc("filename"), cl::init("")); | |||
117 | ||||
118 | // Determine optimization level. | |||
119 | cl::opt<char> | |||
120 | OptLevel("O", | |||
121 | cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " | |||
122 | "(default = '-O2')"), | |||
123 | cl::Prefix, | |||
124 | cl::ZeroOrMore, | |||
125 | cl::init(' ')); | |||
126 | ||||
127 | cl::opt<std::string> | |||
128 | TargetTriple("mtriple", cl::desc("Override target triple for module")); | |||
129 | ||||
130 | cl::opt<std::string> | |||
131 | EntryFunc("entry-function", | |||
132 | cl::desc("Specify the entry function (default = 'main') " | |||
133 | "of the executable"), | |||
134 | cl::value_desc("function"), | |||
135 | cl::init("main")); | |||
136 | ||||
137 | cl::list<std::string> | |||
138 | ExtraModules("extra-module", | |||
139 | cl::desc("Extra modules to be loaded"), | |||
140 | cl::value_desc("input bitcode")); | |||
141 | ||||
142 | cl::list<std::string> | |||
143 | ExtraObjects("extra-object", | |||
144 | cl::desc("Extra object files to be loaded"), | |||
145 | cl::value_desc("input object")); | |||
146 | ||||
147 | cl::list<std::string> | |||
148 | ExtraArchives("extra-archive", | |||
149 | cl::desc("Extra archive files to be loaded"), | |||
150 | cl::value_desc("input archive")); | |||
151 | ||||
152 | cl::opt<bool> | |||
153 | EnableCacheManager("enable-cache-manager", | |||
154 | cl::desc("Use cache manager to save/load mdoules"), | |||
155 | cl::init(false)); | |||
156 | ||||
157 | cl::opt<std::string> | |||
158 | ObjectCacheDir("object-cache-dir", | |||
159 | cl::desc("Directory to store cached object files " | |||
160 | "(must be user writable)"), | |||
161 | cl::init("")); | |||
162 | ||||
163 | cl::opt<std::string> | |||
164 | FakeArgv0("fake-argv0", | |||
165 | cl::desc("Override the 'argv[0]' value passed into the executing" | |||
166 | " program"), cl::value_desc("executable")); | |||
167 | ||||
168 | cl::opt<bool> | |||
169 | DisableCoreFiles("disable-core-files", cl::Hidden, | |||
170 | cl::desc("Disable emission of core files if possible")); | |||
171 | ||||
172 | cl::opt<bool> | |||
173 | NoLazyCompilation("disable-lazy-compilation", | |||
174 | cl::desc("Disable JIT lazy compilation"), | |||
175 | cl::init(false)); | |||
176 | ||||
177 | cl::opt<bool> | |||
178 | GenerateSoftFloatCalls("soft-float", | |||
179 | cl::desc("Generate software floating point library calls"), | |||
180 | cl::init(false)); | |||
181 | ||||
182 | enum class DumpKind { | |||
183 | NoDump, | |||
184 | DumpFuncsToStdOut, | |||
185 | DumpModsToStdOut, | |||
186 | DumpModsToDisk | |||
187 | }; | |||
188 | ||||
189 | cl::opt<DumpKind> OrcDumpKind( | |||
190 | "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."), | |||
191 | cl::init(DumpKind::NoDump), | |||
192 | cl::values(clEnumValN(DumpKind::NoDump, "no-dump",llvm::cl::OptionEnumValue { "no-dump", int(DumpKind::NoDump), "Don't dump anything." } | |||
193 | "Don't dump anything.")llvm::cl::OptionEnumValue { "no-dump", int(DumpKind::NoDump), "Don't dump anything." }, | |||
194 | clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",llvm::cl::OptionEnumValue { "funcs-to-stdout", int(DumpKind:: DumpFuncsToStdOut), "Dump function names to stdout." } | |||
195 | "Dump function names to stdout.")llvm::cl::OptionEnumValue { "funcs-to-stdout", int(DumpKind:: DumpFuncsToStdOut), "Dump function names to stdout." }, | |||
196 | clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",llvm::cl::OptionEnumValue { "mods-to-stdout", int(DumpKind::DumpModsToStdOut ), "Dump modules to stdout." } | |||
197 | "Dump modules to stdout.")llvm::cl::OptionEnumValue { "mods-to-stdout", int(DumpKind::DumpModsToStdOut ), "Dump modules to stdout." }, | |||
198 | clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",llvm::cl::OptionEnumValue { "mods-to-disk", int(DumpKind::DumpModsToDisk ), "Dump modules to the current " "working directory. (WARNING: " "will overwrite existing files)." } | |||
199 | "Dump modules to the current "llvm::cl::OptionEnumValue { "mods-to-disk", int(DumpKind::DumpModsToDisk ), "Dump modules to the current " "working directory. (WARNING: " "will overwrite existing files)." } | |||
200 | "working directory. (WARNING: "llvm::cl::OptionEnumValue { "mods-to-disk", int(DumpKind::DumpModsToDisk ), "Dump modules to the current " "working directory. (WARNING: " "will overwrite existing files)." } | |||
201 | "will overwrite existing files).")llvm::cl::OptionEnumValue { "mods-to-disk", int(DumpKind::DumpModsToDisk ), "Dump modules to the current " "working directory. (WARNING: " "will overwrite existing files)." }), | |||
202 | cl::Hidden); | |||
203 | ||||
204 | ExitOnError ExitOnErr; | |||
205 | } | |||
206 | ||||
207 | //===----------------------------------------------------------------------===// | |||
208 | // Object cache | |||
209 | // | |||
210 | // This object cache implementation writes cached objects to disk to the | |||
211 | // directory specified by CacheDir, using a filename provided in the module | |||
212 | // descriptor. The cache tries to load a saved object using that path if the | |||
213 | // file exists. CacheDir defaults to "", in which case objects are cached | |||
214 | // alongside their originating bitcodes. | |||
215 | // | |||
216 | class LLIObjectCache : public ObjectCache { | |||
217 | public: | |||
218 | LLIObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) { | |||
219 | // Add trailing '/' to cache dir if necessary. | |||
220 | if (!this->CacheDir.empty() && | |||
221 | this->CacheDir[this->CacheDir.size() - 1] != '/') | |||
222 | this->CacheDir += '/'; | |||
223 | } | |||
224 | ~LLIObjectCache() override {} | |||
225 | ||||
226 | void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { | |||
227 | const std::string &ModuleID = M->getModuleIdentifier(); | |||
228 | std::string CacheName; | |||
229 | if (!getCacheFilename(ModuleID, CacheName)) | |||
230 | return; | |||
231 | if (!CacheDir.empty()) { // Create user-defined cache dir. | |||
232 | SmallString<128> dir(sys::path::parent_path(CacheName)); | |||
233 | sys::fs::create_directories(Twine(dir)); | |||
234 | } | |||
235 | std::error_code EC; | |||
236 | raw_fd_ostream outfile(CacheName, EC, sys::fs::F_None); | |||
237 | outfile.write(Obj.getBufferStart(), Obj.getBufferSize()); | |||
238 | outfile.close(); | |||
239 | } | |||
240 | ||||
241 | std::unique_ptr<MemoryBuffer> getObject(const Module* M) override { | |||
242 | const std::string &ModuleID = M->getModuleIdentifier(); | |||
243 | std::string CacheName; | |||
244 | if (!getCacheFilename(ModuleID, CacheName)) | |||
245 | return nullptr; | |||
246 | // Load the object from the cache filename | |||
247 | ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer = | |||
248 | MemoryBuffer::getFile(CacheName, -1, false); | |||
249 | // If the file isn't there, that's OK. | |||
250 | if (!IRObjectBuffer) | |||
251 | return nullptr; | |||
252 | // MCJIT will want to write into this buffer, and we don't want that | |||
253 | // because the file has probably just been mmapped. Instead we make | |||
254 | // a copy. The filed-based buffer will be released when it goes | |||
255 | // out of scope. | |||
256 | return MemoryBuffer::getMemBufferCopy(IRObjectBuffer.get()->getBuffer()); | |||
257 | } | |||
258 | ||||
259 | private: | |||
260 | std::string CacheDir; | |||
261 | ||||
262 | bool getCacheFilename(const std::string &ModID, std::string &CacheName) { | |||
263 | std::string Prefix("file:"); | |||
264 | size_t PrefixLength = Prefix.length(); | |||
265 | if (ModID.substr(0, PrefixLength) != Prefix) | |||
266 | return false; | |||
267 | std::string CacheSubdir = ModID.substr(PrefixLength); | |||
268 | #if defined(_WIN32) | |||
269 | // Transform "X:\foo" => "/X\foo" for convenience. | |||
270 | if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') { | |||
271 | CacheSubdir[1] = CacheSubdir[0]; | |||
272 | CacheSubdir[0] = '/'; | |||
273 | } | |||
274 | #endif | |||
275 | CacheName = CacheDir + CacheSubdir; | |||
276 | size_t pos = CacheName.rfind('.'); | |||
277 | CacheName.replace(pos, CacheName.length() - pos, ".o"); | |||
278 | return true; | |||
279 | } | |||
280 | }; | |||
281 | ||||
282 | // On Mingw and Cygwin, an external symbol named '__main' is called from the | |||
283 | // generated 'main' function to allow static initialization. To avoid linking | |||
284 | // problems with remote targets (because lli's remote target support does not | |||
285 | // currently handle external linking) we add a secondary module which defines | |||
286 | // an empty '__main' function. | |||
287 | static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context, | |||
288 | StringRef TargetTripleStr) { | |||
289 | IRBuilder<> Builder(Context); | |||
290 | Triple TargetTriple(TargetTripleStr); | |||
291 | ||||
292 | // Create a new module. | |||
293 | std::unique_ptr<Module> M = make_unique<Module>("CygMingHelper", Context); | |||
294 | M->setTargetTriple(TargetTripleStr); | |||
295 | ||||
296 | // Create an empty function named "__main". | |||
297 | Function *Result; | |||
298 | if (TargetTriple.isArch64Bit()) { | |||
299 | Result = Function::Create( | |||
300 | TypeBuilder<int64_t(void), false>::get(Context), | |||
301 | GlobalValue::ExternalLinkage, "__main", M.get()); | |||
302 | } else { | |||
303 | Result = Function::Create( | |||
304 | TypeBuilder<int32_t(void), false>::get(Context), | |||
305 | GlobalValue::ExternalLinkage, "__main", M.get()); | |||
306 | } | |||
307 | BasicBlock *BB = BasicBlock::Create(Context, "__main", Result); | |||
308 | Builder.SetInsertPoint(BB); | |||
309 | Value *ReturnVal; | |||
310 | if (TargetTriple.isArch64Bit()) | |||
311 | ReturnVal = ConstantInt::get(Context, APInt(64, 0)); | |||
312 | else | |||
313 | ReturnVal = ConstantInt::get(Context, APInt(32, 0)); | |||
314 | Builder.CreateRet(ReturnVal); | |||
315 | ||||
316 | // Add this new module to the ExecutionEngine. | |||
317 | EE.addModule(std::move(M)); | |||
318 | } | |||
319 | ||||
320 | CodeGenOpt::Level getOptLevel() { | |||
321 | switch (OptLevel) { | |||
322 | default: | |||
323 | WithColor::error(errs(), "lli") << "invalid optimization level.\n"; | |||
324 | exit(1); | |||
325 | case '0': return CodeGenOpt::None; | |||
326 | case '1': return CodeGenOpt::Less; | |||
327 | case ' ': | |||
328 | case '2': return CodeGenOpt::Default; | |||
329 | case '3': return CodeGenOpt::Aggressive; | |||
330 | } | |||
331 | llvm_unreachable("Unrecognized opt level.")::llvm::llvm_unreachable_internal("Unrecognized opt level.", "/build/llvm-toolchain-snapshot-7~svn338205/tools/lli/lli.cpp" , 331); | |||
332 | } | |||
333 | ||||
334 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
335 | static void reportError(SMDiagnostic Err, const char *ProgName) { | |||
336 | Err.print(ProgName, errs()); | |||
337 | exit(1); | |||
338 | } | |||
339 | ||||
340 | int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms, | |||
341 | const std::vector<std::string> &Args); | |||
342 | ||||
343 | //===----------------------------------------------------------------------===// | |||
344 | // main Driver function | |||
345 | // | |||
346 | int main(int argc, char **argv, char * const *envp) { | |||
347 | InitLLVM X(argc, argv); | |||
348 | ||||
349 | if (argc > 1) | |||
| ||||
350 | ExitOnErr.setBanner(std::string(argv[0]) + ": "); | |||
351 | ||||
352 | // If we have a native target, initialize it to ensure it is linked in and | |||
353 | // usable by the JIT. | |||
354 | InitializeNativeTarget(); | |||
355 | InitializeNativeTargetAsmPrinter(); | |||
356 | InitializeNativeTargetAsmParser(); | |||
357 | ||||
358 | cl::ParseCommandLineOptions(argc, argv, | |||
359 | "llvm interpreter & dynamic compiler\n"); | |||
360 | ||||
361 | // If the user doesn't want core files, disable them. | |||
362 | if (DisableCoreFiles) | |||
363 | sys::Process::PreventCoreFiles(); | |||
364 | ||||
365 | LLVMContext Context; | |||
366 | ||||
367 | // Load the bitcode... | |||
368 | SMDiagnostic Err; | |||
369 | std::unique_ptr<Module> Owner = parseIRFile(InputFile, Err, Context); | |||
370 | Module *Mod = Owner.get(); | |||
371 | if (!Mod) | |||
372 | reportError(Err, argv[0]); | |||
373 | ||||
374 | if (UseJITKind == JITKind::OrcLazy) { | |||
375 | std::vector<std::unique_ptr<Module>> Ms; | |||
376 | Ms.push_back(std::move(Owner)); | |||
377 | for (auto &ExtraMod : ExtraModules) { | |||
378 | Ms.push_back(parseIRFile(ExtraMod, Err, Context)); | |||
379 | if (!Ms.back()) | |||
380 | reportError(Err, argv[0]); | |||
381 | } | |||
382 | std::vector<std::string> Args; | |||
383 | Args.push_back(InputFile); | |||
384 | for (auto &Arg : InputArgv) | |||
385 | Args.push_back(Arg); | |||
386 | return runOrcLazyJIT(Context, std::move(Ms), Args); | |||
387 | } | |||
388 | ||||
389 | if (EnableCacheManager) { | |||
390 | std::string CacheName("file:"); | |||
391 | CacheName.append(InputFile); | |||
392 | Mod->setModuleIdentifier(CacheName); | |||
393 | } | |||
394 | ||||
395 | // If not jitting lazily, load the whole bitcode file eagerly too. | |||
396 | if (NoLazyCompilation) { | |||
397 | // Use *argv instead of argv[0] to work around a wrong GCC warning. | |||
398 | ExitOnError ExitOnErr(std::string(*argv) + | |||
399 | ": bitcode didn't read correctly: "); | |||
400 | ExitOnErr(Mod->materializeAll()); | |||
401 | } | |||
402 | ||||
403 | std::string ErrorMsg; | |||
404 | EngineBuilder builder(std::move(Owner)); | |||
405 | builder.setMArch(MArch); | |||
406 | builder.setMCPU(getCPUStr()); | |||
407 | builder.setMAttrs(getFeatureList()); | |||
408 | if (RelocModel.getNumOccurrences()) | |||
409 | builder.setRelocationModel(RelocModel); | |||
410 | if (CMModel.getNumOccurrences()) | |||
411 | builder.setCodeModel(CMModel); | |||
412 | builder.setErrorStr(&ErrorMsg); | |||
413 | builder.setEngineKind(ForceInterpreter | |||
414 | ? EngineKind::Interpreter | |||
415 | : EngineKind::JIT); | |||
416 | builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement); | |||
417 | ||||
418 | // If we are supposed to override the target triple, do so now. | |||
419 | if (!TargetTriple.empty()) | |||
420 | Mod->setTargetTriple(Triple::normalize(TargetTriple)); | |||
| ||||
421 | ||||
422 | // Enable MCJIT if desired. | |||
423 | RTDyldMemoryManager *RTDyldMM = nullptr; | |||
424 | if (!ForceInterpreter) { | |||
425 | if (RemoteMCJIT) | |||
426 | RTDyldMM = new ForwardingMemoryManager(); | |||
427 | else | |||
428 | RTDyldMM = new SectionMemoryManager(); | |||
429 | ||||
430 | // Deliberately construct a temp std::unique_ptr to pass in. Do not null out | |||
431 | // RTDyldMM: We still use it below, even though we don't own it. | |||
432 | builder.setMCJITMemoryManager( | |||
433 | std::unique_ptr<RTDyldMemoryManager>(RTDyldMM)); | |||
434 | } else if (RemoteMCJIT) { | |||
435 | WithColor::error(errs(), argv[0]) | |||
436 | << "remote process execution does not work with the interpreter.\n"; | |||
437 | exit(1); | |||
438 | } | |||
439 | ||||
440 | builder.setOptLevel(getOptLevel()); | |||
441 | ||||
442 | TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); | |||
443 | if (FloatABIForCalls != FloatABI::Default) | |||
444 | Options.FloatABIType = FloatABIForCalls; | |||
445 | ||||
446 | builder.setTargetOptions(Options); | |||
447 | ||||
448 | std::unique_ptr<ExecutionEngine> EE(builder.create()); | |||
449 | if (!EE) { | |||
450 | if (!ErrorMsg.empty()) | |||
451 | WithColor::error(errs(), argv[0]) | |||
452 | << "error creating EE: " << ErrorMsg << "\n"; | |||
453 | else | |||
454 | WithColor::error(errs(), argv[0]) << "unknown error creating EE!\n"; | |||
455 | exit(1); | |||
456 | } | |||
457 | ||||
458 | std::unique_ptr<LLIObjectCache> CacheManager; | |||
459 | if (EnableCacheManager) { | |||
460 | CacheManager.reset(new LLIObjectCache(ObjectCacheDir)); | |||
461 | EE->setObjectCache(CacheManager.get()); | |||
462 | } | |||
463 | ||||
464 | // Load any additional modules specified on the command line. | |||
465 | for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) { | |||
466 | std::unique_ptr<Module> XMod = parseIRFile(ExtraModules[i], Err, Context); | |||
467 | if (!XMod) | |||
468 | reportError(Err, argv[0]); | |||
469 | if (EnableCacheManager) { | |||
470 | std::string CacheName("file:"); | |||
471 | CacheName.append(ExtraModules[i]); | |||
472 | XMod->setModuleIdentifier(CacheName); | |||
473 | } | |||
474 | EE->addModule(std::move(XMod)); | |||
475 | } | |||
476 | ||||
477 | for (unsigned i = 0, e = ExtraObjects.size(); i != e; ++i) { | |||
478 | Expected<object::OwningBinary<object::ObjectFile>> Obj = | |||
479 | object::ObjectFile::createObjectFile(ExtraObjects[i]); | |||
480 | if (!Obj) { | |||
481 | // TODO: Actually report errors helpfully. | |||
482 | consumeError(Obj.takeError()); | |||
483 | reportError(Err, argv[0]); | |||
484 | } | |||
485 | object::OwningBinary<object::ObjectFile> &O = Obj.get(); | |||
486 | EE->addObjectFile(std::move(O)); | |||
487 | } | |||
488 | ||||
489 | for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) { | |||
490 | ErrorOr<std::unique_ptr<MemoryBuffer>> ArBufOrErr = | |||
491 | MemoryBuffer::getFileOrSTDIN(ExtraArchives[i]); | |||
492 | if (!ArBufOrErr) | |||
493 | reportError(Err, argv[0]); | |||
494 | std::unique_ptr<MemoryBuffer> &ArBuf = ArBufOrErr.get(); | |||
495 | ||||
496 | Expected<std::unique_ptr<object::Archive>> ArOrErr = | |||
497 | object::Archive::create(ArBuf->getMemBufferRef()); | |||
498 | if (!ArOrErr) { | |||
499 | std::string Buf; | |||
500 | raw_string_ostream OS(Buf); | |||
501 | logAllUnhandledErrors(ArOrErr.takeError(), OS, ""); | |||
502 | OS.flush(); | |||
503 | errs() << Buf; | |||
504 | exit(1); | |||
505 | } | |||
506 | std::unique_ptr<object::Archive> &Ar = ArOrErr.get(); | |||
507 | ||||
508 | object::OwningBinary<object::Archive> OB(std::move(Ar), std::move(ArBuf)); | |||
509 | ||||
510 | EE->addArchive(std::move(OB)); | |||
511 | } | |||
512 | ||||
513 | // If the target is Cygwin/MingW and we are generating remote code, we | |||
514 | // need an extra module to help out with linking. | |||
515 | if (RemoteMCJIT && Triple(Mod->getTargetTriple()).isOSCygMing()) { | |||
516 | addCygMingExtraModule(*EE, Context, Mod->getTargetTriple()); | |||
517 | } | |||
518 | ||||
519 | // The following functions have no effect if their respective profiling | |||
520 | // support wasn't enabled in the build configuration. | |||
521 | EE->RegisterJITEventListener( | |||
522 | JITEventListener::createOProfileJITEventListener()); | |||
523 | EE->RegisterJITEventListener( | |||
524 | JITEventListener::createIntelJITEventListener()); | |||
525 | if (!RemoteMCJIT) | |||
526 | EE->RegisterJITEventListener( | |||
527 | JITEventListener::createPerfJITEventListener()); | |||
528 | ||||
529 | if (!NoLazyCompilation && RemoteMCJIT) { | |||
530 | WithColor::warning(errs(), argv[0]) | |||
531 | << "remote mcjit does not support lazy compilation\n"; | |||
532 | NoLazyCompilation = true; | |||
533 | } | |||
534 | EE->DisableLazyCompilation(NoLazyCompilation); | |||
535 | ||||
536 | // If the user specifically requested an argv[0] to pass into the program, | |||
537 | // do it now. | |||
538 | if (!FakeArgv0.empty()) { | |||
539 | InputFile = static_cast<std::string>(FakeArgv0); | |||
540 | } else { | |||
541 | // Otherwise, if there is a .bc suffix on the executable strip it off, it | |||
542 | // might confuse the program. | |||
543 | if (StringRef(InputFile).endswith(".bc")) | |||
544 | InputFile.erase(InputFile.length() - 3); | |||
545 | } | |||
546 | ||||
547 | // Add the module's name to the start of the vector of arguments to main(). | |||
548 | InputArgv.insert(InputArgv.begin(), InputFile); | |||
549 | ||||
550 | // Call the main function from M as if its signature were: | |||
551 | // int main (int argc, char **argv, const char **envp) | |||
552 | // using the contents of Args to determine argc & argv, and the contents of | |||
553 | // EnvVars to determine envp. | |||
554 | // | |||
555 | Function *EntryFn = Mod->getFunction(EntryFunc); | |||
556 | if (!EntryFn) { | |||
557 | WithColor::error(errs(), argv[0]) | |||
558 | << '\'' << EntryFunc << "\' function not found in module.\n"; | |||
559 | return -1; | |||
560 | } | |||
561 | ||||
562 | // Reset errno to zero on entry to main. | |||
563 | errno(*__errno_location ()) = 0; | |||
564 | ||||
565 | int Result = -1; | |||
566 | ||||
567 | // Sanity check use of remote-jit: LLI currently only supports use of the | |||
568 | // remote JIT on Unix platforms. | |||
569 | if (RemoteMCJIT) { | |||
570 | #ifndef LLVM_ON_UNIX1 | |||
571 | WithColor::warning(errs(), argv[0]) | |||
572 | << "host does not support external remote targets.\n"; | |||
573 | WithColor::note() << "defaulting to local execution\n"; | |||
574 | return -1; | |||
575 | #else | |||
576 | if (ChildExecPath.empty()) { | |||
577 | WithColor::error(errs(), argv[0]) | |||
578 | << "-remote-mcjit requires -mcjit-remote-process.\n"; | |||
579 | exit(1); | |||
580 | } else if (!sys::fs::can_execute(ChildExecPath)) { | |||
581 | WithColor::error(errs(), argv[0]) | |||
582 | << "unable to find usable child executable: '" << ChildExecPath | |||
583 | << "'\n"; | |||
584 | return -1; | |||
585 | } | |||
586 | #endif | |||
587 | } | |||
588 | ||||
589 | if (!RemoteMCJIT) { | |||
590 | // If the program doesn't explicitly call exit, we will need the Exit | |||
591 | // function later on to make an explicit call, so get the function now. | |||
592 | Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context), | |||
593 | Type::getInt32Ty(Context)); | |||
594 | ||||
595 | // Run static constructors. | |||
596 | if (!ForceInterpreter) { | |||
597 | // Give MCJIT a chance to apply relocations and set page permissions. | |||
598 | EE->finalizeObject(); | |||
599 | } | |||
600 | EE->runStaticConstructorsDestructors(false); | |||
601 | ||||
602 | // Trigger compilation separately so code regions that need to be | |||
603 | // invalidated will be known. | |||
604 | (void)EE->getPointerToFunction(EntryFn); | |||
605 | // Clear instruction cache before code will be executed. | |||
606 | if (RTDyldMM) | |||
607 | static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache(); | |||
608 | ||||
609 | // Run main. | |||
610 | Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); | |||
611 | ||||
612 | // Run static destructors. | |||
613 | EE->runStaticConstructorsDestructors(true); | |||
614 | ||||
615 | // If the program didn't call exit explicitly, we should call it now. | |||
616 | // This ensures that any atexit handlers get called correctly. | |||
617 | if (Function *ExitF = dyn_cast<Function>(Exit)) { | |||
618 | std::vector<GenericValue> Args; | |||
619 | GenericValue ResultGV; | |||
620 | ResultGV.IntVal = APInt(32, Result); | |||
621 | Args.push_back(ResultGV); | |||
622 | EE->runFunction(ExitF, Args); | |||
623 | WithColor::error(errs(), argv[0]) << "exit(" << Result << ") returned!\n"; | |||
624 | abort(); | |||
625 | } else { | |||
626 | WithColor::error(errs(), argv[0]) | |||
627 | << "exit defined with wrong prototype!\n"; | |||
628 | abort(); | |||
629 | } | |||
630 | } else { | |||
631 | // else == "if (RemoteMCJIT)" | |||
632 | ||||
633 | // Remote target MCJIT doesn't (yet) support static constructors. No reason | |||
634 | // it couldn't. This is a limitation of the LLI implementation, not the | |||
635 | // MCJIT itself. FIXME. | |||
636 | ||||
637 | // Lanch the remote process and get a channel to it. | |||
638 | std::unique_ptr<FDRawChannel> C = launchRemote(); | |||
639 | if (!C) { | |||
640 | WithColor::error(errs(), argv[0]) << "failed to launch remote JIT.\n"; | |||
641 | exit(1); | |||
642 | } | |||
643 | ||||
644 | // Create a remote target client running over the channel. | |||
645 | llvm::orc::ExecutionSession ES; | |||
646 | ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); }); | |||
647 | typedef orc::remote::OrcRemoteTargetClient MyRemote; | |||
648 | auto R = ExitOnErr(MyRemote::Create(*C, ES)); | |||
649 | ||||
650 | // Create a remote memory manager. | |||
651 | auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager()); | |||
652 | ||||
653 | // Forward MCJIT's memory manager calls to the remote memory manager. | |||
654 | static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr( | |||
655 | std::move(RemoteMM)); | |||
656 | ||||
657 | // Forward MCJIT's symbol resolution calls to the remote. | |||
658 | static_cast<ForwardingMemoryManager *>(RTDyldMM)->setResolver( | |||
659 | orc::createLambdaResolver( | |||
660 | [](const std::string &Name) { return nullptr; }, | |||
661 | [&](const std::string &Name) { | |||
662 | if (auto Addr = ExitOnErr(R->getSymbolAddress(Name))) | |||
663 | return JITSymbol(Addr, JITSymbolFlags::Exported); | |||
664 | return JITSymbol(nullptr); | |||
665 | })); | |||
666 | ||||
667 | // Grab the target address of the JIT'd main function on the remote and call | |||
668 | // it. | |||
669 | // FIXME: argv and envp handling. | |||
670 | JITTargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str()); | |||
671 | EE->finalizeObject(); | |||
672 | LLVM_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) | |||
673 | << format("%llx", Entry) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("lli")) { dbgs() << "Executing '" << EntryFn-> getName() << "' at 0x" << format("%llx", Entry) << "\n"; } } while (false); | |||
674 | Result = ExitOnErr(R->callIntVoid(Entry)); | |||
675 | ||||
676 | // Like static constructors, the remote target MCJIT support doesn't handle | |||
677 | // this yet. It could. FIXME. | |||
678 | ||||
679 | // Delete the EE - we need to tear it down *before* we terminate the session | |||
680 | // with the remote, otherwise it'll crash when it tries to release resources | |||
681 | // on a remote that has already been disconnected. | |||
682 | EE.reset(); | |||
683 | ||||
684 | // Signal the remote target that we're done JITing. | |||
685 | ExitOnErr(R->terminateSession()); | |||
686 | } | |||
687 | ||||
688 | return Result; | |||
689 | } | |||
690 | ||||
691 | static orc::IRTransformLayer2::TransformFunction createDebugDumper() { | |||
692 | switch (OrcDumpKind) { | |||
693 | case DumpKind::NoDump: | |||
694 | return [](std::unique_ptr<Module> M) { return M; }; | |||
695 | ||||
696 | case DumpKind::DumpFuncsToStdOut: | |||
697 | return [](std::unique_ptr<Module> M) { | |||
698 | printf("[ "); | |||
699 | ||||
700 | for (const auto &F : *M) { | |||
701 | if (F.isDeclaration()) | |||
702 | continue; | |||
703 | ||||
704 | if (F.hasName()) { | |||
705 | std::string Name(F.getName()); | |||
706 | printf("%s ", Name.c_str()); | |||
707 | } else | |||
708 | printf("<anon> "); | |||
709 | } | |||
710 | ||||
711 | printf("]\n"); | |||
712 | return M; | |||
713 | }; | |||
714 | ||||
715 | case DumpKind::DumpModsToStdOut: | |||
716 | return [](std::unique_ptr<Module> M) { | |||
717 | outs() << "----- Module Start -----\n" | |||
718 | << *M << "----- Module End -----\n"; | |||
719 | ||||
720 | return M; | |||
721 | }; | |||
722 | ||||
723 | case DumpKind::DumpModsToDisk: | |||
724 | return [](std::unique_ptr<Module> M) { | |||
725 | std::error_code EC; | |||
726 | raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, sys::fs::F_Text); | |||
727 | if (EC) { | |||
728 | errs() << "Couldn't open " << M->getModuleIdentifier() | |||
729 | << " for dumping.\nError:" << EC.message() << "\n"; | |||
730 | exit(1); | |||
731 | } | |||
732 | Out << *M; | |||
733 | return M; | |||
734 | }; | |||
735 | } | |||
736 | llvm_unreachable("Unknown DumpKind")::llvm::llvm_unreachable_internal("Unknown DumpKind", "/build/llvm-toolchain-snapshot-7~svn338205/tools/lli/lli.cpp" , 736); | |||
737 | } | |||
738 | ||||
739 | int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms, | |||
740 | const std::vector<std::string> &Args) { | |||
741 | // Bail out early if no modules loaded. | |||
742 | if (Ms.empty()) | |||
743 | return 0; | |||
744 | ||||
745 | // Add lli's symbols into the JIT's search space. | |||
746 | std::string ErrMsg; | |||
747 | sys::DynamicLibrary LibLLI = | |||
748 | sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg); | |||
749 | if (!LibLLI.isValid()) { | |||
750 | errs() << "Error loading lli symbols: " << ErrMsg << ".\n"; | |||
751 | return 1; | |||
752 | } | |||
753 | ||||
754 | const auto &TT = Ms.front()->getTargetTriple(); | |||
755 | orc::JITTargetMachineBuilder TMD = | |||
756 | TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost()) | |||
757 | : orc::JITTargetMachineBuilder(Triple(TT)); | |||
758 | ||||
759 | TMD.setArch(MArch) | |||
760 | .setCPU(getCPUStr()) | |||
761 | .addFeatures(getFeatureList()) | |||
762 | .setRelocationModel(RelocModel.getNumOccurrences() | |||
763 | ? Optional<Reloc::Model>(RelocModel) | |||
764 | : None) | |||
765 | .setCodeModel(CMModel.getNumOccurrences() | |||
766 | ? Optional<CodeModel::Model>(CMModel) | |||
767 | : None); | |||
768 | auto TM = ExitOnErr(TMD.createTargetMachine()); | |||
769 | auto DL = TM->createDataLayout(); | |||
770 | auto ES = llvm::make_unique<orc::ExecutionSession>(); | |||
771 | auto J = | |||
772 | ExitOnErr(orc::LLLazyJIT::Create(std::move(ES), std::move(TM), DL, Ctx)); | |||
773 | ||||
774 | auto Dump = createDebugDumper(); | |||
775 | ||||
776 | J->setLazyCompileTransform( | |||
777 | [&](std::unique_ptr<Module> M) { | |||
778 | if (verifyModule(*M, &dbgs())) { | |||
779 | dbgs() << "Bad module: " << *M << "\n"; | |||
780 | exit(1); | |||
781 | } | |||
782 | return Dump(std::move(M)); | |||
783 | }); | |||
784 | J->getMainVSO().setFallbackDefinitionGenerator( | |||
785 | orc::DynamicLibraryFallbackGenerator( | |||
786 | std::move(LibLLI), DL, [](orc::SymbolStringPtr) { return true; })); | |||
787 | ||||
788 | orc::MangleAndInterner Mangle(J->getExecutionSession(), DL); | |||
789 | orc::LocalCXXRuntimeOverrides2 CXXRuntimeOverrides; | |||
790 | ExitOnErr(CXXRuntimeOverrides.enable(J->getMainVSO(), Mangle)); | |||
791 | ||||
792 | for (auto &M : Ms) { | |||
793 | orc::makeAllSymbolsExternallyAccessible(*M); | |||
794 | ExitOnErr(J->addLazyIRModule(std::move(M))); | |||
795 | } | |||
796 | ||||
797 | ExitOnErr(J->runConstructors()); | |||
798 | ||||
799 | auto MainSym = ExitOnErr(J->lookup("main")); | |||
800 | typedef int (*MainFnPtr)(int, const char *[]); | |||
801 | std::vector<const char *> ArgV; | |||
802 | for (auto &Arg : Args) | |||
803 | ArgV.push_back(Arg.c_str()); | |||
804 | auto Main = | |||
805 | reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress())); | |||
806 | auto Result = Main(ArgV.size(), (const char **)ArgV.data()); | |||
807 | ||||
808 | ExitOnErr(J->runDestructors()); | |||
809 | ||||
810 | CXXRuntimeOverrides.runDestructors(); | |||
811 | ||||
812 | return Result; | |||
813 | } | |||
814 | ||||
815 | std::unique_ptr<FDRawChannel> launchRemote() { | |||
816 | #ifndef LLVM_ON_UNIX1 | |||
817 | llvm_unreachable("launchRemote not supported on non-Unix platforms")::llvm::llvm_unreachable_internal("launchRemote not supported on non-Unix platforms" , "/build/llvm-toolchain-snapshot-7~svn338205/tools/lli/lli.cpp" , 817); | |||
818 | #else | |||
819 | int PipeFD[2][2]; | |||
820 | pid_t ChildPID; | |||
821 | ||||
822 | // Create two pipes. | |||
823 | if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) | |||
824 | perror("Error creating pipe: "); | |||
825 | ||||
826 | ChildPID = fork(); | |||
827 | ||||
828 | if (ChildPID == 0) { | |||
829 | // In the child... | |||
830 | ||||
831 | // Close the parent ends of the pipes | |||
832 | close(PipeFD[0][1]); | |||
833 | close(PipeFD[1][0]); | |||
834 | ||||
835 | ||||
836 | // Execute the child process. | |||
837 | std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut; | |||
838 | { | |||
839 | ChildPath.reset(new char[ChildExecPath.size() + 1]); | |||
840 | std::copy(ChildExecPath.begin(), ChildExecPath.end(), &ChildPath[0]); | |||
841 | ChildPath[ChildExecPath.size()] = '\0'; | |||
842 | std::string ChildInStr = utostr(PipeFD[0][0]); | |||
843 | ChildIn.reset(new char[ChildInStr.size() + 1]); | |||
844 | std::copy(ChildInStr.begin(), ChildInStr.end(), &ChildIn[0]); | |||
845 | ChildIn[ChildInStr.size()] = '\0'; | |||
846 | std::string ChildOutStr = utostr(PipeFD[1][1]); | |||
847 | ChildOut.reset(new char[ChildOutStr.size() + 1]); | |||
848 | std::copy(ChildOutStr.begin(), ChildOutStr.end(), &ChildOut[0]); | |||
849 | ChildOut[ChildOutStr.size()] = '\0'; | |||
850 | } | |||
851 | ||||
852 | char * const args[] = { &ChildPath[0], &ChildIn[0], &ChildOut[0], nullptr }; | |||
853 | int rc = execv(ChildExecPath.c_str(), args); | |||
854 | if (rc != 0) | |||
855 | perror("Error executing child process: "); | |||
856 | llvm_unreachable("Error executing child process")::llvm::llvm_unreachable_internal("Error executing child process" , "/build/llvm-toolchain-snapshot-7~svn338205/tools/lli/lli.cpp" , 856); | |||
857 | } | |||
858 | // else we're the parent... | |||
859 | ||||
860 | // Close the child ends of the pipes | |||
861 | close(PipeFD[0][0]); | |||
862 | close(PipeFD[1][1]); | |||
863 | ||||
864 | // Return an RPC channel connected to our end of the pipes. | |||
865 | return llvm::make_unique<FDRawChannel>(PipeFD[1][0], PipeFD[0][1]); | |||
866 | #endif | |||
867 | } |
1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2018 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/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H1 |
31 | #define _UNIQUE_PTR_H1 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | |
41 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
42 | { |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
44 | |
45 | /** |
46 | * @addtogroup pointer_abstractions |
47 | * @{ |
48 | */ |
49 | |
50 | #if _GLIBCXX_USE_DEPRECATED1 |
51 | #pragma GCC diagnostic push |
52 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
53 | template<typename> class auto_ptr; |
54 | #pragma GCC diagnostic pop |
55 | #endif |
56 | |
57 | /// Primary template of default_delete, used by unique_ptr |
58 | template<typename _Tp> |
59 | struct default_delete |
60 | { |
61 | /// Default constructor |
62 | constexpr default_delete() noexcept = default; |
63 | |
64 | /** @brief Converting constructor. |
65 | * |
66 | * Allows conversion from a deleter for arrays of another type, @p _Up, |
67 | * only if @p _Up* is convertible to @p _Tp*. |
68 | */ |
69 | template<typename _Up, typename = typename |
70 | enable_if<is_convertible<_Up*, _Tp*>::value>::type> |
71 | default_delete(const default_delete<_Up>&) noexcept { } |
72 | |
73 | /// Calls @c delete @p __ptr |
74 | void |
75 | operator()(_Tp* __ptr) const |
76 | { |
77 | static_assert(!is_void<_Tp>::value, |
78 | "can't delete pointer to incomplete type"); |
79 | static_assert(sizeof(_Tp)>0, |
80 | "can't delete pointer to incomplete type"); |
81 | delete __ptr; |
82 | } |
83 | }; |
84 | |
85 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
86 | // DR 740 - omit specialization for array objects with a compile time length |
87 | /// Specialization for arrays, default_delete. |
88 | template<typename _Tp> |
89 | struct default_delete<_Tp[]> |
90 | { |
91 | public: |
92 | /// Default constructor |
93 | constexpr default_delete() noexcept = default; |
94 | |
95 | /** @brief Converting constructor. |
96 | * |
97 | * Allows conversion from a deleter for arrays of another type, such as |
98 | * a const-qualified version of @p _Tp. |
99 | * |
100 | * Conversions from types derived from @c _Tp are not allowed because |
101 | * it is unsafe to @c delete[] an array of derived types through a |
102 | * pointer to the base type. |
103 | */ |
104 | template<typename _Up, typename = typename |
105 | enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type> |
106 | default_delete(const default_delete<_Up[]>&) noexcept { } |
107 | |
108 | /// Calls @c delete[] @p __ptr |
109 | template<typename _Up> |
110 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
111 | operator()(_Up* __ptr) const |
112 | { |
113 | static_assert(sizeof(_Tp)>0, |
114 | "can't delete pointer to incomplete type"); |
115 | delete [] __ptr; |
116 | } |
117 | }; |
118 | |
119 | template <typename _Tp, typename _Dp> |
120 | class __uniq_ptr_impl |
121 | { |
122 | template <typename _Up, typename _Ep, typename = void> |
123 | struct _Ptr |
124 | { |
125 | using type = _Up*; |
126 | }; |
127 | |
128 | template <typename _Up, typename _Ep> |
129 | struct |
130 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
131 | { |
132 | using type = typename remove_reference<_Ep>::type::pointer; |
133 | }; |
134 | |
135 | public: |
136 | using _DeleterConstraint = enable_if< |
137 | __and_<__not_<is_pointer<_Dp>>, |
138 | is_default_constructible<_Dp>>::value>; |
139 | |
140 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
141 | |
142 | __uniq_ptr_impl() = default; |
143 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
144 | |
145 | template<typename _Del> |
146 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
147 | : _M_t(__p, std::forward<_Del>(__d)) { } |
148 | |
149 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
150 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
151 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
152 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
153 | |
154 | private: |
155 | tuple<pointer, _Dp> _M_t; |
156 | }; |
157 | |
158 | /// 20.7.1.2 unique_ptr for single objects. |
159 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
160 | class unique_ptr |
161 | { |
162 | template <class _Up> |
163 | using _DeleterConstraint = |
164 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
165 | |
166 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
167 | |
168 | public: |
169 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
170 | using element_type = _Tp; |
171 | using deleter_type = _Dp; |
172 | |
173 | // helper template for detecting a safe conversion from another |
174 | // unique_ptr |
175 | template<typename _Up, typename _Ep> |
176 | using __safe_conversion_up = __and_< |
177 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
178 | __not_<is_array<_Up>>, |
179 | __or_<__and_<is_reference<deleter_type>, |
180 | is_same<deleter_type, _Ep>>, |
181 | __and_<__not_<is_reference<deleter_type>>, |
182 | is_convertible<_Ep, deleter_type>> |
183 | > |
184 | >; |
185 | |
186 | // Constructors. |
187 | |
188 | /// Default constructor, creates a unique_ptr that owns nothing. |
189 | template <typename _Up = _Dp, |
190 | typename = _DeleterConstraint<_Up>> |
191 | constexpr unique_ptr() noexcept |
192 | : _M_t() |
193 | { } |
194 | |
195 | /** Takes ownership of a pointer. |
196 | * |
197 | * @param __p A pointer to an object of @c element_type |
198 | * |
199 | * The deleter will be value-initialized. |
200 | */ |
201 | template <typename _Up = _Dp, |
202 | typename = _DeleterConstraint<_Up>> |
203 | explicit |
204 | unique_ptr(pointer __p) noexcept |
205 | : _M_t(__p) |
206 | { } |
207 | |
208 | /** Takes ownership of a pointer. |
209 | * |
210 | * @param __p A pointer to an object of @c element_type |
211 | * @param __d A reference to a deleter. |
212 | * |
213 | * The deleter will be initialized with @p __d |
214 | */ |
215 | unique_ptr(pointer __p, |
216 | typename conditional<is_reference<deleter_type>::value, |
217 | deleter_type, const deleter_type&>::type __d) noexcept |
218 | : _M_t(__p, __d) { } |
219 | |
220 | /** Takes ownership of a pointer. |
221 | * |
222 | * @param __p A pointer to an object of @c element_type |
223 | * @param __d An rvalue reference to a deleter. |
224 | * |
225 | * The deleter will be initialized with @p std::move(__d) |
226 | */ |
227 | unique_ptr(pointer __p, |
228 | typename remove_reference<deleter_type>::type&& __d) noexcept |
229 | : _M_t(std::move(__p), std::move(__d)) |
230 | { static_assert(!std::is_reference<deleter_type>::value, |
231 | "rvalue deleter bound to reference"); } |
232 | |
233 | /// Creates a unique_ptr that owns nothing. |
234 | template <typename _Up = _Dp, |
235 | typename = _DeleterConstraint<_Up>> |
236 | constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
237 | |
238 | // Move constructors. |
239 | |
240 | /// Move constructor. |
241 | unique_ptr(unique_ptr&& __u) noexcept |
242 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
243 | |
244 | /** @brief Converting constructor from another type |
245 | * |
246 | * Requires that the pointer owned by @p __u is convertible to the |
247 | * type of pointer owned by this object, @p __u does not own an array, |
248 | * and @p __u has a compatible deleter type. |
249 | */ |
250 | template<typename _Up, typename _Ep, typename = _Require< |
251 | __safe_conversion_up<_Up, _Ep>, |
252 | typename conditional<is_reference<_Dp>::value, |
253 | is_same<_Ep, _Dp>, |
254 | is_convertible<_Ep, _Dp>>::type>> |
255 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
256 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
257 | { } |
258 | |
259 | #if _GLIBCXX_USE_DEPRECATED1 |
260 | #pragma GCC diagnostic push |
261 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
262 | /// Converting constructor from @c auto_ptr |
263 | template<typename _Up, typename = _Require< |
264 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
265 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
266 | #pragma GCC diagnostic pop |
267 | #endif |
268 | |
269 | /// Destructor, invokes the deleter if the stored pointer is not null. |
270 | ~unique_ptr() noexcept |
271 | { |
272 | auto& __ptr = _M_t._M_ptr(); |
273 | if (__ptr != nullptr) |
274 | get_deleter()(__ptr); |
275 | __ptr = pointer(); |
276 | } |
277 | |
278 | // Assignment. |
279 | |
280 | /** @brief Move assignment operator. |
281 | * |
282 | * @param __u The object to transfer ownership from. |
283 | * |
284 | * Invokes the deleter first if this object owns a pointer. |
285 | */ |
286 | unique_ptr& |
287 | operator=(unique_ptr&& __u) noexcept |
288 | { |
289 | reset(__u.release()); |
290 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
291 | return *this; |
292 | } |
293 | |
294 | /** @brief Assignment from another type. |
295 | * |
296 | * @param __u The object to transfer ownership from, which owns a |
297 | * convertible pointer to a non-array object. |
298 | * |
299 | * Invokes the deleter first if this object owns a pointer. |
300 | */ |
301 | template<typename _Up, typename _Ep> |
302 | typename enable_if< __and_< |
303 | __safe_conversion_up<_Up, _Ep>, |
304 | is_assignable<deleter_type&, _Ep&&> |
305 | >::value, |
306 | unique_ptr&>::type |
307 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
308 | { |
309 | reset(__u.release()); |
310 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
311 | return *this; |
312 | } |
313 | |
314 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
315 | unique_ptr& |
316 | operator=(nullptr_t) noexcept |
317 | { |
318 | reset(); |
319 | return *this; |
320 | } |
321 | |
322 | // Observers. |
323 | |
324 | /// Dereference the stored pointer. |
325 | typename add_lvalue_reference<element_type>::type |
326 | operator*() const |
327 | { |
328 | __glibcxx_assert(get() != pointer()); |
329 | return *get(); |
330 | } |
331 | |
332 | /// Return the stored pointer. |
333 | pointer |
334 | operator->() const noexcept |
335 | { |
336 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
337 | return get(); |
338 | } |
339 | |
340 | /// Return the stored pointer. |
341 | pointer |
342 | get() const noexcept |
343 | { return _M_t._M_ptr(); } |
344 | |
345 | /// Return a reference to the stored deleter. |
346 | deleter_type& |
347 | get_deleter() noexcept |
348 | { return _M_t._M_deleter(); } |
349 | |
350 | /// Return a reference to the stored deleter. |
351 | const deleter_type& |
352 | get_deleter() const noexcept |
353 | { return _M_t._M_deleter(); } |
354 | |
355 | /// Return @c true if the stored pointer is not null. |
356 | explicit operator bool() const noexcept |
357 | { return get() == pointer() ? false : true; } |
358 | |
359 | // Modifiers. |
360 | |
361 | /// Release ownership of any stored pointer. |
362 | pointer |
363 | release() noexcept |
364 | { |
365 | pointer __p = get(); |
366 | _M_t._M_ptr() = pointer(); |
367 | return __p; |
368 | } |
369 | |
370 | /** @brief Replace the stored pointer. |
371 | * |
372 | * @param __p The new pointer to store. |
373 | * |
374 | * The deleter will be invoked if a pointer is already owned. |
375 | */ |
376 | void |
377 | reset(pointer __p = pointer()) noexcept |
378 | { |
379 | using std::swap; |
380 | swap(_M_t._M_ptr(), __p); |
381 | if (__p != pointer()) |
382 | get_deleter()(__p); |
383 | } |
384 | |
385 | /// Exchange the pointer and deleter with another object. |
386 | void |
387 | swap(unique_ptr& __u) noexcept |
388 | { |
389 | using std::swap; |
390 | swap(_M_t, __u._M_t); |
391 | } |
392 | |
393 | // Disable copy from lvalue. |
394 | unique_ptr(const unique_ptr&) = delete; |
395 | unique_ptr& operator=(const unique_ptr&) = delete; |
396 | }; |
397 | |
398 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
399 | // [unique.ptr.runtime] |
400 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
401 | // DR 740 - omit specialization for array objects with a compile time length |
402 | template<typename _Tp, typename _Dp> |
403 | class unique_ptr<_Tp[], _Dp> |
404 | { |
405 | template <typename _Up> |
406 | using _DeleterConstraint = |
407 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
408 | |
409 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
410 | |
411 | template<typename _Up> |
412 | using __remove_cv = typename remove_cv<_Up>::type; |
413 | |
414 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
415 | template<typename _Up> |
416 | using __is_derived_Tp |
417 | = __and_< is_base_of<_Tp, _Up>, |
418 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
419 | |
420 | public: |
421 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
422 | using element_type = _Tp; |
423 | using deleter_type = _Dp; |
424 | |
425 | // helper template for detecting a safe conversion from another |
426 | // unique_ptr |
427 | template<typename _Up, typename _Ep, |
428 | typename _Up_up = unique_ptr<_Up, _Ep>, |
429 | typename _Up_element_type = typename _Up_up::element_type> |
430 | using __safe_conversion_up = __and_< |
431 | is_array<_Up>, |
432 | is_same<pointer, element_type*>, |
433 | is_same<typename _Up_up::pointer, _Up_element_type*>, |
434 | is_convertible<_Up_element_type(*)[], element_type(*)[]>, |
435 | __or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>, |
436 | __and_<__not_<is_reference<deleter_type>>, |
437 | is_convertible<_Ep, deleter_type>>> |
438 | >; |
439 | |
440 | // helper template for detecting a safe conversion from a raw pointer |
441 | template<typename _Up> |
442 | using __safe_conversion_raw = __and_< |
443 | __or_<__or_<is_same<_Up, pointer>, |
444 | is_same<_Up, nullptr_t>>, |
445 | __and_<is_pointer<_Up>, |
446 | is_same<pointer, element_type*>, |
447 | is_convertible< |
448 | typename remove_pointer<_Up>::type(*)[], |
449 | element_type(*)[]> |
450 | > |
451 | > |
452 | >; |
453 | |
454 | // Constructors. |
455 | |
456 | /// Default constructor, creates a unique_ptr that owns nothing. |
457 | template <typename _Up = _Dp, |
458 | typename = _DeleterConstraint<_Up>> |
459 | constexpr unique_ptr() noexcept |
460 | : _M_t() |
461 | { } |
462 | |
463 | /** Takes ownership of a pointer. |
464 | * |
465 | * @param __p A pointer to an array of a type safely convertible |
466 | * to an array of @c element_type |
467 | * |
468 | * The deleter will be value-initialized. |
469 | */ |
470 | template<typename _Up, |
471 | typename _Vp = _Dp, |
472 | typename = _DeleterConstraint<_Vp>, |
473 | typename = typename enable_if< |
474 | __safe_conversion_raw<_Up>::value, bool>::type> |
475 | explicit |
476 | unique_ptr(_Up __p) noexcept |
477 | : _M_t(__p) |
478 | { } |
479 | |
480 | /** Takes ownership of a pointer. |
481 | * |
482 | * @param __p A pointer to an array of a type safely convertible |
483 | * to an array of @c element_type |
484 | * @param __d A reference to a deleter. |
485 | * |
486 | * The deleter will be initialized with @p __d |
487 | */ |
488 | template<typename _Up, |
489 | typename = typename enable_if< |
490 | __safe_conversion_raw<_Up>::value, bool>::type> |
491 | unique_ptr(_Up __p, |
492 | typename conditional<is_reference<deleter_type>::value, |
493 | deleter_type, const deleter_type&>::type __d) noexcept |
494 | : _M_t(__p, __d) { } |
495 | |
496 | /** Takes ownership of a pointer. |
497 | * |
498 | * @param __p A pointer to an array of a type safely convertible |
499 | * to an array of @c element_type |
500 | * @param __d A reference to a deleter. |
501 | * |
502 | * The deleter will be initialized with @p std::move(__d) |
503 | */ |
504 | template<typename _Up, |
505 | typename = typename enable_if< |
506 | __safe_conversion_raw<_Up>::value, bool>::type> |
507 | unique_ptr(_Up __p, typename |
508 | remove_reference<deleter_type>::type&& __d) noexcept |
509 | : _M_t(std::move(__p), std::move(__d)) |
510 | { static_assert(!is_reference<deleter_type>::value, |
511 | "rvalue deleter bound to reference"); } |
512 | |
513 | /// Move constructor. |
514 | unique_ptr(unique_ptr&& __u) noexcept |
515 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
516 | |
517 | /// Creates a unique_ptr that owns nothing. |
518 | template <typename _Up = _Dp, |
519 | typename = _DeleterConstraint<_Up>> |
520 | constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
521 | |
522 | template<typename _Up, typename _Ep, |
523 | typename = _Require<__safe_conversion_up<_Up, _Ep>>> |
524 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
525 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
526 | { } |
527 | |
528 | /// Destructor, invokes the deleter if the stored pointer is not null. |
529 | ~unique_ptr() |
530 | { |
531 | auto& __ptr = _M_t._M_ptr(); |
532 | if (__ptr != nullptr) |
533 | get_deleter()(__ptr); |
534 | __ptr = pointer(); |
535 | } |
536 | |
537 | // Assignment. |
538 | |
539 | /** @brief Move assignment operator. |
540 | * |
541 | * @param __u The object to transfer ownership from. |
542 | * |
543 | * Invokes the deleter first if this object owns a pointer. |
544 | */ |
545 | unique_ptr& |
546 | operator=(unique_ptr&& __u) noexcept |
547 | { |
548 | reset(__u.release()); |
549 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
550 | return *this; |
551 | } |
552 | |
553 | /** @brief Assignment from another type. |
554 | * |
555 | * @param __u The object to transfer ownership from, which owns a |
556 | * convertible pointer to an array object. |
557 | * |
558 | * Invokes the deleter first if this object owns a pointer. |
559 | */ |
560 | template<typename _Up, typename _Ep> |
561 | typename |
562 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
563 | is_assignable<deleter_type&, _Ep&&> |
564 | >::value, |
565 | unique_ptr&>::type |
566 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
567 | { |
568 | reset(__u.release()); |
569 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
570 | return *this; |
571 | } |
572 | |
573 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
574 | unique_ptr& |
575 | operator=(nullptr_t) noexcept |
576 | { |
577 | reset(); |
578 | return *this; |
579 | } |
580 | |
581 | // Observers. |
582 | |
583 | /// Access an element of owned array. |
584 | typename std::add_lvalue_reference<element_type>::type |
585 | operator[](size_t __i) const |
586 | { |
587 | __glibcxx_assert(get() != pointer()); |
588 | return get()[__i]; |
589 | } |
590 | |
591 | /// Return the stored pointer. |
592 | pointer |
593 | get() const noexcept |
594 | { return _M_t._M_ptr(); } |
595 | |
596 | /// Return a reference to the stored deleter. |
597 | deleter_type& |
598 | get_deleter() noexcept |
599 | { return _M_t._M_deleter(); } |
600 | |
601 | /// Return a reference to the stored deleter. |
602 | const deleter_type& |
603 | get_deleter() const noexcept |
604 | { return _M_t._M_deleter(); } |
605 | |
606 | /// Return @c true if the stored pointer is not null. |
607 | explicit operator bool() const noexcept |
608 | { return get() == pointer() ? false : true; } |
609 | |
610 | // Modifiers. |
611 | |
612 | /// Release ownership of any stored pointer. |
613 | pointer |
614 | release() noexcept |
615 | { |
616 | pointer __p = get(); |
617 | _M_t._M_ptr() = pointer(); |
618 | return __p; |
619 | } |
620 | |
621 | /** @brief Replace the stored pointer. |
622 | * |
623 | * @param __p The new pointer to store. |
624 | * |
625 | * The deleter will be invoked if a pointer is already owned. |
626 | */ |
627 | template <typename _Up, |
628 | typename = _Require< |
629 | __or_<is_same<_Up, pointer>, |
630 | __and_<is_same<pointer, element_type*>, |
631 | is_pointer<_Up>, |
632 | is_convertible< |
633 | typename remove_pointer<_Up>::type(*)[], |
634 | element_type(*)[] |
635 | > |
636 | > |
637 | > |
638 | >> |
639 | void |
640 | reset(_Up __p) noexcept |
641 | { |
642 | pointer __ptr = __p; |
643 | using std::swap; |
644 | swap(_M_t._M_ptr(), __ptr); |
645 | if (__ptr != nullptr) |
646 | get_deleter()(__ptr); |
647 | } |
648 | |
649 | void reset(nullptr_t = nullptr) noexcept |
650 | { |
651 | reset(pointer()); |
652 | } |
653 | |
654 | /// Exchange the pointer and deleter with another object. |
655 | void |
656 | swap(unique_ptr& __u) noexcept |
657 | { |
658 | using std::swap; |
659 | swap(_M_t, __u._M_t); |
660 | } |
661 | |
662 | // Disable copy from lvalue. |
663 | unique_ptr(const unique_ptr&) = delete; |
664 | unique_ptr& operator=(const unique_ptr&) = delete; |
665 | }; |
666 | |
667 | template<typename _Tp, typename _Dp> |
668 | inline |
669 | #if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
670 | // Constrained free swap overload, see p0185r1 |
671 | typename enable_if<__is_swappable<_Dp>::value>::type |
672 | #else |
673 | void |
674 | #endif |
675 | swap(unique_ptr<_Tp, _Dp>& __x, |
676 | unique_ptr<_Tp, _Dp>& __y) noexcept |
677 | { __x.swap(__y); } |
678 | |
679 | #if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
680 | template<typename _Tp, typename _Dp> |
681 | typename enable_if<!__is_swappable<_Dp>::value>::type |
682 | swap(unique_ptr<_Tp, _Dp>&, |
683 | unique_ptr<_Tp, _Dp>&) = delete; |
684 | #endif |
685 | |
686 | template<typename _Tp, typename _Dp, |
687 | typename _Up, typename _Ep> |
688 | inline bool |
689 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
690 | const unique_ptr<_Up, _Ep>& __y) |
691 | { return __x.get() == __y.get(); } |
692 | |
693 | template<typename _Tp, typename _Dp> |
694 | inline bool |
695 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
696 | { return !__x; } |
697 | |
698 | template<typename _Tp, typename _Dp> |
699 | inline bool |
700 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
701 | { return !__x; } |
702 | |
703 | template<typename _Tp, typename _Dp, |
704 | typename _Up, typename _Ep> |
705 | inline bool |
706 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
707 | const unique_ptr<_Up, _Ep>& __y) |
708 | { return __x.get() != __y.get(); } |
709 | |
710 | template<typename _Tp, typename _Dp> |
711 | inline bool |
712 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
713 | { return (bool)__x; } |
714 | |
715 | template<typename _Tp, typename _Dp> |
716 | inline bool |
717 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
718 | { return (bool)__x; } |
719 | |
720 | template<typename _Tp, typename _Dp, |
721 | typename _Up, typename _Ep> |
722 | inline bool |
723 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
724 | const unique_ptr<_Up, _Ep>& __y) |
725 | { |
726 | typedef typename |
727 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
728 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
729 | return std::less<_CT>()(__x.get(), __y.get()); |
730 | } |
731 | |
732 | template<typename _Tp, typename _Dp> |
733 | inline bool |
734 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
735 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
736 | nullptr); } |
737 | |
738 | template<typename _Tp, typename _Dp> |
739 | inline bool |
740 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
741 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
742 | __x.get()); } |
743 | |
744 | template<typename _Tp, typename _Dp, |
745 | typename _Up, typename _Ep> |
746 | inline bool |
747 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
748 | const unique_ptr<_Up, _Ep>& __y) |
749 | { return !(__y < __x); } |
750 | |
751 | template<typename _Tp, typename _Dp> |
752 | inline bool |
753 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
754 | { return !(nullptr < __x); } |
755 | |
756 | template<typename _Tp, typename _Dp> |
757 | inline bool |
758 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
759 | { return !(__x < nullptr); } |
760 | |
761 | template<typename _Tp, typename _Dp, |
762 | typename _Up, typename _Ep> |
763 | inline bool |
764 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
765 | const unique_ptr<_Up, _Ep>& __y) |
766 | { return (__y < __x); } |
767 | |
768 | template<typename _Tp, typename _Dp> |
769 | inline bool |
770 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
771 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
772 | __x.get()); } |
773 | |
774 | template<typename _Tp, typename _Dp> |
775 | inline bool |
776 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
777 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
778 | nullptr); } |
779 | |
780 | template<typename _Tp, typename _Dp, |
781 | typename _Up, typename _Ep> |
782 | inline bool |
783 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
784 | const unique_ptr<_Up, _Ep>& __y) |
785 | { return !(__x < __y); } |
786 | |
787 | template<typename _Tp, typename _Dp> |
788 | inline bool |
789 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
790 | { return !(__x < nullptr); } |
791 | |
792 | template<typename _Tp, typename _Dp> |
793 | inline bool |
794 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
795 | { return !(nullptr < __x); } |
796 | |
797 | /// std::hash specialization for unique_ptr. |
798 | template<typename _Tp, typename _Dp> |
799 | struct hash<unique_ptr<_Tp, _Dp>> |
800 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
801 | private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> |
802 | { |
803 | size_t |
804 | operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept |
805 | { |
806 | typedef unique_ptr<_Tp, _Dp> _UP; |
807 | return std::hash<typename _UP::pointer>()(__u.get()); |
808 | } |
809 | }; |
810 | |
811 | #if __cplusplus201103L > 201103L |
812 | |
813 | #define __cpp_lib_make_unique 201304 |
814 | |
815 | template<typename _Tp> |
816 | struct _MakeUniq |
817 | { typedef unique_ptr<_Tp> __single_object; }; |
818 | |
819 | template<typename _Tp> |
820 | struct _MakeUniq<_Tp[]> |
821 | { typedef unique_ptr<_Tp[]> __array; }; |
822 | |
823 | template<typename _Tp, size_t _Bound> |
824 | struct _MakeUniq<_Tp[_Bound]> |
825 | { struct __invalid_type { }; }; |
826 | |
827 | /// std::make_unique for single objects |
828 | template<typename _Tp, typename... _Args> |
829 | inline typename _MakeUniq<_Tp>::__single_object |
830 | make_unique(_Args&&... __args) |
831 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
832 | |
833 | /// std::make_unique for arrays of unknown bound |
834 | template<typename _Tp> |
835 | inline typename _MakeUniq<_Tp>::__array |
836 | make_unique(size_t __num) |
837 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
838 | |
839 | /// Disable std::make_unique for arrays of known bound |
840 | template<typename _Tp, typename... _Args> |
841 | inline typename _MakeUniq<_Tp>::__invalid_type |
842 | make_unique(_Args&&...) = delete; |
843 | #endif |
844 | |
845 | // @} group pointer_abstractions |
846 | |
847 | _GLIBCXX_END_NAMESPACE_VERSION |
848 | } // namespace |
849 | |
850 | #endif /* _UNIQUE_PTR_H */ |