LLVM  14.0.0git
VirtualFileSystem.cpp
Go to the documentation of this file.
1 //===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the VirtualFileSystem interface.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/None.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/StringSet.h"
24 #include "llvm/ADT/Twine.h"
26 #include "llvm/Config/llvm-config.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Chrono.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/Errc.h"
33 #include "llvm/Support/ErrorOr.h"
36 #include "llvm/Support/Path.h"
37 #include "llvm/Support/Process.h"
38 #include "llvm/Support/SMLoc.h"
39 #include "llvm/Support/SourceMgr.h"
42 #include <algorithm>
43 #include <atomic>
44 #include <cassert>
45 #include <cstdint>
46 #include <iterator>
47 #include <limits>
48 #include <map>
49 #include <memory>
50 #include <mutex>
51 #include <string>
52 #include <system_error>
53 #include <utility>
54 #include <vector>
55 
56 using namespace llvm;
57 using namespace llvm::vfs;
58 
65 
67  : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
68  User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
69  Type(Status.type()), Perms(Status.permissions()) {}
70 
73  perms Perms)
74  : Name(Name.str()), UID(UID), MTime(MTime), User(User), Group(Group),
75  Size(Size), Type(Type), Perms(Perms) {}
76 
77 Status Status::copyWithNewName(const Status &In, const Twine &NewName) {
78  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
79  In.getUser(), In.getGroup(), In.getSize(), In.getType(),
80  In.getPermissions());
81 }
82 
84  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
85  In.getUser(), In.getGroup(), In.getSize(), In.type(),
86  In.permissions());
87 }
88 
89 bool Status::equivalent(const Status &Other) const {
90  assert(isStatusKnown() && Other.isStatusKnown());
91  return getUniqueID() == Other.getUniqueID();
92 }
93 
94 bool Status::isDirectory() const { return Type == file_type::directory_file; }
95 
96 bool Status::isRegularFile() const { return Type == file_type::regular_file; }
97 
98 bool Status::isOther() const {
99  return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
100 }
101 
102 bool Status::isSymlink() const { return Type == file_type::symlink_file; }
103 
104 bool Status::isStatusKnown() const { return Type != file_type::status_error; }
105 
106 bool Status::exists() const {
107  return isStatusKnown() && Type != file_type::file_not_found;
108 }
109 
110 File::~File() = default;
111 
112 FileSystem::~FileSystem() = default;
113 
116  bool RequiresNullTerminator, bool IsVolatile) {
117  auto F = openFileForRead(Name);
118  if (!F)
119  return F.getError();
120 
121  return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
122 }
123 
124 std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
126  return {};
127 
128  auto WorkingDir = getCurrentWorkingDirectory();
129  if (!WorkingDir)
130  return WorkingDir.getError();
131 
132  llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
133  return {};
134 }
135 
136 std::error_code FileSystem::getRealPath(const Twine &Path,
137  SmallVectorImpl<char> &Output) const {
139 }
140 
141 std::error_code FileSystem::isLocal(const Twine &Path, bool &Result) {
143 }
144 
145 bool FileSystem::exists(const Twine &Path) {
146  auto Status = status(Path);
147  return Status && Status->exists();
148 }
149 
150 #ifndef NDEBUG
151 static bool isTraversalComponent(StringRef Component) {
152  return Component.equals("..") || Component.equals(".");
153 }
154 
155 static bool pathHasTraversal(StringRef Path) {
156  using namespace llvm::sys;
157 
158  for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
159  if (isTraversalComponent(Comp))
160  return true;
161  return false;
162 }
163 #endif
164 
165 //===-----------------------------------------------------------------------===/
166 // RealFileSystem implementation
167 //===-----------------------------------------------------------------------===/
168 
169 namespace {
170 
171 /// Wrapper around a raw file descriptor.
172 class RealFile : public File {
173  friend class RealFileSystem;
174 
175  file_t FD;
176  Status S;
177  std::string RealName;
178 
179  RealFile(file_t RawFD, StringRef NewName, StringRef NewRealPathName)
180  : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
182  RealName(NewRealPathName.str()) {
183  assert(FD != kInvalidFile && "Invalid or inactive file descriptor");
184  }
185 
186 public:
187  ~RealFile() override;
188 
189  ErrorOr<Status> status() override;
190  ErrorOr<std::string> getName() override;
192  int64_t FileSize,
193  bool RequiresNullTerminator,
194  bool IsVolatile) override;
195  std::error_code close() override;
196 };
197 
198 } // namespace
199 
200 RealFile::~RealFile() { close(); }
201 
203  assert(FD != kInvalidFile && "cannot stat closed file");
204  if (!S.isStatusKnown()) {
205  file_status RealStatus;
206  if (std::error_code EC = sys::fs::status(FD, RealStatus))
207  return EC;
208  S = Status::copyWithNewName(RealStatus, S.getName());
209  }
210  return S;
211 }
212 
214  return RealName.empty() ? S.getName().str() : RealName;
215 }
216 
218 RealFile::getBuffer(const Twine &Name, int64_t FileSize,
219  bool RequiresNullTerminator, bool IsVolatile) {
220  assert(FD != kInvalidFile && "cannot get buffer for closed file");
221  return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
222  IsVolatile);
223 }
224 
225 std::error_code RealFile::close() {
226  std::error_code EC = sys::fs::closeFile(FD);
227  FD = kInvalidFile;
228  return EC;
229 }
230 
231 namespace {
232 
233 /// A file system according to your operating system.
234 /// This may be linked to the process's working directory, or maintain its own.
235 ///
236 /// Currently, its own working directory is emulated by storing the path and
237 /// sending absolute paths to llvm::sys::fs:: functions.
238 /// A more principled approach would be to push this down a level, modelling
239 /// the working dir as an llvm::sys::fs::WorkingDir or similar.
240 /// This would enable the use of openat()-style functions on some platforms.
241 class RealFileSystem : public FileSystem {
242 public:
243  explicit RealFileSystem(bool LinkCWDToProcess) {
244  if (!LinkCWDToProcess) {
245  SmallString<128> PWD, RealPWD;
247  return; // Awful, but nothing to do here.
248  if (llvm::sys::fs::real_path(PWD, RealPWD))
249  WD = {PWD, PWD};
250  else
251  WD = {PWD, RealPWD};
252  }
253  }
254 
255  ErrorOr<Status> status(const Twine &Path) override;
256  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
257  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
258 
259  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
260  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
261  std::error_code isLocal(const Twine &Path, bool &Result) override;
262  std::error_code getRealPath(const Twine &Path,
263  SmallVectorImpl<char> &Output) const override;
264 
265 private:
266  // If this FS has its own working dir, use it to make Path absolute.
267  // The returned twine is safe to use as long as both Storage and Path live.
268  Twine adjustPath(const Twine &Path, SmallVectorImpl<char> &Storage) const {
269  if (!WD)
270  return Path;
271  Path.toVector(Storage);
272  sys::fs::make_absolute(WD->Resolved, Storage);
273  return Storage;
274  }
275 
276  struct WorkingDirectory {
277  // The current working directory, without symlinks resolved. (echo $PWD).
278  SmallString<128> Specified;
279  // The current working directory, with links resolved. (readlink .).
281  };
283 };
284 
285 } // namespace
286 
288  SmallString<256> Storage;
289  sys::fs::file_status RealStatus;
290  if (std::error_code EC =
291  sys::fs::status(adjustPath(Path, Storage), RealStatus))
292  return EC;
293  return Status::copyWithNewName(RealStatus, Path);
294 }
295 
298  SmallString<256> RealName, Storage;
300  adjustPath(Name, Storage), sys::fs::OF_None, &RealName);
301  if (!FDOrErr)
302  return errorToErrorCode(FDOrErr.takeError());
303  return std::unique_ptr<File>(
304  new RealFile(*FDOrErr, Name.str(), RealName.str()));
305 }
306 
307 llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
308  if (WD)
309  return std::string(WD->Specified.str());
310 
311  SmallString<128> Dir;
312  if (std::error_code EC = llvm::sys::fs::current_path(Dir))
313  return EC;
314  return std::string(Dir.str());
315 }
316 
317 std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
318  if (!WD)
319  return llvm::sys::fs::set_current_path(Path);
320 
322  adjustPath(Path, Storage).toVector(Absolute);
323  bool IsDir;
324  if (auto Err = llvm::sys::fs::is_directory(Absolute, IsDir))
325  return Err;
326  if (!IsDir)
327  return std::make_error_code(std::errc::not_a_directory);
328  if (auto Err = llvm::sys::fs::real_path(Absolute, Resolved))
329  return Err;
330  WD = {Absolute, Resolved};
331  return std::error_code();
332 }
333 
334 std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
335  SmallString<256> Storage;
336  return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result);
337 }
338 
339 std::error_code
340 RealFileSystem::getRealPath(const Twine &Path,
341  SmallVectorImpl<char> &Output) const {
342  SmallString<256> Storage;
343  return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
344 }
345 
347  static IntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true));
348  return FS;
349 }
350 
351 std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
352  return std::make_unique<RealFileSystem>(false);
353 }
354 
355 namespace {
356 
357 class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
359 
360 public:
361  RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
362  if (Iter != llvm::sys::fs::directory_iterator())
363  CurrentEntry = directory_entry(Iter->path(), Iter->type());
364  }
365 
366  std::error_code increment() override {
367  std::error_code EC;
368  Iter.increment(EC);
369  CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
370  ? directory_entry()
371  : directory_entry(Iter->path(), Iter->type());
372  return EC;
373  }
374 };
375 
376 } // namespace
377 
378 directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
379  std::error_code &EC) {
380  SmallString<128> Storage;
381  return directory_iterator(
382  std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
383 }
384 
385 //===-----------------------------------------------------------------------===/
386 // OverlayFileSystem implementation
387 //===-----------------------------------------------------------------------===/
388 
390  FSList.push_back(std::move(BaseFS));
391 }
392 
394  FSList.push_back(FS);
395  // Synchronize added file systems by duplicating the working directory from
396  // the first one in the list.
397  FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
398 }
399 
401  // FIXME: handle symlinks that cross file systems
402  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
403  ErrorOr<Status> Status = (*I)->status(Path);
405  return Status;
406  }
408 }
409 
412  // FIXME: handle symlinks that cross file systems
413  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
414  auto Result = (*I)->openFileForRead(Path);
415  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
416  return Result;
417  }
419 }
420 
423  // All file systems are synchronized, just take the first working directory.
424  return FSList.front()->getCurrentWorkingDirectory();
425 }
426 
427 std::error_code
429  for (auto &FS : FSList)
430  if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
431  return EC;
432  return {};
433 }
434 
435 std::error_code OverlayFileSystem::isLocal(const Twine &Path, bool &Result) {
436  for (auto &FS : FSList)
437  if (FS->exists(Path))
438  return FS->isLocal(Path, Result);
440 }
441 
442 std::error_code
444  SmallVectorImpl<char> &Output) const {
445  for (const auto &FS : FSList)
446  if (FS->exists(Path))
447  return FS->getRealPath(Path, Output);
449 }
450 
452 
453 namespace {
454 
455 /// Combines and deduplicates directory entries across multiple file systems.
456 class CombiningDirIterImpl : public llvm::vfs::detail::DirIterImpl {
458 
459  /// File systems to check for entries in. Processed in reverse order.
461  /// The directory iterator for the current filesystem.
462  directory_iterator CurrentDirIter;
463  /// The path of the directory to iterate the entries of.
464  std::string DirPath;
465  /// The set of names already returned as entries.
466  llvm::StringSet<> SeenNames;
467 
468  /// Sets \c CurrentDirIter to an iterator of \c DirPath in the next file
469  /// system in the list, or leaves it as is (at its end position) if we've
470  /// already gone through them all.
471  std::error_code incrementFS() {
472  while (!FSList.empty()) {
473  std::error_code EC;
474  CurrentDirIter = FSList.back()->dir_begin(DirPath, EC);
475  FSList.pop_back();
476  if (EC && EC != errc::no_such_file_or_directory)
477  return EC;
478  if (CurrentDirIter != directory_iterator())
479  break; // found
480  }
481  return {};
482  }
483 
484  std::error_code incrementDirIter(bool IsFirstTime) {
485  assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
486  "incrementing past end");
487  std::error_code EC;
488  if (!IsFirstTime)
489  CurrentDirIter.increment(EC);
490  if (!EC && CurrentDirIter == directory_iterator())
491  EC = incrementFS();
492  return EC;
493  }
494 
495  std::error_code incrementImpl(bool IsFirstTime) {
496  while (true) {
497  std::error_code EC = incrementDirIter(IsFirstTime);
498  if (EC || CurrentDirIter == directory_iterator()) {
499  CurrentEntry = directory_entry();
500  return EC;
501  }
502  CurrentEntry = *CurrentDirIter;
503  StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
504  if (SeenNames.insert(Name).second)
505  return EC; // name not seen before
506  }
507  llvm_unreachable("returned above");
508  }
509 
510 public:
511  CombiningDirIterImpl(ArrayRef<FileSystemPtr> FileSystems, std::string Dir,
512  std::error_code &EC)
513  : FSList(FileSystems.begin(), FileSystems.end()),
514  DirPath(std::move(Dir)) {
515  if (!FSList.empty()) {
516  CurrentDirIter = FSList.back()->dir_begin(DirPath, EC);
517  FSList.pop_back();
518  if (!EC || EC == errc::no_such_file_or_directory)
519  EC = incrementImpl(true);
520  }
521  }
522 
523  CombiningDirIterImpl(directory_iterator FirstIter, FileSystemPtr Fallback,
524  std::string FallbackDir, std::error_code &EC)
525  : FSList({Fallback}), CurrentDirIter(FirstIter),
526  DirPath(std::move(FallbackDir)) {
527  if (!EC || EC == errc::no_such_file_or_directory)
528  EC = incrementImpl(true);
529  }
530 
531  std::error_code increment() override { return incrementImpl(false); }
532 };
533 
534 } // namespace
535 
537  std::error_code &EC) {
538  return directory_iterator(
539  std::make_shared<CombiningDirIterImpl>(FSList, Dir.str(), EC));
540 }
541 
542 void ProxyFileSystem::anchor() {}
543 
544 namespace llvm {
545 namespace vfs {
546 
547 namespace detail {
548 
550 
551 /// The in memory file system is a tree of Nodes. Every node can either be a
552 /// file , hardlink or a directory.
555  std::string FileName;
556 
557 public:
559  : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) {
560  }
561  virtual ~InMemoryNode() = default;
562 
563  /// Get the filename of this node (the name without the directory part).
564  StringRef getFileName() const { return FileName; }
565  InMemoryNodeKind getKind() const { return Kind; }
566  virtual std::string toString(unsigned Indent) const = 0;
567 };
568 
569 class InMemoryFile : public InMemoryNode {
570  Status Stat;
571  std::unique_ptr<llvm::MemoryBuffer> Buffer;
572 
573 public:
574  InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
575  : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
576  Buffer(std::move(Buffer)) {}
577 
578  /// Return the \p Status for this node. \p RequestedName should be the name
579  /// through which the caller referred to this node. It will override
580  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
581  Status getStatus(const Twine &RequestedName) const {
582  return Status::copyWithNewName(Stat, RequestedName);
583  }
584  llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
585 
586  std::string toString(unsigned Indent) const override {
587  return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
588  }
589 
590  static bool classof(const InMemoryNode *N) {
591  return N->getKind() == IME_File;
592  }
593 };
594 
595 namespace {
596 
597 class InMemoryHardLink : public InMemoryNode {
598  const InMemoryFile &ResolvedFile;
599 
600 public:
601  InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)
602  : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
603  const InMemoryFile &getResolvedFile() const { return ResolvedFile; }
604 
605  std::string toString(unsigned Indent) const override {
606  return std::string(Indent, ' ') + "HardLink to -> " +
607  ResolvedFile.toString(0);
608  }
609 
610  static bool classof(const InMemoryNode *N) {
611  return N->getKind() == IME_HardLink;
612  }
613 };
614 
615 /// Adapt a InMemoryFile for VFS' File interface. The goal is to make
616 /// \p InMemoryFileAdaptor mimic as much as possible the behavior of
617 /// \p RealFile.
618 class InMemoryFileAdaptor : public File {
619  const InMemoryFile &Node;
620  /// The name to use when returning a Status for this file.
621  std::string RequestedName;
622 
623 public:
624  explicit InMemoryFileAdaptor(const InMemoryFile &Node,
625  std::string RequestedName)
626  : Node(Node), RequestedName(std::move(RequestedName)) {}
627 
628  llvm::ErrorOr<Status> status() override {
629  return Node.getStatus(RequestedName);
630  }
631 
633  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
634  bool IsVolatile) override {
635  llvm::MemoryBuffer *Buf = Node.getBuffer();
637  Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
638  }
639 
640  std::error_code close() override { return {}; }
641 };
642 } // namespace
643 
645  Status Stat;
647 
648 public:
650  : InMemoryNode(Stat.getName(), IME_Directory), Stat(std::move(Stat)) {}
651 
652  /// Return the \p Status for this node. \p RequestedName should be the name
653  /// through which the caller referred to this node. It will override
654  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
655  Status getStatus(const Twine &RequestedName) const {
656  return Status::copyWithNewName(Stat, RequestedName);
657  }
659  auto I = Entries.find(Name);
660  if (I != Entries.end())
661  return I->second.get();
662  return nullptr;
663  }
664 
665  InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
666  return Entries.insert(make_pair(Name, std::move(Child)))
667  .first->second.get();
668  }
669 
670  using const_iterator = decltype(Entries)::const_iterator;
671 
672  const_iterator begin() const { return Entries.begin(); }
673  const_iterator end() const { return Entries.end(); }
674 
675  std::string toString(unsigned Indent) const override {
676  std::string Result =
677  (std::string(Indent, ' ') + Stat.getName() + "\n").str();
678  for (const auto &Entry : Entries)
679  Result += Entry.second->toString(Indent + 2);
680  return Result;
681  }
682 
683  static bool classof(const InMemoryNode *N) {
684  return N->getKind() == IME_Directory;
685  }
686 };
687 
688 namespace {
689 Status getNodeStatus(const InMemoryNode *Node, const Twine &RequestedName) {
690  if (auto Dir = dyn_cast<detail::InMemoryDirectory>(Node))
691  return Dir->getStatus(RequestedName);
692  if (auto File = dyn_cast<detail::InMemoryFile>(Node))
693  return File->getStatus(RequestedName);
694  if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node))
695  return Link->getResolvedFile().getStatus(RequestedName);
696  llvm_unreachable("Unknown node type");
697 }
698 } // namespace
699 } // namespace detail
700 
702  : Root(new detail::InMemoryDirectory(
703  Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
704  0, llvm::sys::fs::file_type::directory_file,
705  llvm::sys::fs::perms::all_all))),
706  UseNormalizedPaths(UseNormalizedPaths) {}
707 
709 
710 std::string InMemoryFileSystem::toString() const {
711  return Root->toString(/*Indent=*/0);
712 }
713 
714 bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
715  std::unique_ptr<llvm::MemoryBuffer> Buffer,
717  Optional<uint32_t> Group,
720  const detail::InMemoryFile *HardLinkTarget) {
721  SmallString<128> Path;
722  P.toVector(Path);
723 
724  // Fix up relative paths. This just prepends the current working directory.
725  std::error_code EC = makeAbsolute(Path);
726  assert(!EC);
727  (void)EC;
728 
729  if (useNormalizedPaths())
730  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
731 
732  if (Path.empty())
733  return false;
734 
735  detail::InMemoryDirectory *Dir = Root.get();
736  auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
737  const auto ResolvedUser = User.getValueOr(0);
738  const auto ResolvedGroup = Group.getValueOr(0);
739  const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
740  const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
741  assert(!(HardLinkTarget && Buffer) && "HardLink cannot have a buffer");
742  // Any intermediate directories we create should be accessible by
743  // the owner, even if Perms says otherwise for the final path.
744  const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
745  while (true) {
746  StringRef Name = *I;
747  detail::InMemoryNode *Node = Dir->getChild(Name);
748  ++I;
749  if (!Node) {
750  if (I == E) {
751  // End of the path.
752  std::unique_ptr<detail::InMemoryNode> Child;
753  if (HardLinkTarget)
754  Child.reset(new detail::InMemoryHardLink(P.str(), *HardLinkTarget));
755  else {
756  // Create a new file or directory.
757  Status Stat(P.str(), getNextVirtualUniqueID(),
758  llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
759  ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
760  ResolvedPerms);
761  if (ResolvedType == sys::fs::file_type::directory_file) {
762  Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
763  } else {
764  Child.reset(
765  new detail::InMemoryFile(std::move(Stat), std::move(Buffer)));
766  }
767  }
768  Dir->addChild(Name, std::move(Child));
769  return true;
770  }
771 
772  // Create a new directory. Use the path up to here.
773  Status Stat(
774  StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
775  getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
776  ResolvedUser, ResolvedGroup, 0, sys::fs::file_type::directory_file,
777  NewDirectoryPerms);
778  Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
779  Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
780  continue;
781  }
782 
783  if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
784  Dir = NewDir;
785  } else {
786  assert((isa<detail::InMemoryFile>(Node) ||
787  isa<detail::InMemoryHardLink>(Node)) &&
788  "Must be either file, hardlink or directory!");
789 
790  // Trying to insert a directory in place of a file.
791  if (I != E)
792  return false;
793 
794  // Return false only if the new file is different from the existing one.
795  if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
796  return Link->getResolvedFile().getBuffer()->getBuffer() ==
797  Buffer->getBuffer();
798  }
799  return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
800  Buffer->getBuffer();
801  }
802  }
803 }
804 
805 bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
806  std::unique_ptr<llvm::MemoryBuffer> Buffer,
808  Optional<uint32_t> Group,
811  return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
812  Perms, /*HardLinkTarget=*/nullptr);
813 }
814 
815 bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
816  const llvm::MemoryBufferRef &Buffer,
818  Optional<uint32_t> Group,
821  return addFile(P, ModificationTime, llvm::MemoryBuffer::getMemBuffer(Buffer),
823  std::move(Perms));
824 }
825 
828  const Twine &P) {
829  SmallString<128> Path;
830  P.toVector(Path);
831 
832  // Fix up relative paths. This just prepends the current working directory.
833  std::error_code EC = FS.makeAbsolute(Path);
834  assert(!EC);
835  (void)EC;
836 
837  if (FS.useNormalizedPaths())
838  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
839 
840  if (Path.empty())
841  return Dir;
842 
843  auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
844  while (true) {
845  detail::InMemoryNode *Node = Dir->getChild(*I);
846  ++I;
847  if (!Node)
849 
850  // Return the file if it's at the end of the path.
851  if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
852  if (I == E)
853  return File;
855  }
856 
857  // If Node is HardLink then return the resolved file.
858  if (auto File = dyn_cast<detail::InMemoryHardLink>(Node)) {
859  if (I == E)
860  return &File->getResolvedFile();
862  }
863  // Traverse directories.
864  Dir = cast<detail::InMemoryDirectory>(Node);
865  if (I == E)
866  return Dir;
867  }
868 }
869 
871  const Twine &ToPath) {
872  auto FromNode = lookupInMemoryNode(*this, Root.get(), FromPath);
873  auto ToNode = lookupInMemoryNode(*this, Root.get(), ToPath);
874  // FromPath must not have been added before. ToPath must have been added
875  // before. Resolved ToPath must be a File.
876  if (!ToNode || FromNode || !isa<detail::InMemoryFile>(*ToNode))
877  return false;
878  return this->addFile(FromPath, 0, nullptr, None, None, None, None,
879  cast<detail::InMemoryFile>(*ToNode));
880 }
881 
883  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
884  if (Node)
885  return detail::getNodeStatus(*Node, Path);
886  return Node.getError();
887 }
888 
891  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
892  if (!Node)
893  return Node.getError();
894 
895  // When we have a file provide a heap-allocated wrapper for the memory buffer
896  // to match the ownership semantics for File.
897  if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
898  return std::unique_ptr<File>(
899  new detail::InMemoryFileAdaptor(*F, Path.str()));
900 
901  // FIXME: errc::not_a_file?
903 }
904 
905 namespace {
906 
907 /// Adaptor from InMemoryDir::iterator to directory_iterator.
908 class InMemoryDirIterator : public llvm::vfs::detail::DirIterImpl {
911  std::string RequestedDirName;
912 
913  void setCurrentEntry() {
914  if (I != E) {
915  SmallString<256> Path(RequestedDirName);
916  llvm::sys::path::append(Path, I->second->getFileName());
918  switch (I->second->getKind()) {
919  case detail::IME_File:
922  break;
925  break;
926  }
927  CurrentEntry = directory_entry(std::string(Path.str()), Type);
928  } else {
929  // When we're at the end, make CurrentEntry invalid and DirIterImpl will
930  // do the rest.
931  CurrentEntry = directory_entry();
932  }
933  }
934 
935 public:
936  InMemoryDirIterator() = default;
937 
938  explicit InMemoryDirIterator(const detail::InMemoryDirectory &Dir,
939  std::string RequestedDirName)
940  : I(Dir.begin()), E(Dir.end()),
941  RequestedDirName(std::move(RequestedDirName)) {
942  setCurrentEntry();
943  }
944 
945  std::error_code increment() override {
946  ++I;
947  setCurrentEntry();
948  return {};
949  }
950 };
951 
952 } // namespace
953 
955  std::error_code &EC) {
956  auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
957  if (!Node) {
958  EC = Node.getError();
959  return directory_iterator(std::make_shared<InMemoryDirIterator>());
960  }
961 
962  if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
963  return directory_iterator(
964  std::make_shared<InMemoryDirIterator>(*DirNode, Dir.str()));
965 
967  return directory_iterator(std::make_shared<InMemoryDirIterator>());
968 }
969 
971  SmallString<128> Path;
972  P.toVector(Path);
973 
974  // Fix up relative paths. This just prepends the current working directory.
975  std::error_code EC = makeAbsolute(Path);
976  assert(!EC);
977  (void)EC;
978 
979  if (useNormalizedPaths())
980  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
981 
982  if (!Path.empty())
983  WorkingDirectory = std::string(Path.str());
984  return {};
985 }
986 
987 std::error_code
989  SmallVectorImpl<char> &Output) const {
990  auto CWD = getCurrentWorkingDirectory();
991  if (!CWD || CWD->empty())
993  Path.toVector(Output);
994  if (auto EC = makeAbsolute(Output))
995  return EC;
996  llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
997  return {};
998 }
999 
1000 std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
1001  Result = false;
1002  return {};
1003 }
1004 
1005 } // namespace vfs
1006 } // namespace llvm
1007 
1008 //===-----------------------------------------------------------------------===/
1009 // RedirectingFileSystem implementation
1010 //===-----------------------------------------------------------------------===/
1011 
1012 namespace {
1013 
1014 static llvm::sys::path::Style getExistingStyle(llvm::StringRef Path) {
1015  // Detect the path style in use by checking the first separator.
1017  const size_t n = Path.find_first_of("/\\");
1018  if (n != static_cast<size_t>(-1))
1019  style = (Path[n] == '/') ? llvm::sys::path::Style::posix
1021  return style;
1022 }
1023 
1024 /// Removes leading "./" as well as path components like ".." and ".".
1025 static llvm::SmallString<256> canonicalize(llvm::StringRef Path) {
1026  // First detect the path style in use by checking the first separator.
1027  llvm::sys::path::Style style = getExistingStyle(Path);
1028 
1029  // Now remove the dots. Explicitly specifying the path style prevents the
1030  // direction of the slashes from changing.
1033  llvm::sys::path::remove_dots(result, /*remove_dot_dot=*/true, style);
1034  return result;
1035 }
1036 
1037 } // anonymous namespace
1038 
1039 
1040 RedirectingFileSystem::RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
1041  : ExternalFS(std::move(FS)) {
1042  if (ExternalFS)
1043  if (auto ExternalWorkingDirectory =
1044  ExternalFS->getCurrentWorkingDirectory()) {
1045  WorkingDirectory = *ExternalWorkingDirectory;
1046  }
1047 }
1048 
1049 /// Directory iterator implementation for \c RedirectingFileSystem's
1050 /// directory entries.
1053  std::string Dir;
1055 
1056  std::error_code incrementImpl(bool IsFirstTime) {
1057  assert((IsFirstTime || Current != End) && "cannot iterate past end");
1058  if (!IsFirstTime)
1059  ++Current;
1060  if (Current != End) {
1061  SmallString<128> PathStr(Dir);
1062  llvm::sys::path::append(PathStr, (*Current)->getName());
1064  switch ((*Current)->getKind()) {
1069  break;
1072  break;
1073  }
1074  CurrentEntry = directory_entry(std::string(PathStr.str()), Type);
1075  } else {
1077  }
1078  return {};
1079  };
1080 
1081 public:
1084  RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
1085  : Dir(Path.str()), Current(Begin), End(End) {
1086  EC = incrementImpl(/*IsFirstTime=*/true);
1087  }
1088 
1089  std::error_code increment() override {
1090  return incrementImpl(/*IsFirstTime=*/false);
1091  }
1092 };
1093 
1094 /// Directory iterator implementation for \c RedirectingFileSystem's
1095 /// directory remap entries that maps the paths reported by the external
1096 /// file system's directory iterator back to the virtual directory's path.
1098  std::string Dir;
1099  llvm::sys::path::Style DirStyle;
1100  llvm::vfs::directory_iterator ExternalIter;
1101 
1102 public:
1103  RedirectingFSDirRemapIterImpl(std::string DirPath,
1105  : Dir(std::move(DirPath)), DirStyle(getExistingStyle(Dir)),
1106  ExternalIter(ExtIter) {
1107  if (ExternalIter != llvm::vfs::directory_iterator())
1108  setCurrentEntry();
1109  }
1110 
1112  StringRef ExternalPath = ExternalIter->path();
1113  llvm::sys::path::Style ExternalStyle = getExistingStyle(ExternalPath);
1114  StringRef File = llvm::sys::path::filename(ExternalPath, ExternalStyle);
1115 
1116  SmallString<128> NewPath(Dir);
1117  llvm::sys::path::append(NewPath, DirStyle, File);
1118 
1119  CurrentEntry = directory_entry(std::string(NewPath), ExternalIter->type());
1120  }
1121 
1122  std::error_code increment() override {
1123  std::error_code EC;
1124  ExternalIter.increment(EC);
1125  if (!EC && ExternalIter != llvm::vfs::directory_iterator())
1126  setCurrentEntry();
1127  else
1128  CurrentEntry = directory_entry();
1129  return EC;
1130  }
1131 };
1132 
1135  return WorkingDirectory;
1136 }
1137 
1138 std::error_code
1140  // Don't change the working directory if the path doesn't exist.
1141  if (!exists(Path))
1143 
1144  SmallString<128> AbsolutePath;
1145  Path.toVector(AbsolutePath);
1146  if (std::error_code EC = makeAbsolute(AbsolutePath))
1147  return EC;
1148  WorkingDirectory = std::string(AbsolutePath.str());
1149  return {};
1150 }
1151 
1152 std::error_code RedirectingFileSystem::isLocal(const Twine &Path_,
1153  bool &Result) {
1154  SmallString<256> Path;
1155  Path_.toVector(Path);
1156 
1157  if (std::error_code EC = makeCanonical(Path))
1158  return {};
1159 
1160  return ExternalFS->isLocal(Path, Result);
1161 }
1162 
1166  return {};
1167 
1168  auto WorkingDir = getCurrentWorkingDirectory();
1169  if (!WorkingDir)
1170  return WorkingDir.getError();
1171 
1172  // We can't use sys::fs::make_absolute because that assumes the path style
1173  // is native and there is no way to override that. Since we know WorkingDir
1174  // is absolute, we can use it to determine which style we actually have and
1175  // append Path ourselves.
1177  if (sys::path::is_absolute(WorkingDir.get(), sys::path::Style::posix)) {
1178  style = sys::path::Style::posix;
1179  }
1180 
1181  std::string Result = WorkingDir.get();
1182  StringRef Dir(Result);
1183  if (!Dir.endswith(sys::path::get_separator(style))) {
1184  Result += sys::path::get_separator(style);
1185  }
1186  Result.append(Path.data(), Path.size());
1187  Path.assign(Result.begin(), Result.end());
1188 
1189  return {};
1190 }
1191 
1193  std::error_code &EC) {
1194  SmallString<256> Path;
1195  Dir.toVector(Path);
1196 
1197  EC = makeCanonical(Path);
1198  if (EC)
1199  return {};
1200 
1202  if (!Result) {
1203  EC = Result.getError();
1204  if (shouldFallBackToExternalFS(EC))
1205  return ExternalFS->dir_begin(Path, EC);
1206  return {};
1207  }
1208 
1209  // Use status to make sure the path exists and refers to a directory.
1210  ErrorOr<Status> S = status(Path, *Result);
1211  if (!S) {
1212  if (shouldFallBackToExternalFS(S.getError(), Result->E))
1213  return ExternalFS->dir_begin(Dir, EC);
1214  EC = S.getError();
1215  return {};
1216  }
1217  if (!S->isDirectory()) {
1218  EC = std::error_code(static_cast<int>(errc::not_a_directory),
1219  std::system_category());
1220  return {};
1221  }
1222 
1223  // Create the appropriate directory iterator based on whether we found a
1224  // DirectoryRemapEntry or DirectoryEntry.
1225  directory_iterator DirIter;
1226  if (auto ExtRedirect = Result->getExternalRedirect()) {
1227  auto RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
1228  DirIter = ExternalFS->dir_begin(*ExtRedirect, EC);
1229 
1230  if (!RE->useExternalName(UseExternalNames)) {
1231  // Update the paths in the results to use the virtual directory's path.
1232  DirIter =
1233  directory_iterator(std::make_shared<RedirectingFSDirRemapIterImpl>(
1234  std::string(Path), DirIter));
1235  }
1236  } else {
1237  auto DE = cast<DirectoryEntry>(Result->E);
1238  DirIter = directory_iterator(std::make_shared<RedirectingFSDirIterImpl>(
1239  Path, DE->contents_begin(), DE->contents_end(), EC));
1240  }
1241 
1242  if (!shouldUseExternalFS())
1243  return DirIter;
1244  return directory_iterator(std::make_shared<CombiningDirIterImpl>(
1245  DirIter, ExternalFS, std::string(Path), EC));
1246 }
1247 
1249  ExternalContentsPrefixDir = PrefixDir.str();
1250 }
1251 
1253  return ExternalContentsPrefixDir;
1254 }
1255 
1257  IsFallthrough = Fallthrough;
1258 }
1259 
1260 std::vector<StringRef> RedirectingFileSystem::getRoots() const {
1261  std::vector<StringRef> R;
1262  for (const auto &Root : Roots)
1263  R.push_back(Root->getName());
1264  return R;
1265 }
1266 
1268  for (const auto &Root : Roots)
1269  dumpEntry(OS, Root.get());
1270 }
1271 
1274  int NumSpaces) const {
1275  StringRef Name = E->getName();
1276  for (int i = 0, e = NumSpaces; i < e; ++i)
1277  OS << " ";
1278  OS << "'" << Name.str().c_str() << "'"
1279  << "\n";
1280 
1281  if (E->getKind() == RedirectingFileSystem::EK_Directory) {
1282  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(E);
1283  assert(DE && "Should be a directory");
1284 
1285  for (std::unique_ptr<Entry> &SubEntry :
1286  llvm::make_range(DE->contents_begin(), DE->contents_end()))
1287  dumpEntry(OS, SubEntry.get(), NumSpaces + 2);
1288  }
1289 }
1290 
1291 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1293 #endif
1294 
1295 /// A helper class to hold the common YAML parsing state.
1297  yaml::Stream &Stream;
1298 
1299  void error(yaml::Node *N, const Twine &Msg) { Stream.printError(N, Msg); }
1300 
1301  // false on error
1302  bool parseScalarString(yaml::Node *N, StringRef &Result,
1303  SmallVectorImpl<char> &Storage) {
1304  const auto *S = dyn_cast<yaml::ScalarNode>(N);
1305 
1306  if (!S) {
1307  error(N, "expected string");
1308  return false;
1309  }
1310  Result = S->getValue(Storage);
1311  return true;
1312  }
1313 
1314  // false on error
1315  bool parseScalarBool(yaml::Node *N, bool &Result) {
1316  SmallString<5> Storage;
1317  StringRef Value;
1318  if (!parseScalarString(N, Value, Storage))
1319  return false;
1320 
1321  if (Value.equals_insensitive("true") || Value.equals_insensitive("on") ||
1322  Value.equals_insensitive("yes") || Value == "1") {
1323  Result = true;
1324  return true;
1325  } else if (Value.equals_insensitive("false") ||
1326  Value.equals_insensitive("off") ||
1327  Value.equals_insensitive("no") || Value == "0") {
1328  Result = false;
1329  return true;
1330  }
1331 
1332  error(N, "expected boolean value");
1333  return false;
1334  }
1335 
1336  struct KeyStatus {
1337  bool Required;
1338  bool Seen = false;
1339 
1340  KeyStatus(bool Required = false) : Required(Required) {}
1341  };
1342 
1343  using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1344 
1345  // false on error
1346  bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
1348  if (!Keys.count(Key)) {
1349  error(KeyNode, "unknown key");
1350  return false;
1351  }
1352  KeyStatus &S = Keys[Key];
1353  if (S.Seen) {
1354  error(KeyNode, Twine("duplicate key '") + Key + "'");
1355  return false;
1356  }
1357  S.Seen = true;
1358  return true;
1359  }
1360 
1361  // false on error
1362  bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
1363  for (const auto &I : Keys) {
1364  if (I.second.Required && !I.second.Seen) {
1365  error(Obj, Twine("missing key '") + I.first + "'");
1366  return false;
1367  }
1368  }
1369  return true;
1370  }
1371 
1372 public:
1375  RedirectingFileSystem::Entry *ParentEntry = nullptr) {
1376  if (!ParentEntry) { // Look for a existent root
1377  for (const auto &Root : FS->Roots) {
1378  if (Name.equals(Root->getName())) {
1379  ParentEntry = Root.get();
1380  return ParentEntry;
1381  }
1382  }
1383  } else { // Advance to the next component
1384  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1385  for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
1386  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1387  auto *DirContent =
1388  dyn_cast<RedirectingFileSystem::DirectoryEntry>(Content.get());
1389  if (DirContent && Name.equals(Content->getName()))
1390  return DirContent;
1391  }
1392  }
1393 
1394  // ... or create a new one
1395  std::unique_ptr<RedirectingFileSystem::Entry> E =
1396  std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1398  std::chrono::system_clock::now(), 0, 0, 0,
1399  file_type::directory_file, sys::fs::all_all));
1400 
1401  if (!ParentEntry) { // Add a new root to the overlay
1402  FS->Roots.push_back(std::move(E));
1403  ParentEntry = FS->Roots.back().get();
1404  return ParentEntry;
1405  }
1406 
1407  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1408  DE->addContent(std::move(E));
1409  return DE->getLastContent();
1410  }
1411 
1412 private:
1413  void uniqueOverlayTree(RedirectingFileSystem *FS,
1415  RedirectingFileSystem::Entry *NewParentE = nullptr) {
1416  StringRef Name = SrcE->getName();
1417  switch (SrcE->getKind()) {
1419  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
1420  // Empty directories could be present in the YAML as a way to
1421  // describe a file for a current directory after some of its subdir
1422  // is parsed. This only leads to redundant walks, ignore it.
1423  if (!Name.empty())
1424  NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
1425  for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1426  llvm::make_range(DE->contents_begin(), DE->contents_end()))
1427  uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1428  break;
1429  }
1431  assert(NewParentE && "Parent entry must exist");
1432  auto *DR = cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
1433  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1434  DE->addContent(
1435  std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1436  Name, DR->getExternalContentsPath(), DR->getUseName()));
1437  break;
1438  }
1440  assert(NewParentE && "Parent entry must exist");
1441  auto *FE = cast<RedirectingFileSystem::FileEntry>(SrcE);
1442  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1443  DE->addContent(std::make_unique<RedirectingFileSystem::FileEntry>(
1444  Name, FE->getExternalContentsPath(), FE->getUseName()));
1445  break;
1446  }
1447  }
1448  }
1449 
1450  std::unique_ptr<RedirectingFileSystem::Entry>
1451  parseEntry(yaml::Node *N, RedirectingFileSystem *FS, bool IsRootEntry) {
1452  auto *M = dyn_cast<yaml::MappingNode>(N);
1453  if (!M) {
1454  error(N, "expected mapping node for file or directory entry");
1455  return nullptr;
1456  }
1457 
1458  KeyStatusPair Fields[] = {
1459  KeyStatusPair("name", true),
1460  KeyStatusPair("type", true),
1461  KeyStatusPair("contents", false),
1462  KeyStatusPair("external-contents", false),
1463  KeyStatusPair("use-external-name", false),
1464  };
1465 
1466  DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1467 
1468  enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1469  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1470  EntryArrayContents;
1471  SmallString<256> ExternalContentsPath;
1473  yaml::Node *NameValueNode = nullptr;
1474  auto UseExternalName = RedirectingFileSystem::NK_NotSet;
1476 
1477  for (auto &I : *M) {
1478  StringRef Key;
1479  // Reuse the buffer for key and value, since we don't look at key after
1480  // parsing value.
1481  SmallString<256> Buffer;
1482  if (!parseScalarString(I.getKey(), Key, Buffer))
1483  return nullptr;
1484 
1485  if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1486  return nullptr;
1487 
1488  StringRef Value;
1489  if (Key == "name") {
1490  if (!parseScalarString(I.getValue(), Value, Buffer))
1491  return nullptr;
1492 
1493  NameValueNode = I.getValue();
1494  // Guarantee that old YAML files containing paths with ".." and "."
1495  // are properly canonicalized before read into the VFS.
1496  Name = canonicalize(Value).str();
1497  } else if (Key == "type") {
1498  if (!parseScalarString(I.getValue(), Value, Buffer))
1499  return nullptr;
1500  if (Value == "file")
1502  else if (Value == "directory")
1504  else if (Value == "directory-remap")
1506  else {
1507  error(I.getValue(), "unknown value for 'type'");
1508  return nullptr;
1509  }
1510  } else if (Key == "contents") {
1511  if (ContentsField != CF_NotSet) {
1512  error(I.getKey(),
1513  "entry already has 'contents' or 'external-contents'");
1514  return nullptr;
1515  }
1516  ContentsField = CF_List;
1517  auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
1518  if (!Contents) {
1519  // FIXME: this is only for directories, what about files?
1520  error(I.getValue(), "expected array");
1521  return nullptr;
1522  }
1523 
1524  for (auto &I : *Contents) {
1525  if (std::unique_ptr<RedirectingFileSystem::Entry> E =
1526  parseEntry(&I, FS, /*IsRootEntry*/ false))
1527  EntryArrayContents.push_back(std::move(E));
1528  else
1529  return nullptr;
1530  }
1531  } else if (Key == "external-contents") {
1532  if (ContentsField != CF_NotSet) {
1533  error(I.getKey(),
1534  "entry already has 'contents' or 'external-contents'");
1535  return nullptr;
1536  }
1537  ContentsField = CF_External;
1538  if (!parseScalarString(I.getValue(), Value, Buffer))
1539  return nullptr;
1540 
1541  SmallString<256> FullPath;
1542  if (FS->IsRelativeOverlay) {
1543  FullPath = FS->getExternalContentsPrefixDir();
1544  assert(!FullPath.empty() &&
1545  "External contents prefix directory must exist");
1546  llvm::sys::path::append(FullPath, Value);
1547  } else {
1548  FullPath = Value;
1549  }
1550 
1551  // Guarantee that old YAML files containing paths with ".." and "."
1552  // are properly canonicalized before read into the VFS.
1553  FullPath = canonicalize(FullPath);
1554  ExternalContentsPath = FullPath.str();
1555  } else if (Key == "use-external-name") {
1556  bool Val;
1557  if (!parseScalarBool(I.getValue(), Val))
1558  return nullptr;
1559  UseExternalName = Val ? RedirectingFileSystem::NK_External
1561  } else {
1562  llvm_unreachable("key missing from Keys");
1563  }
1564  }
1565 
1566  if (Stream.failed())
1567  return nullptr;
1568 
1569  // check for missing keys
1570  if (ContentsField == CF_NotSet) {
1571  error(N, "missing key 'contents' or 'external-contents'");
1572  return nullptr;
1573  }
1574  if (!checkMissingKeys(N, Keys))
1575  return nullptr;
1576 
1577  // check invalid configuration
1579  UseExternalName != RedirectingFileSystem::NK_NotSet) {
1580  error(N, "'use-external-name' is not supported for 'directory' entries");
1581  return nullptr;
1582  }
1583 
1585  ContentsField == CF_List) {
1586  error(N, "'contents' is not supported for 'directory-remap' entries");
1587  return nullptr;
1588  }
1589 
1591  if (IsRootEntry) {
1592  // VFS root entries may be in either Posix or Windows style. Figure out
1593  // which style we have, and use it consistently.
1595  path_style = sys::path::Style::posix;
1597  path_style = sys::path::Style::windows;
1598  } else {
1599  assert(NameValueNode && "Name presence should be checked earlier");
1600  error(NameValueNode,
1601  "entry with relative path at the root level is not discoverable");
1602  return nullptr;
1603  }
1604  }
1605 
1606  // Remove trailing slash(es), being careful not to remove the root path
1607  StringRef Trimmed = Name;
1608  size_t RootPathLen = sys::path::root_path(Trimmed, path_style).size();
1609  while (Trimmed.size() > RootPathLen &&
1610  sys::path::is_separator(Trimmed.back(), path_style))
1611  Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
1612 
1613  // Get the last component
1614  StringRef LastComponent = sys::path::filename(Trimmed, path_style);
1615 
1616  std::unique_ptr<RedirectingFileSystem::Entry> Result;
1617  switch (Kind) {
1619  Result = std::make_unique<RedirectingFileSystem::FileEntry>(
1620  LastComponent, std::move(ExternalContentsPath), UseExternalName);
1621  break;
1623  Result = std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1624  LastComponent, std::move(ExternalContentsPath), UseExternalName);
1625  break;
1627  Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1628  LastComponent, std::move(EntryArrayContents),
1630  0, 0, 0, file_type::directory_file, sys::fs::all_all));
1631  break;
1632  }
1633 
1634  StringRef Parent = sys::path::parent_path(Trimmed, path_style);
1635  if (Parent.empty())
1636  return Result;
1637 
1638  // if 'name' contains multiple components, create implicit directory entries
1639  for (sys::path::reverse_iterator I = sys::path::rbegin(Parent, path_style),
1640  E = sys::path::rend(Parent);
1641  I != E; ++I) {
1642  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
1643  Entries.push_back(std::move(Result));
1644  Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1645  *I, std::move(Entries),
1647  0, 0, 0, file_type::directory_file, sys::fs::all_all));
1648  }
1649  return Result;
1650  }
1651 
1652 public:
1654 
1655  // false on error
1657  auto *Top = dyn_cast<yaml::MappingNode>(Root);
1658  if (!Top) {
1659  error(Root, "expected mapping node");
1660  return false;
1661  }
1662 
1663  KeyStatusPair Fields[] = {
1664  KeyStatusPair("version", true),
1665  KeyStatusPair("case-sensitive", false),
1666  KeyStatusPair("use-external-names", false),
1667  KeyStatusPair("overlay-relative", false),
1668  KeyStatusPair("fallthrough", false),
1669  KeyStatusPair("roots", true),
1670  };
1671 
1672  DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1673  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
1674 
1675  // Parse configuration and 'roots'
1676  for (auto &I : *Top) {
1677  SmallString<10> KeyBuffer;
1678  StringRef Key;
1679  if (!parseScalarString(I.getKey(), Key, KeyBuffer))
1680  return false;
1681 
1682  if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1683  return false;
1684 
1685  if (Key == "roots") {
1686  auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
1687  if (!Roots) {
1688  error(I.getValue(), "expected array");
1689  return false;
1690  }
1691 
1692  for (auto &I : *Roots) {
1693  if (std::unique_ptr<RedirectingFileSystem::Entry> E =
1694  parseEntry(&I, FS, /*IsRootEntry*/ true))
1695  RootEntries.push_back(std::move(E));
1696  else
1697  return false;
1698  }
1699  } else if (Key == "version") {
1700  StringRef VersionString;
1701  SmallString<4> Storage;
1702  if (!parseScalarString(I.getValue(), VersionString, Storage))
1703  return false;
1704  int Version;
1705  if (VersionString.getAsInteger<int>(10, Version)) {
1706  error(I.getValue(), "expected integer");
1707  return false;
1708  }
1709  if (Version < 0) {
1710  error(I.getValue(), "invalid version number");
1711  return false;
1712  }
1713  if (Version != 0) {
1714  error(I.getValue(), "version mismatch, expected 0");
1715  return false;
1716  }
1717  } else if (Key == "case-sensitive") {
1718  if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
1719  return false;
1720  } else if (Key == "overlay-relative") {
1721  if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
1722  return false;
1723  } else if (Key == "use-external-names") {
1724  if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
1725  return false;
1726  } else if (Key == "fallthrough") {
1727  if (!parseScalarBool(I.getValue(), FS->IsFallthrough))
1728  return false;
1729  } else {
1730  llvm_unreachable("key missing from Keys");
1731  }
1732  }
1733 
1734  if (Stream.failed())
1735  return false;
1736 
1737  if (!checkMissingKeys(Top, Keys))
1738  return false;
1739 
1740  // Now that we sucessefully parsed the YAML file, canonicalize the internal
1741  // representation to a proper directory tree so that we can search faster
1742  // inside the VFS.
1743  for (auto &E : RootEntries)
1744  uniqueOverlayTree(FS, E.get());
1745 
1746  return true;
1747  }
1748 };
1749 
1750 std::unique_ptr<RedirectingFileSystem>
1751 RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
1753  StringRef YAMLFilePath, void *DiagContext,
1754  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
1755  SourceMgr SM;
1756  yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
1757 
1758  SM.setDiagHandler(DiagHandler, DiagContext);
1759  yaml::document_iterator DI = Stream.begin();
1760  yaml::Node *Root = DI->getRoot();
1761  if (DI == Stream.end() || !Root) {
1762  SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
1763  return nullptr;
1764  }
1765 
1767 
1768  std::unique_ptr<RedirectingFileSystem> FS(
1769  new RedirectingFileSystem(ExternalFS));
1770 
1771  if (!YAMLFilePath.empty()) {
1772  // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
1773  // to each 'external-contents' path.
1774  //
1775  // Example:
1776  // -ivfsoverlay dummy.cache/vfs/vfs.yaml
1777  // yields:
1778  // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
1779  //
1780  SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
1781  std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
1782  assert(!EC && "Overlay dir final path must be absolute");
1783  (void)EC;
1784  FS->setExternalContentsPrefixDir(OverlayAbsDir);
1785  }
1786 
1787  if (!P.parse(Root, FS.get()))
1788  return nullptr;
1789 
1790  return FS;
1791 }
1792 
1793 std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create(
1794  ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1795  bool UseExternalNames, FileSystem &ExternalFS) {
1796  std::unique_ptr<RedirectingFileSystem> FS(
1797  new RedirectingFileSystem(&ExternalFS));
1798  FS->UseExternalNames = UseExternalNames;
1799 
1801 
1802  for (auto &Mapping : llvm::reverse(RemappedFiles)) {
1803  SmallString<128> From = StringRef(Mapping.first);
1804  SmallString<128> To = StringRef(Mapping.second);
1805  {
1806  auto EC = ExternalFS.makeAbsolute(From);
1807  (void)EC;
1808  assert(!EC && "Could not make absolute path");
1809  }
1810 
1811  // Check if we've already mapped this file. The first one we see (in the
1812  // reverse iteration) wins.
1813  RedirectingFileSystem::Entry *&ToEntry = Entries[From];
1814  if (ToEntry)
1815  continue;
1816 
1817  // Add parent directories.
1818  RedirectingFileSystem::Entry *Parent = nullptr;
1819  StringRef FromDirectory = llvm::sys::path::parent_path(From);
1820  for (auto I = llvm::sys::path::begin(FromDirectory),
1821  E = llvm::sys::path::end(FromDirectory);
1822  I != E; ++I) {
1824  Parent);
1825  }
1826  assert(Parent && "File without a directory?");
1827  {
1828  auto EC = ExternalFS.makeAbsolute(To);
1829  (void)EC;
1830  assert(!EC && "Could not make absolute path");
1831  }
1832 
1833  // Add the file.
1834  auto NewFile = std::make_unique<RedirectingFileSystem::FileEntry>(
1836  UseExternalNames ? RedirectingFileSystem::NK_External
1838  ToEntry = NewFile.get();
1839  cast<RedirectingFileSystem::DirectoryEntry>(Parent)->addContent(
1840  std::move(NewFile));
1841  }
1842 
1843  return FS;
1844 }
1845 
1848  : E(E) {
1849  assert(E != nullptr);
1850  // If the matched entry is a DirectoryRemapEntry, set ExternalRedirect to the
1851  // path of the directory it maps to in the external file system plus any
1852  // remaining path components in the provided iterator.
1853  if (auto *DRE = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(E)) {
1854  SmallString<256> Redirect(DRE->getExternalContentsPath());
1855  sys::path::append(Redirect, Start, End,
1856  getExistingStyle(DRE->getExternalContentsPath()));
1857  ExternalRedirect = std::string(Redirect);
1858  }
1859 }
1860 
1861 bool RedirectingFileSystem::shouldFallBackToExternalFS(
1862  std::error_code EC, RedirectingFileSystem::Entry *E) const {
1863  if (E && !isa<RedirectingFileSystem::DirectoryRemapEntry>(E))
1864  return false;
1865  return shouldUseExternalFS() && EC == llvm::errc::no_such_file_or_directory;
1866 }
1867 
1868 std::error_code
1869 RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {
1870  if (std::error_code EC = makeAbsolute(Path))
1871  return EC;
1872 
1873  llvm::SmallString<256> CanonicalPath =
1874  canonicalize(StringRef(Path.data(), Path.size()));
1875  if (CanonicalPath.empty())
1877 
1878  Path.assign(CanonicalPath.begin(), CanonicalPath.end());
1879  return {};
1880 }
1881 
1886  for (const auto &Root : Roots) {
1888  lookupPathImpl(Start, End, Root.get());
1889  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
1890  return Result;
1891  }
1893 }
1894 
1896 RedirectingFileSystem::lookupPathImpl(
1899  assert(!isTraversalComponent(*Start) &&
1900  !isTraversalComponent(From->getName()) &&
1901  "Paths should not contain traversal components");
1902 
1903  StringRef FromName = From->getName();
1904 
1905  // Forward the search to the next component in case this is an empty one.
1906  if (!FromName.empty()) {
1907  if (!pathComponentMatches(*Start, FromName))
1909 
1910  ++Start;
1911 
1912  if (Start == End) {
1913  // Match!
1914  return LookupResult(From, Start, End);
1915  }
1916  }
1917 
1918  if (isa<RedirectingFileSystem::FileEntry>(From))
1920 
1921  if (isa<RedirectingFileSystem::DirectoryRemapEntry>(From))
1922  return LookupResult(From, Start, End);
1923 
1924  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(From);
1925  for (const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
1926  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1928  lookupPathImpl(Start, End, DirEntry.get());
1929  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
1930  return Result;
1931  }
1932 
1934 }
1935 
1936 static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
1937  Status ExternalStatus) {
1938  Status S = ExternalStatus;
1939  if (!UseExternalNames)
1940  S = Status::copyWithNewName(S, Path);
1941  S.IsVFSMapped = true;
1942  return S;
1943 }
1944 
1945 ErrorOr<Status> RedirectingFileSystem::status(
1946  const Twine &Path, const RedirectingFileSystem::LookupResult &Result) {
1947  if (Optional<StringRef> ExtRedirect = Result.getExternalRedirect()) {
1948  ErrorOr<Status> S = ExternalFS->status(*ExtRedirect);
1949  if (!S)
1950  return S;
1951  auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result.E);
1952  return getRedirectedFileStatus(Path, RE->useExternalName(UseExternalNames),
1953  *S);
1954  }
1955 
1956  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E);
1957  return Status::copyWithNewName(DE->getStatus(), Path);
1958 }
1959 
1960 ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path_) {
1961  SmallString<256> Path;
1962  Path_.toVector(Path);
1963 
1964  if (std::error_code EC = makeCanonical(Path))
1965  return EC;
1966 
1968  if (!Result) {
1969  if (shouldFallBackToExternalFS(Result.getError()))
1970  return ExternalFS->status(Path);
1971  return Result.getError();
1972  }
1973 
1974  ErrorOr<Status> S = status(Path, *Result);
1975  if (!S && shouldFallBackToExternalFS(S.getError(), Result->E))
1976  S = ExternalFS->status(Path);
1977  return S;
1978 }
1979 
1980 namespace {
1981 
1982 /// Provide a file wrapper with an overriden status.
1983 class FileWithFixedStatus : public File {
1984  std::unique_ptr<File> InnerFile;
1985  Status S;
1986 
1987 public:
1988  FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
1989  : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
1990 
1991  ErrorOr<Status> status() override { return S; }
1993 
1994  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
1995  bool IsVolatile) override {
1996  return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
1997  IsVolatile);
1998  }
1999 
2000  std::error_code close() override { return InnerFile->close(); }
2001 };
2002 
2003 } // namespace
2004 
2007  SmallString<256> Path;
2008  Path_.toVector(Path);
2009 
2010  if (std::error_code EC = makeCanonical(Path))
2011  return EC;
2012 
2014  if (!Result) {
2015  if (shouldFallBackToExternalFS(Result.getError()))
2016  return ExternalFS->openFileForRead(Path);
2017  return Result.getError();
2018  }
2019 
2020  if (!Result->getExternalRedirect()) // FIXME: errc::not_a_file?
2022 
2023  StringRef ExtRedirect = *Result->getExternalRedirect();
2024  auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
2025 
2026  auto ExternalFile = ExternalFS->openFileForRead(ExtRedirect);
2027  if (!ExternalFile) {
2028  if (shouldFallBackToExternalFS(ExternalFile.getError(), Result->E))
2029  return ExternalFS->openFileForRead(Path);
2030  return ExternalFile;
2031  }
2032 
2033  auto ExternalStatus = (*ExternalFile)->status();
2034  if (!ExternalStatus)
2035  return ExternalStatus.getError();
2036 
2037  // FIXME: Update the status with the name and VFSMapped.
2039  Path, RE->useExternalName(UseExternalNames), *ExternalStatus);
2040  return std::unique_ptr<File>(
2041  std::make_unique<FileWithFixedStatus>(std::move(*ExternalFile), S));
2042 }
2043 
2044 std::error_code
2046  SmallVectorImpl<char> &Output) const {
2047  SmallString<256> Path;
2048  Path_.toVector(Path);
2049 
2050  if (std::error_code EC = makeCanonical(Path))
2051  return EC;
2052 
2054  if (!Result) {
2055  if (shouldFallBackToExternalFS(Result.getError()))
2056  return ExternalFS->getRealPath(Path, Output);
2057  return Result.getError();
2058  }
2059 
2060  // If we found FileEntry or DirectoryRemapEntry, look up the mapped
2061  // path in the external file system.
2062  if (auto ExtRedirect = Result->getExternalRedirect()) {
2063  auto P = ExternalFS->getRealPath(*ExtRedirect, Output);
2064  if (!P && shouldFallBackToExternalFS(P, Result->E)) {
2065  return ExternalFS->getRealPath(Path, Output);
2066  }
2067  return P;
2068  }
2069 
2070  // If we found a DirectoryEntry, still fall back to ExternalFS if allowed,
2071  // because directories don't have a single external contents path.
2072  return shouldUseExternalFS() ? ExternalFS->getRealPath(Path, Output)
2074 }
2075 
2076 std::unique_ptr<FileSystem>
2077 vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2079  StringRef YAMLFilePath, void *DiagContext,
2080  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2082  YAMLFilePath, DiagContext,
2083  std::move(ExternalFS));
2084 }
2085 
2088  SmallVectorImpl<YAMLVFSEntry> &Entries) {
2089  auto Kind = SrcE->getKind();
2091  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
2092  assert(DE && "Must be a directory");
2093  for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
2094  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2095  Path.push_back(SubEntry->getName());
2096  getVFSEntries(SubEntry.get(), Path, Entries);
2097  Path.pop_back();
2098  }
2099  return;
2100  }
2101 
2103  auto *DR = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
2104  assert(DR && "Must be a directory remap");
2105  SmallString<128> VPath;
2106  for (auto &Comp : Path)
2107  llvm::sys::path::append(VPath, Comp);
2108  Entries.push_back(
2109  YAMLVFSEntry(VPath.c_str(), DR->getExternalContentsPath()));
2110  return;
2111  }
2112 
2113  assert(Kind == RedirectingFileSystem::EK_File && "Must be a EK_File");
2114  auto *FE = dyn_cast<RedirectingFileSystem::FileEntry>(SrcE);
2115  assert(FE && "Must be a file");
2116  SmallString<128> VPath;
2117  for (auto &Comp : Path)
2118  llvm::sys::path::append(VPath, Comp);
2119  Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
2120 }
2121 
2122 void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2124  StringRef YAMLFilePath,
2125  SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
2126  void *DiagContext,
2127  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2128  std::unique_ptr<RedirectingFileSystem> VFS = RedirectingFileSystem::create(
2129  std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
2130  std::move(ExternalFS));
2131  if (!VFS)
2132  return;
2134  VFS->lookupPath("/");
2135  if (!RootResult)
2136  return;
2137  SmallVector<StringRef, 8> Components;
2138  Components.push_back("/");
2139  getVFSEntries(RootResult->E, Components, CollectedEntries);
2140 }
2141 
2143  static std::atomic<unsigned> UID;
2144  unsigned ID = ++UID;
2145  // The following assumes that uint64_t max will never collide with a real
2146  // dev_t value from the OS.
2148 }
2149 
2150 void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,
2151  bool IsDirectory) {
2152  assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
2153  assert(sys::path::is_absolute(RealPath) && "real path not absolute");
2154  assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
2155  Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2156 }
2157 
2159  addEntry(VirtualPath, RealPath, /*IsDirectory=*/false);
2160 }
2161 
2163  StringRef RealPath) {
2164  addEntry(VirtualPath, RealPath, /*IsDirectory=*/true);
2165 }
2166 
2167 namespace {
2168 
2169 class JSONWriter {
2170  llvm::raw_ostream &OS;
2171  SmallVector<StringRef, 16> DirStack;
2172 
2173  unsigned getDirIndent() { return 4 * DirStack.size(); }
2174  unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
2175  bool containedIn(StringRef Parent, StringRef Path);
2176  StringRef containedPart(StringRef Parent, StringRef Path);
2177  void startDirectory(StringRef Path);
2178  void endDirectory();
2179  void writeEntry(StringRef VPath, StringRef RPath);
2180 
2181 public:
2182  JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
2183 
2184  void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
2185  Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
2186  StringRef OverlayDir);
2187 };
2188 
2189 } // namespace
2190 
2191 bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
2192  using namespace llvm::sys;
2193 
2194  // Compare each path component.
2195  auto IParent = path::begin(Parent), EParent = path::end(Parent);
2196  for (auto IChild = path::begin(Path), EChild = path::end(Path);
2197  IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2198  if (*IParent != *IChild)
2199  return false;
2200  }
2201  // Have we exhausted the parent path?
2202  return IParent == EParent;
2203 }
2204 
2205 StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
2206  assert(!Parent.empty());
2207  assert(containedIn(Parent, Path));
2208  return Path.slice(Parent.size() + 1, StringRef::npos);
2209 }
2210 
2211 void JSONWriter::startDirectory(StringRef Path) {
2212  StringRef Name =
2213  DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
2214  DirStack.push_back(Path);
2215  unsigned Indent = getDirIndent();
2216  OS.indent(Indent) << "{\n";
2217  OS.indent(Indent + 2) << "'type': 'directory',\n";
2218  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
2219  OS.indent(Indent + 2) << "'contents': [\n";
2220 }
2221 
2222 void JSONWriter::endDirectory() {
2223  unsigned Indent = getDirIndent();
2224  OS.indent(Indent + 2) << "]\n";
2225  OS.indent(Indent) << "}";
2226 
2227  DirStack.pop_back();
2228 }
2229 
2230 void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
2231  unsigned Indent = getFileIndent();
2232  OS.indent(Indent) << "{\n";
2233  OS.indent(Indent + 2) << "'type': 'file',\n";
2234  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
2235  OS.indent(Indent + 2) << "'external-contents': \""
2236  << llvm::yaml::escape(RPath) << "\"\n";
2237  OS.indent(Indent) << "}";
2238 }
2239 
2241  Optional<bool> UseExternalNames,
2242  Optional<bool> IsCaseSensitive,
2243  Optional<bool> IsOverlayRelative,
2244  StringRef OverlayDir) {
2245  using namespace llvm::sys;
2246 
2247  OS << "{\n"
2248  " 'version': 0,\n";
2249  if (IsCaseSensitive.hasValue())
2250  OS << " 'case-sensitive': '"
2251  << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
2252  if (UseExternalNames.hasValue())
2253  OS << " 'use-external-names': '"
2254  << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
2255  bool UseOverlayRelative = false;
2256  if (IsOverlayRelative.hasValue()) {
2257  UseOverlayRelative = IsOverlayRelative.getValue();
2258  OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
2259  << "',\n";
2260  }
2261  OS << " 'roots': [\n";
2262 
2263  if (!Entries.empty()) {
2264  const YAMLVFSEntry &Entry = Entries.front();
2265 
2266  startDirectory(
2267  Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath)
2268  );
2269 
2270  StringRef RPath = Entry.RPath;
2271  if (UseOverlayRelative) {
2272  unsigned OverlayDirLen = OverlayDir.size();
2273  assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
2274  "Overlay dir must be contained in RPath");
2275  RPath = RPath.slice(OverlayDirLen, RPath.size());
2276  }
2277 
2278  bool IsCurrentDirEmpty = true;
2279  if (!Entry.IsDirectory) {
2280  writeEntry(path::filename(Entry.VPath), RPath);
2281  IsCurrentDirEmpty = false;
2282  }
2283 
2284  for (const auto &Entry : Entries.slice(1)) {
2285  StringRef Dir =
2286  Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath);
2287  if (Dir == DirStack.back()) {
2288  if (!IsCurrentDirEmpty) {
2289  OS << ",\n";
2290  }
2291  } else {
2292  bool IsDirPoppedFromStack = false;
2293  while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
2294  OS << "\n";
2295  endDirectory();
2296  IsDirPoppedFromStack = true;
2297  }
2298  if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2299  OS << ",\n";
2300  }
2301  startDirectory(Dir);
2302  IsCurrentDirEmpty = true;
2303  }
2304  StringRef RPath = Entry.RPath;
2305  if (UseOverlayRelative) {
2306  unsigned OverlayDirLen = OverlayDir.size();
2307  assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
2308  "Overlay dir must be contained in RPath");
2309  RPath = RPath.slice(OverlayDirLen, RPath.size());
2310  }
2311  if (!Entry.IsDirectory) {
2312  writeEntry(path::filename(Entry.VPath), RPath);
2313  IsCurrentDirEmpty = false;
2314  }
2315  }
2316 
2317  while (!DirStack.empty()) {
2318  OS << "\n";
2319  endDirectory();
2320  }
2321  OS << "\n";
2322  }
2323 
2324  OS << " ]\n"
2325  << "}\n";
2326 }
2327 
2329  llvm::sort(Mappings, [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
2330  return LHS.VPath < RHS.VPath;
2331  });
2332 
2333  JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
2334  IsOverlayRelative, OverlayDir);
2335 }
2336 
2338  FileSystem &FS_, const Twine &Path, std::error_code &EC)
2339  : FS(&FS_) {
2340  directory_iterator I = FS->dir_begin(Path, EC);
2341  if (I != directory_iterator()) {
2342  State = std::make_shared<detail::RecDirIterState>();
2343  State->Stack.push(I);
2344  }
2345 }
2346 
2349  assert(FS && State && !State->Stack.empty() && "incrementing past end");
2350  assert(!State->Stack.top()->path().empty() && "non-canonical end iterator");
2352 
2353  if (State->HasNoPushRequest)
2354  State->HasNoPushRequest = false;
2355  else {
2356  if (State->Stack.top()->type() == sys::fs::file_type::directory_file) {
2357  vfs::directory_iterator I = FS->dir_begin(State->Stack.top()->path(), EC);
2358  if (I != End) {
2359  State->Stack.push(I);
2360  return *this;
2361  }
2362  }
2363  }
2364 
2365  while (!State->Stack.empty() && State->Stack.top().increment(EC) == End)
2366  State->Stack.pop();
2367 
2368  if (State->Stack.empty())
2369  State.reset(); // end iterator
2370 
2371  return *this;
2372 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
llvm::vfs::RedirectingFileSystem::EK_File
@ EK_File
Definition: VirtualFileSystem.h:612
MemoryBuffer.h
llvm::StringRef::back
LLVM_NODISCARD char back() const
back - Get the last character in the string.
Definition: StringRef.h:168
llvm::sys::fs::file_t
int file_t
Definition: FileSystem.h:60
llvm::errc::invalid_argument
@ invalid_argument
llvm::vfs::RedirectingFSDirIterImpl
Directory iterator implementation for RedirectingFileSystem's directory entries.
Definition: VirtualFileSystem.cpp:1051
llvm::vfs::RedirectingFileSystemParser::lookupOrCreateEntry
static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)
Definition: VirtualFileSystem.cpp:1374
llvm::vfs::InMemoryFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:970
getName
static StringRef getName(Value *V)
Definition: ProvenanceAnalysisEvaluator.cpp:42
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:491
llvm::vfs::Status::isRegularFile
bool isRegularFile() const
Definition: VirtualFileSystem.cpp:96
llvm::vfs::RedirectingFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:1139
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::vfs::RedirectingFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: VirtualFileSystem.cpp:1134
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition: iterator_range.h:53
llvm::sys::fs::current_path
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
getVFSEntries
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
Definition: VirtualFileSystem.cpp:2086
Optional.h
llvm::sys::fs::directory_entry::type
file_type type() const
Definition: FileSystem.h:1358
llvm::MemoryBuffer::getOpenFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition: MemoryBuffer.cpp:503
llvm::vfs::detail::DirIterImpl::CurrentEntry
directory_entry CurrentEntry
Definition: VirtualFileSystem.h:152
FileSystem.h
llvm::sys::fs::OF_None
@ OF_None
Definition: FileSystem.h:757
type
llvm::sys::path::rbegin
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
Definition: Path.cpp:295
llvm::vfs::createPhysicalFileSystem
std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition: VirtualFileSystem.cpp:351
llvm::sys::path::Style::posix
@ posix
RedirectingFSDirRemapIterImpl::RedirectingFSDirRemapIterImpl
RedirectingFSDirRemapIterImpl(std::string DirPath, llvm::vfs::directory_iterator ExtIter)
Definition: VirtualFileSystem.cpp:1103
llvm::StringRef::endswith
LLVM_NODISCARD bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:297
llvm::vfs::InMemoryFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: VirtualFileSystem.h:483
llvm::vfs::RedirectingFileSystem::LookupResult::E
Entry * E
The entry the looked-up path corresponds to.
Definition: VirtualFileSystem.h:721
llvm::yaml::escape
std::string escape(StringRef Input, bool EscapePrintable=true)
Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...
Definition: YAMLParser.cpp:683
llvm::vfs::InMemoryFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition: VirtualFileSystem.cpp:954
StringRef.h
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::vfs::recursive_directory_iterator::recursive_directory_iterator
recursive_directory_iterator()=default
Construct an 'end' iterator.
llvm::vfs::RedirectingFileSystem::setFallthrough
void setFallthrough(bool Fallthrough)
Definition: VirtualFileSystem.cpp:1256
llvm::vfs::RedirectingFileSystemParser::parse
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)
Definition: VirtualFileSystem.cpp:1656
llvm::write
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs)
Definition: DWP.cpp:535
llvm::yaml::Node
Abstract base class for all Nodes.
Definition: YAMLParser.h:119
YAMLParser.h
llvm::vfs::RedirectingFileSystem::create
static std::unique_ptr< RedirectingFileSystem > create(std::unique_ptr< MemoryBuffer > Buffer, SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext, IntrusiveRefCntPtr< FileSystem > ExternalFS)
Parses Buffer, which is expected to be in YAML format and returns a virtual file system representing ...
Definition: VirtualFileSystem.cpp:1751
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1020
llvm::sys::path::remove_leading_dotslash
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
Definition: Path.cpp:702
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:60
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Path.h
llvm::vfs::InMemoryFileSystem::useNormalizedPaths
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
Definition: VirtualFileSystem.h:476
llvm::vfs::RedirectingFileSystem::NK_External
@ NK_External
Definition: VirtualFileSystem.h:613
llvm::vfs::InMemoryFileSystem::InMemoryFileSystem
InMemoryFileSystem(bool UseNormalizedPaths=true)
Definition: VirtualFileSystem.cpp:701
llvm::sys::path::is_absolute
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:669
ErrorHandling.h
llvm::sys::path::reverse_iterator
Reverse path iterator.
Definition: Path.h:78
llvm::sys::fs::getUniqueID
std::error_code getUniqueID(const Twine Path, UniqueID &Result)
Definition: Path.cpp:782
Content
T Content
Definition: ELFObjHandler.cpp:90
llvm::vfs::detail::DirIterImpl
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
Definition: VirtualFileSystem.h:145
llvm::vfs::YAMLVFSEntry::VPath
std::string VPath
Definition: VirtualFileSystem.h:514
RedirectingFSDirRemapIterImpl
Directory iterator implementation for RedirectingFileSystem's directory remap entries that maps the p...
Definition: VirtualFileSystem.cpp:1097
llvm::vfs::detail::InMemoryDirectory::const_iterator
decltype(Entries)::const_iterator const_iterator
Definition: VirtualFileSystem.cpp:670
llvm::vfs::detail::DirIterImpl::~DirIterImpl
virtual ~DirIterImpl()
llvm::errc::not_a_directory
@ not_a_directory
llvm::vfs::InMemoryFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Canonicalizes Path by combining with the current working directory and normalizing the path (e....
Definition: VirtualFileSystem.cpp:988
Errc.h
llvm::vfs::RedirectingFileSystem::Entry::getName
StringRef getName() const
Definition: VirtualFileSystem.h:624
llvm::vfs::FileSystem::status
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
DenseMap.h
llvm::vfs::directory_iterator
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
Definition: VirtualFileSystem.h:159
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:333
llvm::vfs::detail::InMemoryNode::getKind
InMemoryNodeKind getKind() const
Definition: VirtualFileSystem.cpp:565
llvm::sys::fs::file_type::regular_file
@ regular_file
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:233
llvm::vfs::OverlayFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: VirtualFileSystem.cpp:422
llvm::sys::fs::all_all
@ all_all
Definition: FileSystem.h:103
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:224
llvm::Optional
Definition: APInt.h:33
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::count
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:145
llvm::errc::no_such_file_or_directory
@ no_such_file_or_directory
llvm::vfs::RedirectingFileSystem::EK_Directory
@ EK_Directory
Definition: VirtualFileSystem.h:612
llvm::StringSet::insert
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:33
llvm::HexagonII::Absolute
@ Absolute
Definition: HexagonBaseInfo.h:32
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::codeview::Link
@ Link
Definition: CodeView.h:154
STLExtras.h
llvm::vfs::detail::IME_Directory
@ IME_Directory
Definition: VirtualFileSystem.cpp:549
llvm::StringRef::slice
LLVM_NODISCARD StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:732
llvm::sys
Definition: Atomic.h:28
llvm::vfs::Status
The result of a status operation.
Definition: VirtualFileSystem.h:46
IntrusiveRefCntPtr.h
llvm::vfs::lookupInMemoryNode
static ErrorOr< const detail::InMemoryNode * > lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir, const Twine &P)
Definition: VirtualFileSystem.cpp:827
llvm::vfs::detail::InMemoryNode::getFileName
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
Definition: VirtualFileSystem.cpp:564
llvm::vfs::RedirectingFileSystem::openFileForRead
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
Definition: VirtualFileSystem.cpp:2006
llvm::sys::fs::set_current_path
std::error_code set_current_path(const Twine &path)
Set the current path.
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:50
llvm::vfs::OverlayFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
Definition: VirtualFileSystem.cpp:443
llvm::vfs::RedirectingFileSystem
A virtual file system parsed from a YAML file.
Definition: VirtualFileSystem.h:610
new
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM ID Predecessors according to mbb< bb27, 0x8b0a7c0 > Note ADDri is not a two address instruction its result reg1037 is an operand of the PHI node in bb76 and its operand reg1039 is the result of the PHI node We should treat it as a two address code and make sure the ADDri is scheduled after any node that reads reg1039 Use info(i.e. register scavenger) to assign it a free register to allow reuse the collector could move the objects and invalidate the derived pointer This is bad enough in the first but safe points can crop up unpredictably **array_addr i32 n y store obj * new
Definition: README.txt:125
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::vfs::RedirectingFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition: VirtualFileSystem.cpp:1152
llvm::vfs::FileSystem::isLocal
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
Definition: VirtualFileSystem.cpp:141
llvm::sys::TimePoint
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:33
llvm::vfs::OverlayFileSystem::overlays_end
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
Definition: VirtualFileSystem.h:355
Chrono.h
result
It looks like we only need to define PPCfmarto for these because according to these instructions perform RTO on fma s result
Definition: README_P9.txt:256
llvm::vfs::OverlayFileSystem::iterator
FileSystemList::reverse_iterator iterator
Definition: VirtualFileSystem.h:345
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:288
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:454
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Mappings
Inject TLI Mappings
Definition: InjectTLIMappings.cpp:172
llvm::StringRef::substr
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:611
llvm::vfs::detail::InMemoryDirectory::addChild
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
Definition: VirtualFileSystem.cpp:665
llvm::vfs::OverlayFileSystem::status
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
Definition: VirtualFileSystem.cpp:400
llvm::vfs::detail::InMemoryDirectory::getChild
InMemoryNode * getChild(StringRef Name)
Definition: VirtualFileSystem.cpp:658
Process.h
llvm::vfs::RedirectingFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
Definition: VirtualFileSystem.cpp:2045
llvm::orc::tpctypes::LookupResult
std::vector< JITTargetAddress > LookupResult
Definition: TargetProcessControlTypes.h:144
llvm::vfs::Status::copyWithNewName
static Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
Definition: VirtualFileSystem.cpp:77
llvm::sys::fs::is_local
std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
llvm::MemoryBuffer::getMemBuffer
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition: MemoryBuffer.cpp:113
llvm::vfs::detail::InMemoryDirectory::begin
const_iterator begin() const
Definition: VirtualFileSystem.cpp:672
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
SmallString.h
llvm::vfs::FileSystem::getBufferForFile
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
This is a convenience method that opens a file, gets its content and then closes the file.
Definition: VirtualFileSystem.cpp:115
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::User
Definition: User.h:44
llvm::vfs::collectVFSFromYAML
void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
llvm::cl::Required
@ Required
Definition: CommandLine.h:121
Twine.h
llvm::vfs::directory_iterator::increment
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition: VirtualFileSystem.h:174
llvm::sys::fs::file_type::status_error
@ status_error
llvm::vfs::OverlayFileSystem::overlays_begin
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
Definition: VirtualFileSystem.h:351
llvm::vfs::FileSystem::openFileForRead
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the file at Path, if one exists.
llvm::sys::path::root_path
StringRef root_path(StringRef path, Style style=Style::native)
Get root path.
Definition: Path.cpp:346
llvm::vfs
Definition: CommandLine.h:46
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::sys::fs::real_path
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
llvm::yaml::Stream::end
document_iterator end()
Definition: YAMLParser.cpp:1874
llvm::sys::fs::owner_all
@ owner_all
Definition: FileSystem.h:91
llvm::vfs::InMemoryFileSystem::~InMemoryFileSystem
~InMemoryFileSystem() override
llvm::vfs::RedirectingFSDirIterImpl::increment
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition: VirtualFileSystem.cpp:1089
SMLoc.h
llvm::vfs::directory_entry::path
llvm::StringRef path() const
Definition: VirtualFileSystem.h:137
llvm::yaml::Stream::printError
void printError(Node *N, const Twine &Msg, SourceMgr::DiagKind Kind=SourceMgr::DK_Error)
Definition: YAMLParser.cpp:1854
llvm::vfs::RedirectingFileSystem::Entry::getKind
EntryKind getKind() const
Definition: VirtualFileSystem.h:625
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::vfs::FileSystem::exists
bool exists(const Twine &Path)
Check whether a file exists. Provided for convenience.
Definition: VirtualFileSystem.cpp:145
llvm::IndexedInstrProf::Version
const uint64_t Version
Definition: InstrProf.h:991
llvm::sys::path::Style
Style
Definition: Path.h:28
llvm::sys::fs::openNativeFileForRead
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
llvm::MemoryBuffer::getBuffer
StringRef getBuffer() const
Definition: MemoryBuffer.h:69
llvm::vfs::getVFSFromYAML
std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
llvm::sys::fs::file_type
file_type
An enumeration for the file system's view of the type.
Definition: FileSystem.h:66
llvm::vfs::RedirectingFileSystem::DirectoryEntry::iterator
decltype(Contents)::iterator iterator
Definition: VirtualFileSystem.h:652
llvm::SourceMgr::setDiagHandler
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
Definition: SourceMgr.h:109
llvm::vfs::directory_entry
A member of a directory, yielded by a directory_iterator.
Definition: VirtualFileSystem.h:128
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:245
llvm::sys::path::Style::windows
@ windows
llvm::StringRef::getAsInteger
std::enable_if_t< std::numeric_limits< T >::is_signed, bool > getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:510
llvm::None
const NoneType None
Definition: None.h:23
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
now
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
Definition: ArchiveWriter.cpp:259
SourceMgr.h
llvm::vfs::detail::InMemoryNode
The in memory file system is a tree of Nodes.
Definition: VirtualFileSystem.cpp:553
llvm::StringRef::equals
LLVM_NODISCARD bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:187
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:108
llvm::SmallString< 128 >
llvm::MemoryBuffer::getBufferIdentifier
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Definition: MemoryBuffer.h:75
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
llvm::vfs::RedirectingFileSystem::getExternalContentsPrefixDir
StringRef getExternalContentsPrefixDir() const
Definition: VirtualFileSystem.cpp:1252
pathHasTraversal
static bool pathHasTraversal(StringRef Path)
Definition: VirtualFileSystem.cpp:155
llvm::vfs::Status::isOther
bool isOther() const
Definition: VirtualFileSystem.cpp:98
llvm::vfs::detail::IME_HardLink
@ IME_HardLink
Definition: VirtualFileSystem.cpp:549
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
llvm::Optional::getValueOr
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:297
llvm::vfs::detail::InMemoryDirectory::InMemoryDirectory
InMemoryDirectory(Status Stat)
Definition: VirtualFileSystem.cpp:649
llvm::SmallString::c_str
const char * c_str()
Definition: SmallString.h:262
isTraversalComponent
static bool isTraversalComponent(StringRef Component)
Definition: VirtualFileSystem.cpp:151
llvm::sys::fs::file_type::type_unknown
@ type_unknown
llvm::vfs::RedirectingFileSystem::EntryKind
EntryKind
Definition: VirtualFileSystem.h:612
llvm::sys::fs::UniqueID
Definition: UniqueID.h:23
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
llvm::vfs::Status::getName
StringRef getName() const
Returns the name that should be used for this file or directory.
Definition: VirtualFileSystem.h:73
llvm::sys::path::remove_dots
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition: Path.cpp:714
llvm::vfs::getRealFileSystem
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition: VirtualFileSystem.cpp:346
llvm::vfs::FileSystem::getCurrentWorkingDirectory
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
llvm::vfs::YAMLVFSEntry
Definition: VirtualFileSystem.h:509
llvm::vfs::recursive_directory_iterator::increment
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition: VirtualFileSystem.cpp:2348
uint64_t
llvm::sys::path::get_separator
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition: Path.cpp:607
llvm::SourceMgr::PrintMessage
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
Definition: SourceMgr.cpp:341
llvm::vfs::detail::InMemoryFile
Definition: VirtualFileSystem.cpp:569
llvm::vfs::detail::InMemoryDirectory::getStatus
Status getStatus(const Twine &RequestedName) const
Return the Status for this node.
Definition: VirtualFileSystem.cpp:655
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::Twine::toVector
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition: Twine.cpp:32
llvm::vfs::detail::InMemoryFile::getStatus
Status getStatus(const Twine &RequestedName) const
Return the Status for this node.
Definition: VirtualFileSystem.cpp:581
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::vfs::Status::isDirectory
bool isDirectory() const
Definition: VirtualFileSystem.cpp:94
llvm::DenseMap
Definition: DenseMap.h:714
llvm::vfs::InMemoryFileSystem::toString
std::string toString() const
Definition: VirtualFileSystem.cpp:710
ErrorOr.h
llvm::SourceMgr::DiagHandlerTy
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:43
llvm::vfs::detail::InMemoryFile::getBuffer
llvm::MemoryBuffer * getBuffer() const
Definition: VirtualFileSystem.cpp:584
I
#define I(x, y, z)
Definition: MD5.cpp:59
ArrayRef.h
llvm::vfs::RedirectingFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition: VirtualFileSystem.cpp:1192
llvm::sys::path::Style::native
@ native
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::vfs::RedirectingFileSystem::setExternalContentsPrefixDir
void setExternalContentsPrefixDir(StringRef PrefixDir)
Definition: VirtualFileSystem.cpp:1248
llvm::sys::path::parent_path
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:465
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1609
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::sys::fs::directory_iterator::increment
directory_iterator & increment(std::error_code &ec)
Definition: FileSystem.h:1422
iterator_range.h
RedirectingFSDirRemapIterImpl::setCurrentEntry
void setCurrentEntry()
Definition: VirtualFileSystem.cpp:1111
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:901
llvm::vfs::RedirectingFileSystemParser
A helper class to hold the common YAML parsing state.
Definition: VirtualFileSystem.cpp:1296
llvm::vfs::InMemoryFileSystem::status
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
Definition: VirtualFileSystem.cpp:882
llvm::sys::fs::kInvalidFile
const file_t kInvalidFile
llvm::yaml::Stream::failed
bool failed()
Definition: YAMLParser.cpp:1852
llvm::StringSet
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:22
llvm::vfs::getNextVirtualUniqueID
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
Definition: VirtualFileSystem.cpp:2142
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
None.h
DiagHandler
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1095
llvm::vfs::RedirectingFileSystem::getRoots
std::vector< llvm::StringRef > getRoots() const
Definition: VirtualFileSystem.cpp:1260
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::SourceMgr
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition: SourceMgr.h:31
uint32_t
Compiler.h
llvm::vfs::RedirectingFileSystem::dump
LLVM_DUMP_METHOD void dump() const
Definition: VirtualFileSystem.cpp:1292
llvm::vfs::detail::InMemoryDirectory
Definition: VirtualFileSystem.cpp:644
llvm::vfs::detail::InMemoryDirectory::end
const_iterator end() const
Definition: VirtualFileSystem.cpp:673
llvm::yaml::Stream
This class represents a YAML stream potentially containing multiple documents.
Definition: YAMLParser.h:86
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::vfs::Status::getUniqueID
llvm::sys::fs::UniqueID getUniqueID() const
Definition: VirtualFileSystem.h:80
llvm::AMDGPU::HSAMD::Kernel::Arg::Key::IsVolatile
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
Definition: AMDGPUMetadata.h:194
llvm::vfs::YAMLVFSWriter::write
void write(llvm::raw_ostream &OS)
Definition: VirtualFileSystem.cpp:2328
LLVM_FALLTHROUGH
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:273
llvm::vfs::InMemoryFileSystem::addHardLink
bool addHardLink(const Twine &From, const Twine &To)
Add a hard link to a file.
Definition: VirtualFileSystem.cpp:870
llvm::sys::path::const_iterator
Path iterator.
Definition: Path.h:52
llvm::vfs::File
Represents an open file.
Definition: VirtualFileSystem.h:99
VirtualFileSystem.h
llvm::vfs::directory_entry::type
llvm::sys::fs::file_type type() const
Definition: VirtualFileSystem.h:138
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition: BitcodeReader.h:270
llvm::vfs::Status::isSymlink
bool isSymlink() const
Definition: VirtualFileSystem.cpp:102
llvm::vfs::InMemoryFileSystem::addFileNoOwn
bool addFileNoOwn(const Twine &Path, time_t ModificationTime, const llvm::MemoryBufferRef &Buffer, Optional< uint32_t > User=None, Optional< uint32_t > Group=None, Optional< llvm::sys::fs::file_type > Type=None, Optional< llvm::sys::fs::perms > Perms=None)
Add a buffer to the VFS with a path.
Definition: VirtualFileSystem.cpp:815
StringSet.h
llvm::yaml::Stream::begin
document_iterator begin()
Definition: YAMLParser.cpp:1863
llvm::vfs::RedirectingFileSystem::dumpEntry
void dumpEntry(raw_ostream &OS, Entry *E, int NumSpaces=0) const
Definition: VirtualFileSystem.cpp:1272
llvm::vfs::recursive_directory_iterator
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
Definition: VirtualFileSystem.h:209
llvm::sys::fs::file_type::directory_file
@ directory_file
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::vfs::RedirectingFileSystem::EK_DirectoryRemap
@ EK_DirectoryRemap
Definition: VirtualFileSystem.h:612
llvm::vfs::FileSystem
The virtual file system interface.
Definition: VirtualFileSystem.h:245
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::vfs::InMemoryFileSystem
An in-memory file system.
Definition: VirtualFileSystem.h:416
get
Should compile to something r4 addze r3 instead we get
Definition: README.txt:24
llvm::SmallVectorImpl::assign
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:669
RedirectingFSDirRemapIterImpl::increment
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition: VirtualFileSystem.cpp:1122
llvm::vfs::RedirectingFileSystem::LookupResult::LookupResult
LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
Definition: VirtualFileSystem.cpp:1846
llvm::vfs::detail::InMemoryNode::InMemoryNode
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
Definition: VirtualFileSystem.cpp:558
llvm::X86AS::FS
@ FS
Definition: X86.h:188
llvm::vfs::RedirectingFileSystem::lookupPath
ErrorOr< LookupResult > lookupPath(StringRef Path) const
Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...
Definition: VirtualFileSystem.cpp:1883
llvm::vfs::OverlayFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition: VirtualFileSystem.cpp:536
Casting.h
llvm::vfs::RedirectingFileSystem::NK_Virtual
@ NK_Virtual
Definition: VirtualFileSystem.h:613
llvm::vfs::RedirectingFileSystem::NK_NotSet
@ NK_NotSet
Definition: VirtualFileSystem.h:613
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1492
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::SourceMgr::DK_Error
@ DK_Error
Definition: SourceMgr.h:34
llvm::vfs::YAMLVFSWriter::addFileMapping
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
Definition: VirtualFileSystem.cpp:2158
llvm::sys::fs::is_directory
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:1088
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:259
llvm::vfs::RedirectingFSDirIterImpl::RedirectingFSDirIterImpl
RedirectingFSDirIterImpl(const Twine &Path, RedirectingFileSystem::DirectoryEntry::iterator Begin, RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
Definition: VirtualFileSystem.cpp:1082
llvm::vfs::OverlayFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:428
llvm::vfs::Status::exists
bool exists() const
Definition: VirtualFileSystem.cpp:106
llvm::errorToErrorCode
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition: Error.cpp:93
llvm::vfs::InMemoryFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition: VirtualFileSystem.cpp:1000
llvm::vfs::File::~File
virtual ~File()
Destroy the file after closing it (if open).
llvm::vfs::OverlayFileSystem::pushOverlay
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
Definition: VirtualFileSystem.cpp:393
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:589
llvm::sys::path::is_separator
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition: Path.cpp:599
llvm::sys::fs::directory_iterator
directory_iterator - Iterates through the entries in path.
Definition: FileSystem.h:1396
llvm::vfs::OverlayFileSystem::openFileForRead
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
Definition: VirtualFileSystem.cpp:411
llvm::sys::fs::perms
perms
Definition: FileSystem.h:86
llvm::vfs::detail::InMemoryFile::InMemoryFile
InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Definition: VirtualFileSystem.cpp:574
llvm::sys::path::filename
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:575
llvm::vfs::RedirectingFileSystemParser::RedirectingFileSystemParser
RedirectingFileSystemParser(yaml::Stream &S)
Definition: VirtualFileSystem.cpp:1653
SmallVector.h
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition: raw_ostream.cpp:497
llvm::sys::fs::directory_entry::path
const std::string & path() const
Definition: FileSystem.h:1350
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
N
#define N
llvm::sys::toTimePoint
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition: Chrono.h:44
llvm::vfs::detail::InMemoryFile::classof
static bool classof(const InMemoryNode *N)
Definition: VirtualFileSystem.cpp:590
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::vfs::RedirectingFileSystem::LookupResult
Represents the result of a path lookup into the RedirectingFileSystem.
Definition: VirtualFileSystem.h:719
llvm::vfs::detail::InMemoryDirectory::classof
static bool classof(const InMemoryNode *N)
Definition: VirtualFileSystem.cpp:683
llvm::vfs::detail::IME_File
@ IME_File
Definition: VirtualFileSystem.cpp:549
llvm::vfs::YAMLVFSWriter::addDirectoryMapping
void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
Definition: VirtualFileSystem.cpp:2162
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::SmallVectorImpl< char >
llvm::sys::path::rend
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
Definition: Path.cpp:304
llvm::yaml::document_iterator
Iterator abstraction for Documents over a Stream.
Definition: YAMLParser.h:588
llvm::errc::operation_not_permitted
@ operation_not_permitted
llvm::vfs::FileSystem::getRealPath
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const
Gets real path of Path e.g.
Definition: VirtualFileSystem.cpp:136
llvm::vfs::detail::InMemoryNodeKind
InMemoryNodeKind
Definition: VirtualFileSystem.cpp:549
llvm::vfs::FileSystem::makeAbsolute
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
Definition: VirtualFileSystem.cpp:124
llvm::StringRef::find_first_of
LLVM_NODISCARD size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition: StringRef.h:410
llvm::vfs::detail::InMemoryFile::toString
std::string toString(unsigned Indent) const override
Definition: VirtualFileSystem.cpp:586
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
From
BlockVerifier::State From
Definition: BlockVerifier.cpp:55
llvm::vfs::RedirectingFileSystem::makeAbsolute
std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const override
Make Path an absolute path.
Definition: VirtualFileSystem.cpp:1163
llvm::vfs::Status::equivalent
bool equivalent(const Status &Other) const
Definition: VirtualFileSystem.cpp:89
raw_ostream.h
n
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
Definition: README.txt:685
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::vfs::OverlayFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition: VirtualFileSystem.cpp:435
llvm::vfs::detail::InMemoryDirectory::toString
std::string toString(unsigned Indent) const override
Definition: VirtualFileSystem.cpp:675
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::vfs::InMemoryFileSystem::openFileForRead
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
Definition: VirtualFileSystem.cpp:890
getRedirectedFileStatus
static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames, Status ExternalStatus)
Definition: VirtualFileSystem.cpp:1936
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::vfs::Status::isStatusKnown
bool isStatusKnown() const
Definition: VirtualFileSystem.cpp:104
Debug.h
File
Instrumentation for Order File
Definition: InstrOrderFile.cpp:205
llvm::IntrusiveRefCntPtr
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
Definition: IntrusiveRefCntPtr.h:163
llvm::vfs::Status::Status
Status()=default
llvm::Optional::getValue
constexpr const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:282
llvm::sys::fs::openFileForRead
std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
SpecialSubKind::string
@ string
Other
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1172
llvm::vfs::RedirectingFileSystem::Entry
A single file or directory in the VFS.
Definition: VirtualFileSystem.h:616
write
static void write(bool isBE, void *P, T V)
Definition: RuntimeDyldELF.cpp:37
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37
llvm::vfs::FileSystem::~FileSystem
virtual ~FileSystem()
llvm::vfs::OverlayFileSystem::OverlayFileSystem
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
Definition: VirtualFileSystem.cpp:389