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"
37 #include "llvm/Support/Path.h"
38 #include "llvm/Support/Process.h"
39 #include "llvm/Support/SMLoc.h"
40 #include "llvm/Support/SourceMgr.h"
43 #include <algorithm>
44 #include <atomic>
45 #include <cassert>
46 #include <cstdint>
47 #include <iterator>
48 #include <limits>
49 #include <map>
50 #include <memory>
51 #include <mutex>
52 #include <string>
53 #include <system_error>
54 #include <utility>
55 #include <vector>
56 
57 using namespace llvm;
58 using namespace llvm::vfs;
59 
66 
68  : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
69  User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
70  Type(Status.type()), Perms(Status.permissions()) {}
71 
74  perms Perms)
75  : Name(Name.str()), UID(UID), MTime(MTime), User(User), Group(Group),
76  Size(Size), Type(Type), Perms(Perms) {}
77 
79  return Status(In.getName(), In.getUniqueID(), In.getLastModificationTime(),
80  In.getUser(), In.getGroup(), NewSize, In.getType(),
81  In.getPermissions());
82 }
83 
84 Status Status::copyWithNewName(const Status &In, const Twine &NewName) {
85  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
86  In.getUser(), In.getGroup(), In.getSize(), In.getType(),
87  In.getPermissions());
88 }
89 
91  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
92  In.getUser(), In.getGroup(), In.getSize(), In.type(),
93  In.permissions());
94 }
95 
96 bool Status::equivalent(const Status &Other) const {
97  assert(isStatusKnown() && Other.isStatusKnown());
98  return getUniqueID() == Other.getUniqueID();
99 }
100 
101 bool Status::isDirectory() const { return Type == file_type::directory_file; }
102 
103 bool Status::isRegularFile() const { return Type == file_type::regular_file; }
104 
105 bool Status::isOther() const {
106  return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
107 }
108 
109 bool Status::isSymlink() const { return Type == file_type::symlink_file; }
110 
111 bool Status::isStatusKnown() const { return Type != file_type::status_error; }
112 
113 bool Status::exists() const {
114  return isStatusKnown() && Type != file_type::file_not_found;
115 }
116 
117 File::~File() = default;
118 
119 FileSystem::~FileSystem() = default;
120 
123  bool RequiresNullTerminator, bool IsVolatile) {
124  auto F = openFileForRead(Name);
125  if (!F)
126  return F.getError();
127 
128  return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
129 }
130 
131 std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
133  return {};
134 
135  auto WorkingDir = getCurrentWorkingDirectory();
136  if (!WorkingDir)
137  return WorkingDir.getError();
138 
139  llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
140  return {};
141 }
142 
143 std::error_code FileSystem::getRealPath(const Twine &Path,
144  SmallVectorImpl<char> &Output) const {
146 }
147 
148 std::error_code FileSystem::isLocal(const Twine &Path, bool &Result) {
150 }
151 
152 bool FileSystem::exists(const Twine &Path) {
153  auto Status = status(Path);
154  return Status && Status->exists();
155 }
156 
157 #ifndef NDEBUG
158 static bool isTraversalComponent(StringRef Component) {
159  return Component.equals("..") || Component.equals(".");
160 }
161 
162 static bool pathHasTraversal(StringRef Path) {
163  using namespace llvm::sys;
164 
165  for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
166  if (isTraversalComponent(Comp))
167  return true;
168  return false;
169 }
170 #endif
171 
172 //===-----------------------------------------------------------------------===/
173 // RealFileSystem implementation
174 //===-----------------------------------------------------------------------===/
175 
176 namespace {
177 
178 /// Wrapper around a raw file descriptor.
179 class RealFile : public File {
180  friend class RealFileSystem;
181 
182  file_t FD;
183  Status S;
184  std::string RealName;
185 
186  RealFile(file_t RawFD, StringRef NewName, StringRef NewRealPathName)
187  : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
189  RealName(NewRealPathName.str()) {
190  assert(FD != kInvalidFile && "Invalid or inactive file descriptor");
191  }
192 
193 public:
194  ~RealFile() override;
195 
196  ErrorOr<Status> status() override;
197  ErrorOr<std::string> getName() override;
199  int64_t FileSize,
200  bool RequiresNullTerminator,
201  bool IsVolatile) override;
202  std::error_code close() override;
203  void setPath(const Twine &Path) override;
204 };
205 
206 } // namespace
207 
208 RealFile::~RealFile() { close(); }
209 
211  assert(FD != kInvalidFile && "cannot stat closed file");
212  if (!S.isStatusKnown()) {
213  file_status RealStatus;
214  if (std::error_code EC = sys::fs::status(FD, RealStatus))
215  return EC;
216  S = Status::copyWithNewName(RealStatus, S.getName());
217  }
218  return S;
219 }
220 
222  return RealName.empty() ? S.getName().str() : RealName;
223 }
224 
226 RealFile::getBuffer(const Twine &Name, int64_t FileSize,
227  bool RequiresNullTerminator, bool IsVolatile) {
228  assert(FD != kInvalidFile && "cannot get buffer for closed file");
229  return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
230  IsVolatile);
231 }
232 
233 std::error_code RealFile::close() {
234  std::error_code EC = sys::fs::closeFile(FD);
235  FD = kInvalidFile;
236  return EC;
237 }
238 
239 void RealFile::setPath(const Twine &Path) {
240  RealName = Path.str();
241  if (auto Status = status())
242  S = Status.get().copyWithNewName(Status.get(), Path);
243 }
244 
245 namespace {
246 
247 /// A file system according to your operating system.
248 /// This may be linked to the process's working directory, or maintain its own.
249 ///
250 /// Currently, its own working directory is emulated by storing the path and
251 /// sending absolute paths to llvm::sys::fs:: functions.
252 /// A more principled approach would be to push this down a level, modelling
253 /// the working dir as an llvm::sys::fs::WorkingDir or similar.
254 /// This would enable the use of openat()-style functions on some platforms.
255 class RealFileSystem : public FileSystem {
256 public:
257  explicit RealFileSystem(bool LinkCWDToProcess) {
258  if (!LinkCWDToProcess) {
259  SmallString<128> PWD, RealPWD;
261  return; // Awful, but nothing to do here.
262  if (llvm::sys::fs::real_path(PWD, RealPWD))
263  WD = {PWD, PWD};
264  else
265  WD = {PWD, RealPWD};
266  }
267  }
268 
269  ErrorOr<Status> status(const Twine &Path) override;
270  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
271  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
272 
273  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
274  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
275  std::error_code isLocal(const Twine &Path, bool &Result) override;
276  std::error_code getRealPath(const Twine &Path,
277  SmallVectorImpl<char> &Output) const override;
278 
279 private:
280  // If this FS has its own working dir, use it to make Path absolute.
281  // The returned twine is safe to use as long as both Storage and Path live.
282  Twine adjustPath(const Twine &Path, SmallVectorImpl<char> &Storage) const {
283  if (!WD)
284  return Path;
285  Path.toVector(Storage);
286  sys::fs::make_absolute(WD->Resolved, Storage);
287  return Storage;
288  }
289 
290  struct WorkingDirectory {
291  // The current working directory, without symlinks resolved. (echo $PWD).
292  SmallString<128> Specified;
293  // The current working directory, with links resolved. (readlink .).
295  };
297 };
298 
299 } // namespace
300 
302  SmallString<256> Storage;
303  sys::fs::file_status RealStatus;
304  if (std::error_code EC =
305  sys::fs::status(adjustPath(Path, Storage), RealStatus))
306  return EC;
307  return Status::copyWithNewName(RealStatus, Path);
308 }
309 
312  SmallString<256> RealName, Storage;
314  adjustPath(Name, Storage), sys::fs::OF_None, &RealName);
315  if (!FDOrErr)
316  return errorToErrorCode(FDOrErr.takeError());
317  return std::unique_ptr<File>(
318  new RealFile(*FDOrErr, Name.str(), RealName.str()));
319 }
320 
321 llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
322  if (WD)
323  return std::string(WD->Specified.str());
324 
325  SmallString<128> Dir;
326  if (std::error_code EC = llvm::sys::fs::current_path(Dir))
327  return EC;
328  return std::string(Dir.str());
329 }
330 
331 std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
332  if (!WD)
333  return llvm::sys::fs::set_current_path(Path);
334 
336  adjustPath(Path, Storage).toVector(Absolute);
337  bool IsDir;
338  if (auto Err = llvm::sys::fs::is_directory(Absolute, IsDir))
339  return Err;
340  if (!IsDir)
341  return std::make_error_code(std::errc::not_a_directory);
342  if (auto Err = llvm::sys::fs::real_path(Absolute, Resolved))
343  return Err;
344  WD = {Absolute, Resolved};
345  return std::error_code();
346 }
347 
348 std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
349  SmallString<256> Storage;
350  return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result);
351 }
352 
353 std::error_code
354 RealFileSystem::getRealPath(const Twine &Path,
355  SmallVectorImpl<char> &Output) const {
356  SmallString<256> Storage;
357  return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
358 }
359 
361  static IntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true));
362  return FS;
363 }
364 
365 std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
366  return std::make_unique<RealFileSystem>(false);
367 }
368 
369 namespace {
370 
371 class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
373 
374 public:
375  RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
376  if (Iter != llvm::sys::fs::directory_iterator())
377  CurrentEntry = directory_entry(Iter->path(), Iter->type());
378  }
379 
380  std::error_code increment() override {
381  std::error_code EC;
382  Iter.increment(EC);
383  CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
384  ? directory_entry()
385  : directory_entry(Iter->path(), Iter->type());
386  return EC;
387  }
388 };
389 
390 } // namespace
391 
392 directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
393  std::error_code &EC) {
394  SmallString<128> Storage;
395  return directory_iterator(
396  std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
397 }
398 
399 //===-----------------------------------------------------------------------===/
400 // OverlayFileSystem implementation
401 //===-----------------------------------------------------------------------===/
402 
404  FSList.push_back(std::move(BaseFS));
405 }
406 
408  FSList.push_back(FS);
409  // Synchronize added file systems by duplicating the working directory from
410  // the first one in the list.
411  FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
412 }
413 
415  // FIXME: handle symlinks that cross file systems
416  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
417  ErrorOr<Status> Status = (*I)->status(Path);
419  return Status;
420  }
422 }
423 
426  // FIXME: handle symlinks that cross file systems
427  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
428  auto Result = (*I)->openFileForRead(Path);
429  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
430  return Result;
431  }
433 }
434 
437  // All file systems are synchronized, just take the first working directory.
438  return FSList.front()->getCurrentWorkingDirectory();
439 }
440 
441 std::error_code
443  for (auto &FS : FSList)
444  if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
445  return EC;
446  return {};
447 }
448 
449 std::error_code OverlayFileSystem::isLocal(const Twine &Path, bool &Result) {
450  for (auto &FS : FSList)
451  if (FS->exists(Path))
452  return FS->isLocal(Path, Result);
454 }
455 
456 std::error_code
458  SmallVectorImpl<char> &Output) const {
459  for (const auto &FS : FSList)
460  if (FS->exists(Path))
461  return FS->getRealPath(Path, Output);
463 }
464 
466 
467 namespace {
468 
469 /// Combines and deduplicates directory entries across multiple file systems.
470 class CombiningDirIterImpl : public llvm::vfs::detail::DirIterImpl {
472 
473  /// File systems to check for entries in. Processed in reverse order.
475  /// The directory iterator for the current filesystem.
476  directory_iterator CurrentDirIter;
477  /// The path of the directory to iterate the entries of.
478  std::string DirPath;
479  /// The set of names already returned as entries.
480  llvm::StringSet<> SeenNames;
481 
482  /// Sets \c CurrentDirIter to an iterator of \c DirPath in the next file
483  /// system in the list, or leaves it as is (at its end position) if we've
484  /// already gone through them all.
485  std::error_code incrementFS() {
486  while (!FSList.empty()) {
487  std::error_code EC;
488  CurrentDirIter = FSList.back()->dir_begin(DirPath, EC);
489  FSList.pop_back();
490  if (EC && EC != errc::no_such_file_or_directory)
491  return EC;
492  if (CurrentDirIter != directory_iterator())
493  break; // found
494  }
495  return {};
496  }
497 
498  std::error_code incrementDirIter(bool IsFirstTime) {
499  assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
500  "incrementing past end");
501  std::error_code EC;
502  if (!IsFirstTime)
503  CurrentDirIter.increment(EC);
504  if (!EC && CurrentDirIter == directory_iterator())
505  EC = incrementFS();
506  return EC;
507  }
508 
509  std::error_code incrementImpl(bool IsFirstTime) {
510  while (true) {
511  std::error_code EC = incrementDirIter(IsFirstTime);
512  if (EC || CurrentDirIter == directory_iterator()) {
513  CurrentEntry = directory_entry();
514  return EC;
515  }
516  CurrentEntry = *CurrentDirIter;
517  StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
518  if (SeenNames.insert(Name).second)
519  return EC; // name not seen before
520  }
521  llvm_unreachable("returned above");
522  }
523 
524 public:
525  CombiningDirIterImpl(ArrayRef<FileSystemPtr> FileSystems, std::string Dir,
526  std::error_code &EC)
527  : FSList(FileSystems.begin(), FileSystems.end()),
528  DirPath(std::move(Dir)) {
529  if (!FSList.empty()) {
530  CurrentDirIter = FSList.back()->dir_begin(DirPath, EC);
531  FSList.pop_back();
532  if (!EC || EC == errc::no_such_file_or_directory)
533  EC = incrementImpl(true);
534  }
535  }
536 
537  CombiningDirIterImpl(directory_iterator FirstIter, FileSystemPtr Fallback,
538  std::string FallbackDir, std::error_code &EC)
539  : FSList({Fallback}), CurrentDirIter(FirstIter),
540  DirPath(std::move(FallbackDir)) {
541  if (!EC || EC == errc::no_such_file_or_directory)
542  EC = incrementImpl(true);
543  }
544 
545  std::error_code increment() override { return incrementImpl(false); }
546 };
547 
548 } // namespace
549 
551  std::error_code &EC) {
552  return directory_iterator(
553  std::make_shared<CombiningDirIterImpl>(FSList, Dir.str(), EC));
554 }
555 
556 void ProxyFileSystem::anchor() {}
557 
558 namespace llvm {
559 namespace vfs {
560 
561 namespace detail {
562 
564 
565 /// The in memory file system is a tree of Nodes. Every node can either be a
566 /// file , hardlink or a directory.
569  std::string FileName;
570 
571 public:
573  : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) {
574  }
575  virtual ~InMemoryNode() = default;
576 
577  /// Get the filename of this node (the name without the directory part).
578  StringRef getFileName() const { return FileName; }
579  InMemoryNodeKind getKind() const { return Kind; }
580  virtual std::string toString(unsigned Indent) const = 0;
581 };
582 
583 class InMemoryFile : public InMemoryNode {
584  Status Stat;
585  std::unique_ptr<llvm::MemoryBuffer> Buffer;
586 
587 public:
588  InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
589  : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
590  Buffer(std::move(Buffer)) {}
591 
592  /// Return the \p Status for this node. \p RequestedName should be the name
593  /// through which the caller referred to this node. It will override
594  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
595  Status getStatus(const Twine &RequestedName) const {
596  return Status::copyWithNewName(Stat, RequestedName);
597  }
598  llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
599 
600  std::string toString(unsigned Indent) const override {
601  return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
602  }
603 
604  static bool classof(const InMemoryNode *N) {
605  return N->getKind() == IME_File;
606  }
607 };
608 
609 namespace {
610 
611 class InMemoryHardLink : public InMemoryNode {
612  const InMemoryFile &ResolvedFile;
613 
614 public:
615  InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)
616  : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
617  const InMemoryFile &getResolvedFile() const { return ResolvedFile; }
618 
619  std::string toString(unsigned Indent) const override {
620  return std::string(Indent, ' ') + "HardLink to -> " +
621  ResolvedFile.toString(0);
622  }
623 
624  static bool classof(const InMemoryNode *N) {
625  return N->getKind() == IME_HardLink;
626  }
627 };
628 
629 /// Adapt a InMemoryFile for VFS' File interface. The goal is to make
630 /// \p InMemoryFileAdaptor mimic as much as possible the behavior of
631 /// \p RealFile.
632 class InMemoryFileAdaptor : public File {
633  const InMemoryFile &Node;
634  /// The name to use when returning a Status for this file.
635  std::string RequestedName;
636 
637 public:
638  explicit InMemoryFileAdaptor(const InMemoryFile &Node,
639  std::string RequestedName)
640  : Node(Node), RequestedName(std::move(RequestedName)) {}
641 
642  llvm::ErrorOr<Status> status() override {
643  return Node.getStatus(RequestedName);
644  }
645 
647  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
648  bool IsVolatile) override {
649  llvm::MemoryBuffer *Buf = Node.getBuffer();
651  Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
652  }
653 
654  std::error_code close() override { return {}; }
655 
656  void setPath(const Twine &Path) override { RequestedName = Path.str(); }
657 };
658 } // namespace
659 
661  Status Stat;
663 
664 public:
666  : InMemoryNode(Stat.getName(), IME_Directory), Stat(std::move(Stat)) {}
667 
668  /// Return the \p Status for this node. \p RequestedName should be the name
669  /// through which the caller referred to this node. It will override
670  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
671  Status getStatus(const Twine &RequestedName) const {
672  return Status::copyWithNewName(Stat, RequestedName);
673  }
674 
675  UniqueID getUniqueID() const { return Stat.getUniqueID(); }
676 
678  auto I = Entries.find(Name);
679  if (I != Entries.end())
680  return I->second.get();
681  return nullptr;
682  }
683 
684  InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
685  return Entries.insert(make_pair(Name, std::move(Child)))
686  .first->second.get();
687  }
688 
689  using const_iterator = decltype(Entries)::const_iterator;
690 
691  const_iterator begin() const { return Entries.begin(); }
692  const_iterator end() const { return Entries.end(); }
693 
694  std::string toString(unsigned Indent) const override {
695  std::string Result =
696  (std::string(Indent, ' ') + Stat.getName() + "\n").str();
697  for (const auto &Entry : Entries)
698  Result += Entry.second->toString(Indent + 2);
699  return Result;
700  }
701 
702  static bool classof(const InMemoryNode *N) {
703  return N->getKind() == IME_Directory;
704  }
705 };
706 
707 namespace {
708 Status getNodeStatus(const InMemoryNode *Node, const Twine &RequestedName) {
709  if (auto Dir = dyn_cast<detail::InMemoryDirectory>(Node))
710  return Dir->getStatus(RequestedName);
711  if (auto File = dyn_cast<detail::InMemoryFile>(Node))
712  return File->getStatus(RequestedName);
713  if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node))
714  return Link->getResolvedFile().getStatus(RequestedName);
715  llvm_unreachable("Unknown node type");
716 }
717 } // namespace
718 } // namespace detail
719 
720 // The UniqueID of in-memory files is derived from path and content.
721 // This avoids difficulties in creating exactly equivalent in-memory FSes,
722 // as often needed in multithreaded programs.
725  uint64_t(size_t(Hash)));
726 }
729  llvm::StringRef Contents) {
730  return getUniqueID(llvm::hash_combine(Parent.getFile(), Name, Contents));
731 }
734  return getUniqueID(llvm::hash_combine(Parent.getFile(), Name));
735 }
736 
738  : Root(new detail::InMemoryDirectory(
739  Status("", getDirectoryID(llvm::sys::fs::UniqueID(), ""),
740  llvm::sys::TimePoint<>(), 0, 0, 0,
741  llvm::sys::fs::file_type::directory_file,
742  llvm::sys::fs::perms::all_all))),
743  UseNormalizedPaths(UseNormalizedPaths) {}
744 
746 
747 std::string InMemoryFileSystem::toString() const {
748  return Root->toString(/*Indent=*/0);
749 }
750 
751 bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
752  std::unique_ptr<llvm::MemoryBuffer> Buffer,
754  Optional<uint32_t> Group,
757  const detail::InMemoryFile *HardLinkTarget) {
758  SmallString<128> Path;
759  P.toVector(Path);
760 
761  // Fix up relative paths. This just prepends the current working directory.
762  std::error_code EC = makeAbsolute(Path);
763  assert(!EC);
764  (void)EC;
765 
766  if (useNormalizedPaths())
767  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
768 
769  if (Path.empty())
770  return false;
771 
772  detail::InMemoryDirectory *Dir = Root.get();
773  auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
774  const auto ResolvedUser = User.getValueOr(0);
775  const auto ResolvedGroup = Group.getValueOr(0);
776  const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
777  const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
778  assert(!(HardLinkTarget && Buffer) && "HardLink cannot have a buffer");
779  // Any intermediate directories we create should be accessible by
780  // the owner, even if Perms says otherwise for the final path.
781  const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
782  while (true) {
783  StringRef Name = *I;
784  detail::InMemoryNode *Node = Dir->getChild(Name);
785  ++I;
786  if (!Node) {
787  if (I == E) {
788  // End of the path.
789  std::unique_ptr<detail::InMemoryNode> Child;
790  if (HardLinkTarget)
791  Child.reset(new detail::InMemoryHardLink(P.str(), *HardLinkTarget));
792  else {
793  // Create a new file or directory.
794  Status Stat(
795  P.str(),
796  (ResolvedType == sys::fs::file_type::directory_file)
797  ? getDirectoryID(Dir->getUniqueID(), Name)
798  : getFileID(Dir->getUniqueID(), Name, Buffer->getBuffer()),
799  llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
800  ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
801  ResolvedPerms);
802  if (ResolvedType == sys::fs::file_type::directory_file) {
803  Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
804  } else {
805  Child.reset(
806  new detail::InMemoryFile(std::move(Stat), std::move(Buffer)));
807  }
808  }
809  Dir->addChild(Name, std::move(Child));
810  return true;
811  }
812 
813  // Create a new directory. Use the path up to here.
814  Status Stat(
815  StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
817  llvm::sys::toTimePoint(ModificationTime), ResolvedUser, ResolvedGroup,
818  0, sys::fs::file_type::directory_file, NewDirectoryPerms);
819  Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
820  Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
821  continue;
822  }
823 
824  if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
825  Dir = NewDir;
826  } else {
827  assert((isa<detail::InMemoryFile>(Node) ||
828  isa<detail::InMemoryHardLink>(Node)) &&
829  "Must be either file, hardlink or directory!");
830 
831  // Trying to insert a directory in place of a file.
832  if (I != E)
833  return false;
834 
835  // Return false only if the new file is different from the existing one.
836  if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
837  return Link->getResolvedFile().getBuffer()->getBuffer() ==
838  Buffer->getBuffer();
839  }
840  return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
841  Buffer->getBuffer();
842  }
843  }
844 }
845 
846 bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
847  std::unique_ptr<llvm::MemoryBuffer> Buffer,
849  Optional<uint32_t> Group,
852  return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
853  Perms, /*HardLinkTarget=*/nullptr);
854 }
855 
856 bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
857  const llvm::MemoryBufferRef &Buffer,
859  Optional<uint32_t> Group,
862  return addFile(P, ModificationTime, llvm::MemoryBuffer::getMemBuffer(Buffer),
864  std::move(Perms));
865 }
866 
869  const Twine &P) {
870  SmallString<128> Path;
871  P.toVector(Path);
872 
873  // Fix up relative paths. This just prepends the current working directory.
874  std::error_code EC = FS.makeAbsolute(Path);
875  assert(!EC);
876  (void)EC;
877 
878  if (FS.useNormalizedPaths())
879  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
880 
881  if (Path.empty())
882  return Dir;
883 
884  auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
885  while (true) {
886  detail::InMemoryNode *Node = Dir->getChild(*I);
887  ++I;
888  if (!Node)
890 
891  // Return the file if it's at the end of the path.
892  if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
893  if (I == E)
894  return File;
896  }
897 
898  // If Node is HardLink then return the resolved file.
899  if (auto File = dyn_cast<detail::InMemoryHardLink>(Node)) {
900  if (I == E)
901  return &File->getResolvedFile();
903  }
904  // Traverse directories.
905  Dir = cast<detail::InMemoryDirectory>(Node);
906  if (I == E)
907  return Dir;
908  }
909 }
910 
912  const Twine &ToPath) {
913  auto FromNode = lookupInMemoryNode(*this, Root.get(), FromPath);
914  auto ToNode = lookupInMemoryNode(*this, Root.get(), ToPath);
915  // FromPath must not have been added before. ToPath must have been added
916  // before. Resolved ToPath must be a File.
917  if (!ToNode || FromNode || !isa<detail::InMemoryFile>(*ToNode))
918  return false;
919  return this->addFile(FromPath, 0, nullptr, None, None, None, None,
920  cast<detail::InMemoryFile>(*ToNode));
921 }
922 
924  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
925  if (Node)
926  return detail::getNodeStatus(*Node, Path);
927  return Node.getError();
928 }
929 
932  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
933  if (!Node)
934  return Node.getError();
935 
936  // When we have a file provide a heap-allocated wrapper for the memory buffer
937  // to match the ownership semantics for File.
938  if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
939  return std::unique_ptr<File>(
940  new detail::InMemoryFileAdaptor(*F, Path.str()));
941 
942  // FIXME: errc::not_a_file?
944 }
945 
946 namespace {
947 
948 /// Adaptor from InMemoryDir::iterator to directory_iterator.
949 class InMemoryDirIterator : public llvm::vfs::detail::DirIterImpl {
952  std::string RequestedDirName;
953 
954  void setCurrentEntry() {
955  if (I != E) {
956  SmallString<256> Path(RequestedDirName);
957  llvm::sys::path::append(Path, I->second->getFileName());
959  switch (I->second->getKind()) {
960  case detail::IME_File:
963  break;
966  break;
967  }
968  CurrentEntry = directory_entry(std::string(Path.str()), Type);
969  } else {
970  // When we're at the end, make CurrentEntry invalid and DirIterImpl will
971  // do the rest.
972  CurrentEntry = directory_entry();
973  }
974  }
975 
976 public:
977  InMemoryDirIterator() = default;
978 
979  explicit InMemoryDirIterator(const detail::InMemoryDirectory &Dir,
980  std::string RequestedDirName)
981  : I(Dir.begin()), E(Dir.end()),
982  RequestedDirName(std::move(RequestedDirName)) {
983  setCurrentEntry();
984  }
985 
986  std::error_code increment() override {
987  ++I;
988  setCurrentEntry();
989  return {};
990  }
991 };
992 
993 } // namespace
994 
996  std::error_code &EC) {
997  auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
998  if (!Node) {
999  EC = Node.getError();
1000  return directory_iterator(std::make_shared<InMemoryDirIterator>());
1001  }
1002 
1003  if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
1004  return directory_iterator(
1005  std::make_shared<InMemoryDirIterator>(*DirNode, Dir.str()));
1006 
1008  return directory_iterator(std::make_shared<InMemoryDirIterator>());
1009 }
1010 
1012  SmallString<128> Path;
1013  P.toVector(Path);
1014 
1015  // Fix up relative paths. This just prepends the current working directory.
1016  std::error_code EC = makeAbsolute(Path);
1017  assert(!EC);
1018  (void)EC;
1019 
1020  if (useNormalizedPaths())
1021  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
1022 
1023  if (!Path.empty())
1024  WorkingDirectory = std::string(Path.str());
1025  return {};
1026 }
1027 
1028 std::error_code
1030  SmallVectorImpl<char> &Output) const {
1031  auto CWD = getCurrentWorkingDirectory();
1032  if (!CWD || CWD->empty())
1034  Path.toVector(Output);
1035  if (auto EC = makeAbsolute(Output))
1036  return EC;
1037  llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
1038  return {};
1039 }
1040 
1041 std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
1042  Result = false;
1043  return {};
1044 }
1045 
1046 } // namespace vfs
1047 } // namespace llvm
1048 
1049 //===-----------------------------------------------------------------------===/
1050 // RedirectingFileSystem implementation
1051 //===-----------------------------------------------------------------------===/
1052 
1053 namespace {
1054 
1055 static llvm::sys::path::Style getExistingStyle(llvm::StringRef Path) {
1056  // Detect the path style in use by checking the first separator.
1058  const size_t n = Path.find_first_of("/\\");
1059  // Can't distinguish between posix and windows_slash here.
1060  if (n != static_cast<size_t>(-1))
1061  style = (Path[n] == '/') ? llvm::sys::path::Style::posix
1063  return style;
1064 }
1065 
1066 /// Removes leading "./" as well as path components like ".." and ".".
1067 static llvm::SmallString<256> canonicalize(llvm::StringRef Path) {
1068  // First detect the path style in use by checking the first separator.
1069  llvm::sys::path::Style style = getExistingStyle(Path);
1070 
1071  // Now remove the dots. Explicitly specifying the path style prevents the
1072  // direction of the slashes from changing.
1075  llvm::sys::path::remove_dots(result, /*remove_dot_dot=*/true, style);
1076  return result;
1077 }
1078 
1079 } // anonymous namespace
1080 
1081 
1082 RedirectingFileSystem::RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
1083  : ExternalFS(std::move(FS)) {
1084  if (ExternalFS)
1085  if (auto ExternalWorkingDirectory =
1086  ExternalFS->getCurrentWorkingDirectory()) {
1087  WorkingDirectory = *ExternalWorkingDirectory;
1088  }
1089 }
1090 
1091 /// Directory iterator implementation for \c RedirectingFileSystem's
1092 /// directory entries.
1095  std::string Dir;
1097 
1098  std::error_code incrementImpl(bool IsFirstTime) {
1099  assert((IsFirstTime || Current != End) && "cannot iterate past end");
1100  if (!IsFirstTime)
1101  ++Current;
1102  if (Current != End) {
1103  SmallString<128> PathStr(Dir);
1104  llvm::sys::path::append(PathStr, (*Current)->getName());
1106  switch ((*Current)->getKind()) {
1111  break;
1114  break;
1115  }
1116  CurrentEntry = directory_entry(std::string(PathStr.str()), Type);
1117  } else {
1119  }
1120  return {};
1121  };
1122 
1123 public:
1126  RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
1127  : Dir(Path.str()), Current(Begin), End(End) {
1128  EC = incrementImpl(/*IsFirstTime=*/true);
1129  }
1130 
1131  std::error_code increment() override {
1132  return incrementImpl(/*IsFirstTime=*/false);
1133  }
1134 };
1135 
1136 namespace {
1137 /// Directory iterator implementation for \c RedirectingFileSystem's
1138 /// directory remap entries that maps the paths reported by the external
1139 /// file system's directory iterator back to the virtual directory's path.
1140 class RedirectingFSDirRemapIterImpl : public llvm::vfs::detail::DirIterImpl {
1141  std::string Dir;
1142  llvm::sys::path::Style DirStyle;
1143  llvm::vfs::directory_iterator ExternalIter;
1144 
1145 public:
1146  RedirectingFSDirRemapIterImpl(std::string DirPath,
1148  : Dir(std::move(DirPath)), DirStyle(getExistingStyle(Dir)),
1149  ExternalIter(ExtIter) {
1150  if (ExternalIter != llvm::vfs::directory_iterator())
1151  setCurrentEntry();
1152  }
1153 
1154  void setCurrentEntry() {
1155  StringRef ExternalPath = ExternalIter->path();
1156  llvm::sys::path::Style ExternalStyle = getExistingStyle(ExternalPath);
1157  StringRef File = llvm::sys::path::filename(ExternalPath, ExternalStyle);
1158 
1159  SmallString<128> NewPath(Dir);
1160  llvm::sys::path::append(NewPath, DirStyle, File);
1161 
1162  CurrentEntry = directory_entry(std::string(NewPath), ExternalIter->type());
1163  }
1164 
1165  std::error_code increment() override {
1166  std::error_code EC;
1167  ExternalIter.increment(EC);
1168  if (!EC && ExternalIter != llvm::vfs::directory_iterator())
1169  setCurrentEntry();
1170  else
1171  CurrentEntry = directory_entry();
1172  return EC;
1173  }
1174 };
1175 } // namespace
1176 
1179  return WorkingDirectory;
1180 }
1181 
1182 std::error_code
1184  // Don't change the working directory if the path doesn't exist.
1185  if (!exists(Path))
1187 
1188  SmallString<128> AbsolutePath;
1189  Path.toVector(AbsolutePath);
1190  if (std::error_code EC = makeAbsolute(AbsolutePath))
1191  return EC;
1192  WorkingDirectory = std::string(AbsolutePath.str());
1193  return {};
1194 }
1195 
1196 std::error_code RedirectingFileSystem::isLocal(const Twine &Path_,
1197  bool &Result) {
1198  SmallString<256> Path;
1199  Path_.toVector(Path);
1200 
1201  if (std::error_code EC = makeCanonical(Path))
1202  return {};
1203 
1204  return ExternalFS->isLocal(Path, Result);
1205 }
1206 
1208  // is_absolute(..., Style::windows_*) accepts paths with both slash types.
1212  return {};
1213 
1214  auto WorkingDir = getCurrentWorkingDirectory();
1215  if (!WorkingDir)
1216  return WorkingDir.getError();
1217 
1218  // We can't use sys::fs::make_absolute because that assumes the path style
1219  // is native and there is no way to override that. Since we know WorkingDir
1220  // is absolute, we can use it to determine which style we actually have and
1221  // append Path ourselves.
1223  if (sys::path::is_absolute(WorkingDir.get(), sys::path::Style::posix)) {
1224  style = sys::path::Style::posix;
1225  } else {
1226  // Distinguish between windows_backslash and windows_slash; getExistingStyle
1227  // returns posix for a path with windows_slash.
1228  if (getExistingStyle(WorkingDir.get()) !=
1231  }
1232 
1233  std::string Result = WorkingDir.get();
1234  StringRef Dir(Result);
1235  if (!Dir.endswith(sys::path::get_separator(style))) {
1236  Result += sys::path::get_separator(style);
1237  }
1238  Result.append(Path.data(), Path.size());
1239  Path.assign(Result.begin(), Result.end());
1240 
1241  return {};
1242 }
1243 
1245  std::error_code &EC) {
1246  SmallString<256> Path;
1247  Dir.toVector(Path);
1248 
1249  EC = makeCanonical(Path);
1250  if (EC)
1251  return {};
1252 
1254  if (!Result) {
1255  EC = Result.getError();
1256  if (shouldFallBackToExternalFS(EC))
1257  return ExternalFS->dir_begin(Path, EC);
1258  return {};
1259  }
1260 
1261  // Use status to make sure the path exists and refers to a directory.
1262  ErrorOr<Status> S = status(Path, Dir, *Result);
1263  if (!S) {
1264  if (shouldFallBackToExternalFS(S.getError(), Result->E))
1265  return ExternalFS->dir_begin(Dir, EC);
1266  EC = S.getError();
1267  return {};
1268  }
1269  if (!S->isDirectory()) {
1270  EC = std::error_code(static_cast<int>(errc::not_a_directory),
1271  std::system_category());
1272  return {};
1273  }
1274 
1275  // Create the appropriate directory iterator based on whether we found a
1276  // DirectoryRemapEntry or DirectoryEntry.
1277  directory_iterator DirIter;
1278  if (auto ExtRedirect = Result->getExternalRedirect()) {
1279  auto RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
1280  DirIter = ExternalFS->dir_begin(*ExtRedirect, EC);
1281 
1282  if (!RE->useExternalName(UseExternalNames)) {
1283  // Update the paths in the results to use the virtual directory's path.
1284  DirIter =
1285  directory_iterator(std::make_shared<RedirectingFSDirRemapIterImpl>(
1286  std::string(Path), DirIter));
1287  }
1288  } else {
1289  auto DE = cast<DirectoryEntry>(Result->E);
1290  DirIter = directory_iterator(std::make_shared<RedirectingFSDirIterImpl>(
1291  Path, DE->contents_begin(), DE->contents_end(), EC));
1292  }
1293 
1294  if (!shouldUseExternalFS())
1295  return DirIter;
1296  return directory_iterator(std::make_shared<CombiningDirIterImpl>(
1297  DirIter, ExternalFS, std::string(Path), EC));
1298 }
1299 
1301  ExternalContentsPrefixDir = PrefixDir.str();
1302 }
1303 
1305  return ExternalContentsPrefixDir;
1306 }
1307 
1309  IsFallthrough = Fallthrough;
1310 }
1311 
1312 std::vector<StringRef> RedirectingFileSystem::getRoots() const {
1313  std::vector<StringRef> R;
1314  for (const auto &Root : Roots)
1315  R.push_back(Root->getName());
1316  return R;
1317 }
1318 
1320  for (const auto &Root : Roots)
1321  dumpEntry(OS, Root.get());
1322 }
1323 
1326  int NumSpaces) const {
1327  StringRef Name = E->getName();
1328  for (int i = 0, e = NumSpaces; i < e; ++i)
1329  OS << " ";
1330  OS << "'" << Name.str().c_str() << "'"
1331  << "\n";
1332 
1333  if (E->getKind() == RedirectingFileSystem::EK_Directory) {
1334  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(E);
1335  assert(DE && "Should be a directory");
1336 
1337  for (std::unique_ptr<Entry> &SubEntry :
1338  llvm::make_range(DE->contents_begin(), DE->contents_end()))
1339  dumpEntry(OS, SubEntry.get(), NumSpaces + 2);
1340  }
1341 }
1342 
1343 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1345 #endif
1346 
1347 /// A helper class to hold the common YAML parsing state.
1349  yaml::Stream &Stream;
1350 
1351  void error(yaml::Node *N, const Twine &Msg) { Stream.printError(N, Msg); }
1352 
1353  // false on error
1354  bool parseScalarString(yaml::Node *N, StringRef &Result,
1355  SmallVectorImpl<char> &Storage) {
1356  const auto *S = dyn_cast<yaml::ScalarNode>(N);
1357 
1358  if (!S) {
1359  error(N, "expected string");
1360  return false;
1361  }
1362  Result = S->getValue(Storage);
1363  return true;
1364  }
1365 
1366  // false on error
1367  bool parseScalarBool(yaml::Node *N, bool &Result) {
1368  SmallString<5> Storage;
1369  StringRef Value;
1370  if (!parseScalarString(N, Value, Storage))
1371  return false;
1372 
1373  if (Value.equals_insensitive("true") || Value.equals_insensitive("on") ||
1374  Value.equals_insensitive("yes") || Value == "1") {
1375  Result = true;
1376  return true;
1377  } else if (Value.equals_insensitive("false") ||
1378  Value.equals_insensitive("off") ||
1379  Value.equals_insensitive("no") || Value == "0") {
1380  Result = false;
1381  return true;
1382  }
1383 
1384  error(N, "expected boolean value");
1385  return false;
1386  }
1387 
1388  struct KeyStatus {
1389  bool Required;
1390  bool Seen = false;
1391 
1392  KeyStatus(bool Required = false) : Required(Required) {}
1393  };
1394 
1395  using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1396 
1397  // false on error
1398  bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
1400  if (!Keys.count(Key)) {
1401  error(KeyNode, "unknown key");
1402  return false;
1403  }
1404  KeyStatus &S = Keys[Key];
1405  if (S.Seen) {
1406  error(KeyNode, Twine("duplicate key '") + Key + "'");
1407  return false;
1408  }
1409  S.Seen = true;
1410  return true;
1411  }
1412 
1413  // false on error
1414  bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
1415  for (const auto &I : Keys) {
1416  if (I.second.Required && !I.second.Seen) {
1417  error(Obj, Twine("missing key '") + I.first + "'");
1418  return false;
1419  }
1420  }
1421  return true;
1422  }
1423 
1424 public:
1427  RedirectingFileSystem::Entry *ParentEntry = nullptr) {
1428  if (!ParentEntry) { // Look for a existent root
1429  for (const auto &Root : FS->Roots) {
1430  if (Name.equals(Root->getName())) {
1431  ParentEntry = Root.get();
1432  return ParentEntry;
1433  }
1434  }
1435  } else { // Advance to the next component
1436  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1437  for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
1438  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1439  auto *DirContent =
1440  dyn_cast<RedirectingFileSystem::DirectoryEntry>(Content.get());
1441  if (DirContent && Name.equals(Content->getName()))
1442  return DirContent;
1443  }
1444  }
1445 
1446  // ... or create a new one
1447  std::unique_ptr<RedirectingFileSystem::Entry> E =
1448  std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1450  std::chrono::system_clock::now(), 0, 0, 0,
1451  file_type::directory_file, sys::fs::all_all));
1452 
1453  if (!ParentEntry) { // Add a new root to the overlay
1454  FS->Roots.push_back(std::move(E));
1455  ParentEntry = FS->Roots.back().get();
1456  return ParentEntry;
1457  }
1458 
1459  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1460  DE->addContent(std::move(E));
1461  return DE->getLastContent();
1462  }
1463 
1464 private:
1465  void uniqueOverlayTree(RedirectingFileSystem *FS,
1467  RedirectingFileSystem::Entry *NewParentE = nullptr) {
1468  StringRef Name = SrcE->getName();
1469  switch (SrcE->getKind()) {
1471  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
1472  // Empty directories could be present in the YAML as a way to
1473  // describe a file for a current directory after some of its subdir
1474  // is parsed. This only leads to redundant walks, ignore it.
1475  if (!Name.empty())
1476  NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
1477  for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1478  llvm::make_range(DE->contents_begin(), DE->contents_end()))
1479  uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1480  break;
1481  }
1483  assert(NewParentE && "Parent entry must exist");
1484  auto *DR = cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
1485  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1486  DE->addContent(
1487  std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1488  Name, DR->getExternalContentsPath(), DR->getUseName()));
1489  break;
1490  }
1492  assert(NewParentE && "Parent entry must exist");
1493  auto *FE = cast<RedirectingFileSystem::FileEntry>(SrcE);
1494  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1495  DE->addContent(std::make_unique<RedirectingFileSystem::FileEntry>(
1496  Name, FE->getExternalContentsPath(), FE->getUseName()));
1497  break;
1498  }
1499  }
1500  }
1501 
1502  std::unique_ptr<RedirectingFileSystem::Entry>
1503  parseEntry(yaml::Node *N, RedirectingFileSystem *FS, bool IsRootEntry) {
1504  auto *M = dyn_cast<yaml::MappingNode>(N);
1505  if (!M) {
1506  error(N, "expected mapping node for file or directory entry");
1507  return nullptr;
1508  }
1509 
1510  KeyStatusPair Fields[] = {
1511  KeyStatusPair("name", true),
1512  KeyStatusPair("type", true),
1513  KeyStatusPair("contents", false),
1514  KeyStatusPair("external-contents", false),
1515  KeyStatusPair("use-external-name", false),
1516  };
1517 
1518  DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1519 
1520  enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1521  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1522  EntryArrayContents;
1523  SmallString<256> ExternalContentsPath;
1525  yaml::Node *NameValueNode = nullptr;
1526  auto UseExternalName = RedirectingFileSystem::NK_NotSet;
1528 
1529  for (auto &I : *M) {
1530  StringRef Key;
1531  // Reuse the buffer for key and value, since we don't look at key after
1532  // parsing value.
1533  SmallString<256> Buffer;
1534  if (!parseScalarString(I.getKey(), Key, Buffer))
1535  return nullptr;
1536 
1537  if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1538  return nullptr;
1539 
1540  StringRef Value;
1541  if (Key == "name") {
1542  if (!parseScalarString(I.getValue(), Value, Buffer))
1543  return nullptr;
1544 
1545  NameValueNode = I.getValue();
1546  // Guarantee that old YAML files containing paths with ".." and "."
1547  // are properly canonicalized before read into the VFS.
1548  Name = canonicalize(Value).str();
1549  } else if (Key == "type") {
1550  if (!parseScalarString(I.getValue(), Value, Buffer))
1551  return nullptr;
1552  if (Value == "file")
1554  else if (Value == "directory")
1556  else if (Value == "directory-remap")
1558  else {
1559  error(I.getValue(), "unknown value for 'type'");
1560  return nullptr;
1561  }
1562  } else if (Key == "contents") {
1563  if (ContentsField != CF_NotSet) {
1564  error(I.getKey(),
1565  "entry already has 'contents' or 'external-contents'");
1566  return nullptr;
1567  }
1568  ContentsField = CF_List;
1569  auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
1570  if (!Contents) {
1571  // FIXME: this is only for directories, what about files?
1572  error(I.getValue(), "expected array");
1573  return nullptr;
1574  }
1575 
1576  for (auto &I : *Contents) {
1577  if (std::unique_ptr<RedirectingFileSystem::Entry> E =
1578  parseEntry(&I, FS, /*IsRootEntry*/ false))
1579  EntryArrayContents.push_back(std::move(E));
1580  else
1581  return nullptr;
1582  }
1583  } else if (Key == "external-contents") {
1584  if (ContentsField != CF_NotSet) {
1585  error(I.getKey(),
1586  "entry already has 'contents' or 'external-contents'");
1587  return nullptr;
1588  }
1589  ContentsField = CF_External;
1590  if (!parseScalarString(I.getValue(), Value, Buffer))
1591  return nullptr;
1592 
1593  SmallString<256> FullPath;
1594  if (FS->IsRelativeOverlay) {
1595  FullPath = FS->getExternalContentsPrefixDir();
1596  assert(!FullPath.empty() &&
1597  "External contents prefix directory must exist");
1598  llvm::sys::path::append(FullPath, Value);
1599  } else {
1600  FullPath = Value;
1601  }
1602 
1603  // Guarantee that old YAML files containing paths with ".." and "."
1604  // are properly canonicalized before read into the VFS.
1605  FullPath = canonicalize(FullPath);
1606  ExternalContentsPath = FullPath.str();
1607  } else if (Key == "use-external-name") {
1608  bool Val;
1609  if (!parseScalarBool(I.getValue(), Val))
1610  return nullptr;
1611  UseExternalName = Val ? RedirectingFileSystem::NK_External
1613  } else {
1614  llvm_unreachable("key missing from Keys");
1615  }
1616  }
1617 
1618  if (Stream.failed())
1619  return nullptr;
1620 
1621  // check for missing keys
1622  if (ContentsField == CF_NotSet) {
1623  error(N, "missing key 'contents' or 'external-contents'");
1624  return nullptr;
1625  }
1626  if (!checkMissingKeys(N, Keys))
1627  return nullptr;
1628 
1629  // check invalid configuration
1631  UseExternalName != RedirectingFileSystem::NK_NotSet) {
1632  error(N, "'use-external-name' is not supported for 'directory' entries");
1633  return nullptr;
1634  }
1635 
1637  ContentsField == CF_List) {
1638  error(N, "'contents' is not supported for 'directory-remap' entries");
1639  return nullptr;
1640  }
1641 
1643  if (IsRootEntry) {
1644  // VFS root entries may be in either Posix or Windows style. Figure out
1645  // which style we have, and use it consistently.
1647  path_style = sys::path::Style::posix;
1648  } else if (sys::path::is_absolute(Name,
1651  } else {
1652  // Relative VFS root entries are made absolute to the current working
1653  // directory, then we can determine the path style from that.
1654  auto EC = sys::fs::make_absolute(Name);
1655  if (EC) {
1656  assert(NameValueNode && "Name presence should be checked earlier");
1657  error(
1658  NameValueNode,
1659  "entry with relative path at the root level is not discoverable");
1660  return nullptr;
1661  }
1665  }
1666  }
1667 
1668  // Remove trailing slash(es), being careful not to remove the root path
1669  StringRef Trimmed = Name;
1670  size_t RootPathLen = sys::path::root_path(Trimmed, path_style).size();
1671  while (Trimmed.size() > RootPathLen &&
1672  sys::path::is_separator(Trimmed.back(), path_style))
1673  Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
1674 
1675  // Get the last component
1676  StringRef LastComponent = sys::path::filename(Trimmed, path_style);
1677 
1678  std::unique_ptr<RedirectingFileSystem::Entry> Result;
1679  switch (Kind) {
1681  Result = std::make_unique<RedirectingFileSystem::FileEntry>(
1682  LastComponent, std::move(ExternalContentsPath), UseExternalName);
1683  break;
1685  Result = std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1686  LastComponent, std::move(ExternalContentsPath), UseExternalName);
1687  break;
1689  Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1690  LastComponent, std::move(EntryArrayContents),
1692  0, 0, 0, file_type::directory_file, sys::fs::all_all));
1693  break;
1694  }
1695 
1696  StringRef Parent = sys::path::parent_path(Trimmed, path_style);
1697  if (Parent.empty())
1698  return Result;
1699 
1700  // if 'name' contains multiple components, create implicit directory entries
1701  for (sys::path::reverse_iterator I = sys::path::rbegin(Parent, path_style),
1702  E = sys::path::rend(Parent);
1703  I != E; ++I) {
1704  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
1705  Entries.push_back(std::move(Result));
1706  Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1707  *I, std::move(Entries),
1709  0, 0, 0, file_type::directory_file, sys::fs::all_all));
1710  }
1711  return Result;
1712  }
1713 
1714 public:
1716 
1717  // false on error
1719  auto *Top = dyn_cast<yaml::MappingNode>(Root);
1720  if (!Top) {
1721  error(Root, "expected mapping node");
1722  return false;
1723  }
1724 
1725  KeyStatusPair Fields[] = {
1726  KeyStatusPair("version", true),
1727  KeyStatusPair("case-sensitive", false),
1728  KeyStatusPair("use-external-names", false),
1729  KeyStatusPair("overlay-relative", false),
1730  KeyStatusPair("fallthrough", false),
1731  KeyStatusPair("roots", true),
1732  };
1733 
1734  DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1735  std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
1736 
1737  // Parse configuration and 'roots'
1738  for (auto &I : *Top) {
1739  SmallString<10> KeyBuffer;
1740  StringRef Key;
1741  if (!parseScalarString(I.getKey(), Key, KeyBuffer))
1742  return false;
1743 
1744  if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1745  return false;
1746 
1747  if (Key == "roots") {
1748  auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
1749  if (!Roots) {
1750  error(I.getValue(), "expected array");
1751  return false;
1752  }
1753 
1754  for (auto &I : *Roots) {
1755  if (std::unique_ptr<RedirectingFileSystem::Entry> E =
1756  parseEntry(&I, FS, /*IsRootEntry*/ true))
1757  RootEntries.push_back(std::move(E));
1758  else
1759  return false;
1760  }
1761  } else if (Key == "version") {
1762  StringRef VersionString;
1763  SmallString<4> Storage;
1764  if (!parseScalarString(I.getValue(), VersionString, Storage))
1765  return false;
1766  int Version;
1767  if (VersionString.getAsInteger<int>(10, Version)) {
1768  error(I.getValue(), "expected integer");
1769  return false;
1770  }
1771  if (Version < 0) {
1772  error(I.getValue(), "invalid version number");
1773  return false;
1774  }
1775  if (Version != 0) {
1776  error(I.getValue(), "version mismatch, expected 0");
1777  return false;
1778  }
1779  } else if (Key == "case-sensitive") {
1780  if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
1781  return false;
1782  } else if (Key == "overlay-relative") {
1783  if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
1784  return false;
1785  } else if (Key == "use-external-names") {
1786  if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
1787  return false;
1788  } else if (Key == "fallthrough") {
1789  if (!parseScalarBool(I.getValue(), FS->IsFallthrough))
1790  return false;
1791  } else {
1792  llvm_unreachable("key missing from Keys");
1793  }
1794  }
1795 
1796  if (Stream.failed())
1797  return false;
1798 
1799  if (!checkMissingKeys(Top, Keys))
1800  return false;
1801 
1802  // Now that we sucessefully parsed the YAML file, canonicalize the internal
1803  // representation to a proper directory tree so that we can search faster
1804  // inside the VFS.
1805  for (auto &E : RootEntries)
1806  uniqueOverlayTree(FS, E.get());
1807 
1808  return true;
1809  }
1810 };
1811 
1812 std::unique_ptr<RedirectingFileSystem>
1813 RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
1815  StringRef YAMLFilePath, void *DiagContext,
1816  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
1817  SourceMgr SM;
1818  yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
1819 
1820  SM.setDiagHandler(DiagHandler, DiagContext);
1821  yaml::document_iterator DI = Stream.begin();
1822  yaml::Node *Root = DI->getRoot();
1823  if (DI == Stream.end() || !Root) {
1824  SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
1825  return nullptr;
1826  }
1827 
1829 
1830  std::unique_ptr<RedirectingFileSystem> FS(
1831  new RedirectingFileSystem(ExternalFS));
1832 
1833  if (!YAMLFilePath.empty()) {
1834  // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
1835  // to each 'external-contents' path.
1836  //
1837  // Example:
1838  // -ivfsoverlay dummy.cache/vfs/vfs.yaml
1839  // yields:
1840  // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
1841  //
1842  SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
1843  std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
1844  assert(!EC && "Overlay dir final path must be absolute");
1845  (void)EC;
1846  FS->setExternalContentsPrefixDir(OverlayAbsDir);
1847  }
1848 
1849  if (!P.parse(Root, FS.get()))
1850  return nullptr;
1851 
1852  return FS;
1853 }
1854 
1855 std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create(
1856  ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1857  bool UseExternalNames, FileSystem &ExternalFS) {
1858  std::unique_ptr<RedirectingFileSystem> FS(
1859  new RedirectingFileSystem(&ExternalFS));
1860  FS->UseExternalNames = UseExternalNames;
1861 
1863 
1864  for (auto &Mapping : llvm::reverse(RemappedFiles)) {
1865  SmallString<128> From = StringRef(Mapping.first);
1866  SmallString<128> To = StringRef(Mapping.second);
1867  {
1868  auto EC = ExternalFS.makeAbsolute(From);
1869  (void)EC;
1870  assert(!EC && "Could not make absolute path");
1871  }
1872 
1873  // Check if we've already mapped this file. The first one we see (in the
1874  // reverse iteration) wins.
1875  RedirectingFileSystem::Entry *&ToEntry = Entries[From];
1876  if (ToEntry)
1877  continue;
1878 
1879  // Add parent directories.
1880  RedirectingFileSystem::Entry *Parent = nullptr;
1881  StringRef FromDirectory = llvm::sys::path::parent_path(From);
1882  for (auto I = llvm::sys::path::begin(FromDirectory),
1883  E = llvm::sys::path::end(FromDirectory);
1884  I != E; ++I) {
1886  Parent);
1887  }
1888  assert(Parent && "File without a directory?");
1889  {
1890  auto EC = ExternalFS.makeAbsolute(To);
1891  (void)EC;
1892  assert(!EC && "Could not make absolute path");
1893  }
1894 
1895  // Add the file.
1896  auto NewFile = std::make_unique<RedirectingFileSystem::FileEntry>(
1898  UseExternalNames ? RedirectingFileSystem::NK_External
1900  ToEntry = NewFile.get();
1901  cast<RedirectingFileSystem::DirectoryEntry>(Parent)->addContent(
1902  std::move(NewFile));
1903  }
1904 
1905  return FS;
1906 }
1907 
1910  : E(E) {
1911  assert(E != nullptr);
1912  // If the matched entry is a DirectoryRemapEntry, set ExternalRedirect to the
1913  // path of the directory it maps to in the external file system plus any
1914  // remaining path components in the provided iterator.
1915  if (auto *DRE = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(E)) {
1916  SmallString<256> Redirect(DRE->getExternalContentsPath());
1917  sys::path::append(Redirect, Start, End,
1918  getExistingStyle(DRE->getExternalContentsPath()));
1919  ExternalRedirect = std::string(Redirect);
1920  }
1921 }
1922 
1923 bool RedirectingFileSystem::shouldFallBackToExternalFS(
1924  std::error_code EC, RedirectingFileSystem::Entry *E) const {
1925  if (E && !isa<RedirectingFileSystem::DirectoryRemapEntry>(E))
1926  return false;
1927  return shouldUseExternalFS() && EC == llvm::errc::no_such_file_or_directory;
1928 }
1929 
1930 std::error_code
1931 RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {
1932  if (std::error_code EC = makeAbsolute(Path))
1933  return EC;
1934 
1935  llvm::SmallString<256> CanonicalPath =
1936  canonicalize(StringRef(Path.data(), Path.size()));
1937  if (CanonicalPath.empty())
1939 
1940  Path.assign(CanonicalPath.begin(), CanonicalPath.end());
1941  return {};
1942 }
1943 
1948  for (const auto &Root : Roots) {
1950  lookupPathImpl(Start, End, Root.get());
1951  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
1952  return Result;
1953  }
1955 }
1956 
1958 RedirectingFileSystem::lookupPathImpl(
1961  assert(!isTraversalComponent(*Start) &&
1962  !isTraversalComponent(From->getName()) &&
1963  "Paths should not contain traversal components");
1964 
1965  StringRef FromName = From->getName();
1966 
1967  // Forward the search to the next component in case this is an empty one.
1968  if (!FromName.empty()) {
1969  if (!pathComponentMatches(*Start, FromName))
1971 
1972  ++Start;
1973 
1974  if (Start == End) {
1975  // Match!
1976  return LookupResult(From, Start, End);
1977  }
1978  }
1979 
1980  if (isa<RedirectingFileSystem::FileEntry>(From))
1982 
1983  if (isa<RedirectingFileSystem::DirectoryRemapEntry>(From))
1984  return LookupResult(From, Start, End);
1985 
1986  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(From);
1987  for (const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
1988  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1990  lookupPathImpl(Start, End, DirEntry.get());
1991  if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
1992  return Result;
1993  }
1994 
1996 }
1997 
1998 static Status getRedirectedFileStatus(const Twine &OriginalPath,
1999  bool UseExternalNames,
2000  Status ExternalStatus) {
2001  Status S = ExternalStatus;
2002  if (!UseExternalNames)
2003  S = Status::copyWithNewName(S, OriginalPath);
2004  S.IsVFSMapped = true;
2005  return S;
2006 }
2007 
2008 ErrorOr<Status> RedirectingFileSystem::status(
2009  const Twine &CanonicalPath, const Twine &OriginalPath,
2010  const RedirectingFileSystem::LookupResult &Result) {
2011  if (Optional<StringRef> ExtRedirect = Result.getExternalRedirect()) {
2012  SmallString<256> CanonicalRemappedPath((*ExtRedirect).str());
2013  if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2014  return EC;
2015 
2016  ErrorOr<Status> S = ExternalFS->status(CanonicalRemappedPath);
2017  if (!S)
2018  return S;
2019  S = Status::copyWithNewName(*S, *ExtRedirect);
2020  auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result.E);
2021  return getRedirectedFileStatus(OriginalPath,
2022  RE->useExternalName(UseExternalNames), *S);
2023  }
2024 
2025  auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E);
2026  return Status::copyWithNewName(DE->getStatus(), CanonicalPath);
2027 }
2028 
2030 RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath,
2031  const Twine &OriginalPath) const {
2032  if (auto Result = ExternalFS->status(CanonicalPath)) {
2033  return Result.get().copyWithNewName(Result.get(), OriginalPath);
2034  } else {
2035  return Result.getError();
2036  }
2037 }
2038 
2039 ErrorOr<Status> RedirectingFileSystem::status(const Twine &OriginalPath) {
2040  SmallString<256> CanonicalPath;
2041  OriginalPath.toVector(CanonicalPath);
2042 
2043  if (std::error_code EC = makeCanonical(CanonicalPath))
2044  return EC;
2045 
2047  lookupPath(CanonicalPath);
2048  if (!Result) {
2049  if (shouldFallBackToExternalFS(Result.getError())) {
2050  return getExternalStatus(CanonicalPath, OriginalPath);
2051  }
2052  return Result.getError();
2053  }
2054 
2055  ErrorOr<Status> S = status(CanonicalPath, OriginalPath, *Result);
2056  if (!S && shouldFallBackToExternalFS(S.getError(), Result->E)) {
2057  return getExternalStatus(CanonicalPath, OriginalPath);
2058  }
2059 
2060  return S;
2061 }
2062 
2063 namespace {
2064 
2065 /// Provide a file wrapper with an overriden status.
2066 class FileWithFixedStatus : public File {
2067  std::unique_ptr<File> InnerFile;
2068  Status S;
2069 
2070 public:
2071  FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
2072  : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
2073 
2074  ErrorOr<Status> status() override { return S; }
2076 
2077  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
2078  bool IsVolatile) override {
2079  return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
2080  IsVolatile);
2081  }
2082 
2083  std::error_code close() override { return InnerFile->close(); }
2084 
2085  void setPath(const Twine &Path) override { S = S.copyWithNewName(S, Path); }
2086 };
2087 
2088 } // namespace
2089 
2091 File::getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P) {
2092  if (!Result)
2093  return Result;
2094 
2096  auto Name = F->get()->getName();
2097  if (Name && Name.get() != P.str())
2098  F->get()->setPath(P);
2099  return F;
2100 }
2101 
2104  SmallString<256> CanonicalPath;
2105  OriginalPath.toVector(CanonicalPath);
2106 
2107  if (std::error_code EC = makeCanonical(CanonicalPath))
2108  return EC;
2109 
2111  lookupPath(CanonicalPath);
2112  if (!Result) {
2113  if (shouldFallBackToExternalFS(Result.getError()))
2114  return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
2115  OriginalPath);
2116 
2117  return Result.getError();
2118  }
2119 
2120  if (!Result->getExternalRedirect()) // FIXME: errc::not_a_file?
2122 
2123  StringRef ExtRedirect = *Result->getExternalRedirect();
2124  SmallString<256> CanonicalRemappedPath(ExtRedirect.str());
2125  if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2126  return EC;
2127 
2128  auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
2129 
2130  auto ExternalFile = File::getWithPath(
2131  ExternalFS->openFileForRead(CanonicalRemappedPath), ExtRedirect);
2132  if (!ExternalFile) {
2133  if (shouldFallBackToExternalFS(ExternalFile.getError(), Result->E))
2134  return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
2135  OriginalPath);
2136  return ExternalFile;
2137  }
2138 
2139  auto ExternalStatus = (*ExternalFile)->status();
2140  if (!ExternalStatus)
2141  return ExternalStatus.getError();
2142 
2143  // FIXME: Update the status with the name and VFSMapped.
2145  OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);
2146  return std::unique_ptr<File>(
2147  std::make_unique<FileWithFixedStatus>(std::move(*ExternalFile), S));
2148 }
2149 
2150 std::error_code
2152  SmallVectorImpl<char> &Output) const {
2153  SmallString<256> Path;
2154  Path_.toVector(Path);
2155 
2156  if (std::error_code EC = makeCanonical(Path))
2157  return EC;
2158 
2160  if (!Result) {
2161  if (shouldFallBackToExternalFS(Result.getError()))
2162  return ExternalFS->getRealPath(Path, Output);
2163  return Result.getError();
2164  }
2165 
2166  // If we found FileEntry or DirectoryRemapEntry, look up the mapped
2167  // path in the external file system.
2168  if (auto ExtRedirect = Result->getExternalRedirect()) {
2169  auto P = ExternalFS->getRealPath(*ExtRedirect, Output);
2170  if (!P && shouldFallBackToExternalFS(P, Result->E)) {
2171  return ExternalFS->getRealPath(Path, Output);
2172  }
2173  return P;
2174  }
2175 
2176  // If we found a DirectoryEntry, still fall back to ExternalFS if allowed,
2177  // because directories don't have a single external contents path.
2178  return shouldUseExternalFS() ? ExternalFS->getRealPath(Path, Output)
2180 }
2181 
2182 std::unique_ptr<FileSystem>
2183 vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2185  StringRef YAMLFilePath, void *DiagContext,
2186  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2188  YAMLFilePath, DiagContext,
2189  std::move(ExternalFS));
2190 }
2191 
2194  SmallVectorImpl<YAMLVFSEntry> &Entries) {
2195  auto Kind = SrcE->getKind();
2197  auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
2198  assert(DE && "Must be a directory");
2199  for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
2200  llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2201  Path.push_back(SubEntry->getName());
2202  getVFSEntries(SubEntry.get(), Path, Entries);
2203  Path.pop_back();
2204  }
2205  return;
2206  }
2207 
2209  auto *DR = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
2210  assert(DR && "Must be a directory remap");
2211  SmallString<128> VPath;
2212  for (auto &Comp : Path)
2213  llvm::sys::path::append(VPath, Comp);
2214  Entries.push_back(
2215  YAMLVFSEntry(VPath.c_str(), DR->getExternalContentsPath()));
2216  return;
2217  }
2218 
2219  assert(Kind == RedirectingFileSystem::EK_File && "Must be a EK_File");
2220  auto *FE = dyn_cast<RedirectingFileSystem::FileEntry>(SrcE);
2221  assert(FE && "Must be a file");
2222  SmallString<128> VPath;
2223  for (auto &Comp : Path)
2224  llvm::sys::path::append(VPath, Comp);
2225  Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
2226 }
2227 
2228 void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2230  StringRef YAMLFilePath,
2231  SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
2232  void *DiagContext,
2233  IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2234  std::unique_ptr<RedirectingFileSystem> VFS = RedirectingFileSystem::create(
2235  std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
2236  std::move(ExternalFS));
2237  if (!VFS)
2238  return;
2240  VFS->lookupPath("/");
2241  if (!RootResult)
2242  return;
2243  SmallVector<StringRef, 8> Components;
2244  Components.push_back("/");
2245  getVFSEntries(RootResult->E, Components, CollectedEntries);
2246 }
2247 
2249  static std::atomic<unsigned> UID;
2250  unsigned ID = ++UID;
2251  // The following assumes that uint64_t max will never collide with a real
2252  // dev_t value from the OS.
2254 }
2255 
2256 void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,
2257  bool IsDirectory) {
2258  assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
2259  assert(sys::path::is_absolute(RealPath) && "real path not absolute");
2260  assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
2261  Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2262 }
2263 
2265  addEntry(VirtualPath, RealPath, /*IsDirectory=*/false);
2266 }
2267 
2269  StringRef RealPath) {
2270  addEntry(VirtualPath, RealPath, /*IsDirectory=*/true);
2271 }
2272 
2273 namespace {
2274 
2275 class JSONWriter {
2276  llvm::raw_ostream &OS;
2277  SmallVector<StringRef, 16> DirStack;
2278 
2279  unsigned getDirIndent() { return 4 * DirStack.size(); }
2280  unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
2281  bool containedIn(StringRef Parent, StringRef Path);
2282  StringRef containedPart(StringRef Parent, StringRef Path);
2283  void startDirectory(StringRef Path);
2284  void endDirectory();
2285  void writeEntry(StringRef VPath, StringRef RPath);
2286 
2287 public:
2288  JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
2289 
2290  void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
2291  Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
2292  StringRef OverlayDir);
2293 };
2294 
2295 } // namespace
2296 
2297 bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
2298  using namespace llvm::sys;
2299 
2300  // Compare each path component.
2301  auto IParent = path::begin(Parent), EParent = path::end(Parent);
2302  for (auto IChild = path::begin(Path), EChild = path::end(Path);
2303  IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2304  if (*IParent != *IChild)
2305  return false;
2306  }
2307  // Have we exhausted the parent path?
2308  return IParent == EParent;
2309 }
2310 
2311 StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
2312  assert(!Parent.empty());
2313  assert(containedIn(Parent, Path));
2314  return Path.slice(Parent.size() + 1, StringRef::npos);
2315 }
2316 
2317 void JSONWriter::startDirectory(StringRef Path) {
2318  StringRef Name =
2319  DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
2320  DirStack.push_back(Path);
2321  unsigned Indent = getDirIndent();
2322  OS.indent(Indent) << "{\n";
2323  OS.indent(Indent + 2) << "'type': 'directory',\n";
2324  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
2325  OS.indent(Indent + 2) << "'contents': [\n";
2326 }
2327 
2328 void JSONWriter::endDirectory() {
2329  unsigned Indent = getDirIndent();
2330  OS.indent(Indent + 2) << "]\n";
2331  OS.indent(Indent) << "}";
2332 
2333  DirStack.pop_back();
2334 }
2335 
2336 void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
2337  unsigned Indent = getFileIndent();
2338  OS.indent(Indent) << "{\n";
2339  OS.indent(Indent + 2) << "'type': 'file',\n";
2340  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
2341  OS.indent(Indent + 2) << "'external-contents': \""
2342  << llvm::yaml::escape(RPath) << "\"\n";
2343  OS.indent(Indent) << "}";
2344 }
2345 
2347  Optional<bool> UseExternalNames,
2348  Optional<bool> IsCaseSensitive,
2349  Optional<bool> IsOverlayRelative,
2350  StringRef OverlayDir) {
2351  using namespace llvm::sys;
2352 
2353  OS << "{\n"
2354  " 'version': 0,\n";
2355  if (IsCaseSensitive.hasValue())
2356  OS << " 'case-sensitive': '"
2357  << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
2358  if (UseExternalNames.hasValue())
2359  OS << " 'use-external-names': '"
2360  << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
2361  bool UseOverlayRelative = false;
2362  if (IsOverlayRelative.hasValue()) {
2363  UseOverlayRelative = IsOverlayRelative.getValue();
2364  OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
2365  << "',\n";
2366  }
2367  OS << " 'roots': [\n";
2368 
2369  if (!Entries.empty()) {
2370  const YAMLVFSEntry &Entry = Entries.front();
2371 
2372  startDirectory(
2373  Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath)
2374  );
2375 
2376  StringRef RPath = Entry.RPath;
2377  if (UseOverlayRelative) {
2378  unsigned OverlayDirLen = OverlayDir.size();
2379  assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
2380  "Overlay dir must be contained in RPath");
2381  RPath = RPath.slice(OverlayDirLen, RPath.size());
2382  }
2383 
2384  bool IsCurrentDirEmpty = true;
2385  if (!Entry.IsDirectory) {
2386  writeEntry(path::filename(Entry.VPath), RPath);
2387  IsCurrentDirEmpty = false;
2388  }
2389 
2390  for (const auto &Entry : Entries.slice(1)) {
2391  StringRef Dir =
2392  Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath);
2393  if (Dir == DirStack.back()) {
2394  if (!IsCurrentDirEmpty) {
2395  OS << ",\n";
2396  }
2397  } else {
2398  bool IsDirPoppedFromStack = false;
2399  while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
2400  OS << "\n";
2401  endDirectory();
2402  IsDirPoppedFromStack = true;
2403  }
2404  if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2405  OS << ",\n";
2406  }
2407  startDirectory(Dir);
2408  IsCurrentDirEmpty = true;
2409  }
2410  StringRef RPath = Entry.RPath;
2411  if (UseOverlayRelative) {
2412  unsigned OverlayDirLen = OverlayDir.size();
2413  assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
2414  "Overlay dir must be contained in RPath");
2415  RPath = RPath.slice(OverlayDirLen, RPath.size());
2416  }
2417  if (!Entry.IsDirectory) {
2418  writeEntry(path::filename(Entry.VPath), RPath);
2419  IsCurrentDirEmpty = false;
2420  }
2421  }
2422 
2423  while (!DirStack.empty()) {
2424  OS << "\n";
2425  endDirectory();
2426  }
2427  OS << "\n";
2428  }
2429 
2430  OS << " ]\n"
2431  << "}\n";
2432 }
2433 
2435  llvm::sort(Mappings, [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
2436  return LHS.VPath < RHS.VPath;
2437  });
2438 
2439  JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
2440  IsOverlayRelative, OverlayDir);
2441 }
2442 
2444  FileSystem &FS_, const Twine &Path, std::error_code &EC)
2445  : FS(&FS_) {
2446  directory_iterator I = FS->dir_begin(Path, EC);
2447  if (I != directory_iterator()) {
2448  State = std::make_shared<detail::RecDirIterState>();
2449  State->Stack.push(I);
2450  }
2451 }
2452 
2455  assert(FS && State && !State->Stack.empty() && "incrementing past end");
2456  assert(!State->Stack.top()->path().empty() && "non-canonical end iterator");
2458 
2459  if (State->HasNoPushRequest)
2460  State->HasNoPushRequest = false;
2461  else {
2462  if (State->Stack.top()->type() == sys::fs::file_type::directory_file) {
2463  vfs::directory_iterator I = FS->dir_begin(State->Stack.top()->path(), EC);
2464  if (I != End) {
2465  State->Stack.push(I);
2466  return *this;
2467  }
2468  }
2469  }
2470 
2471  while (!State->Stack.empty() && State->Stack.top().increment(EC) == End)
2472  State->Stack.pop();
2473 
2474  if (State->Stack.empty())
2475  State.reset(); // end iterator
2476 
2477  return *this;
2478 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
llvm::vfs::RedirectingFileSystem::EK_File
@ EK_File
Definition: VirtualFileSystem.h:625
MemoryBuffer.h
llvm::StringRef::back
LLVM_NODISCARD char back() const
back - Get the last character in the string.
Definition: StringRef.h:167
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:1093
llvm::vfs::RedirectingFileSystemParser::lookupOrCreateEntry
static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)
Definition: VirtualFileSystem.cpp:1426
getRedirectedFileStatus
static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus)
Definition: VirtualFileSystem.cpp:1998
llvm::vfs::InMemoryFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:1011
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:510
llvm::vfs::Status::isRegularFile
bool isRegularFile() const
Definition: VirtualFileSystem.cpp:103
llvm::vfs::RedirectingFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:1183
llvm
This is an optimization pass for GlobalISel generic memory operations.
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:1178
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.
llvm::vfs::getUniqueID
static sys::fs::UniqueID getUniqueID(hash_code Hash)
Definition: VirtualFileSystem.cpp:723
getVFSEntries
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
Definition: VirtualFileSystem.cpp:2192
Optional.h
llvm::sys::fs::directory_entry::type
file_type type() const
Definition: FileSystem.h:1385
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:494
llvm::vfs::detail::DirIterImpl::CurrentEntry
directory_entry CurrentEntry
Definition: VirtualFileSystem.h:162
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:298
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:365
llvm::sys::path::Style::posix
@ posix
llvm::StringRef::endswith
LLVM_NODISCARD bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:296
llvm::vfs::InMemoryFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: VirtualFileSystem.h:493
llvm::vfs::RedirectingFileSystem::LookupResult::E
Entry * E
The entry the looked-up path corresponds to.
Definition: VirtualFileSystem.h:734
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:995
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:1308
llvm::vfs::RedirectingFileSystemParser::parse
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)
Definition: VirtualFileSystem.cpp:1718
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:1813
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1030
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:704
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:59
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1177
Path.h
llvm::vfs::InMemoryFileSystem::useNormalizedPaths
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
Definition: VirtualFileSystem.h:486
llvm::vfs::RedirectingFileSystem::NK_External
@ NK_External
Definition: VirtualFileSystem.h:626
llvm::vfs::InMemoryFileSystem::InMemoryFileSystem
InMemoryFileSystem(bool UseNormalizedPaths=true)
Definition: VirtualFileSystem.cpp:737
llvm::sys::path::is_absolute
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:672
ErrorHandling.h
llvm::sys::path::reverse_iterator
Reverse path iterator.
Definition: Path.h:100
Content
T Content
Definition: ELFObjHandler.cpp:89
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:155
llvm::vfs::detail::InMemoryDirectory::const_iterator
decltype(Entries)::const_iterator const_iterator
Definition: VirtualFileSystem.cpp:689
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:1029
Errc.h
llvm::vfs::RedirectingFileSystem::Entry::getName
StringRef getName() const
Definition: VirtualFileSystem.h:637
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:169
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:414
llvm::vfs::detail::InMemoryNode::getKind
InMemoryNodeKind getKind() const
Definition: VirtualFileSystem.cpp:579
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:236
llvm::vfs::OverlayFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: VirtualFileSystem.cpp:436
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:227
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::sys::path::Style::windows_backslash
@ windows_backslash
llvm::errc::no_such_file_or_directory
@ no_such_file_or_directory
llvm::vfs::RedirectingFileSystem::EK_Directory
@ EK_Directory
Definition: VirtualFileSystem.h:625
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
RHS
Value * RHS
Definition: X86PartialReduction.cpp:74
llvm::vfs::detail::IME_Directory
@ IME_Directory
Definition: VirtualFileSystem.cpp:563
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:731
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:868
llvm::vfs::detail::InMemoryNode::getFileName
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
Definition: VirtualFileSystem.cpp:578
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:2103
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:457
llvm::vfs::RedirectingFileSystem
A virtual file system parsed from a YAML file.
Definition: VirtualFileSystem.h:623
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:55
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:1196
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:148
llvm::sys::TimePoint
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:34
llvm::vfs::OverlayFileSystem::overlays_end
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
Definition: VirtualFileSystem.h:365
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:355
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:289
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:457
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:610
llvm::vfs::detail::InMemoryDirectory::addChild
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
Definition: VirtualFileSystem.cpp:684
LHS
Value * LHS
Definition: X86PartialReduction.cpp:73
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:414
llvm::vfs::detail::InMemoryDirectory::getChild
InMemoryNode * getChild(StringRef Name)
Definition: VirtualFileSystem.cpp:677
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:2151
llvm::orc::tpctypes::LookupResult
std::vector< JITTargetAddress > LookupResult
Definition: TargetProcessControlTypes.h:119
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:84
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:691
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:122
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:184
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:361
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:349
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:1131
SMLoc.h
llvm::vfs::directory_entry::path
llvm::StringRef path() const
Definition: VirtualFileSystem.h:147
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:638
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:152
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:665
llvm::sys::fs::UniqueID::getFile
uint64_t getFile() const
Definition: UniqueID.h:48
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:138
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:244
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:509
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:261
SourceMgr.h
llvm::vfs::detail::InMemoryNode
The in memory file system is a tree of Nodes.
Definition: VirtualFileSystem.cpp:567
llvm::vfs::getDirectoryID
static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)
Definition: VirtualFileSystem.cpp:732
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:186
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::X86AS::FS
@ FS
Definition: X86.h:188
llvm::vfs::detail::InMemoryDirectory::getUniqueID
UniqueID getUniqueID() const
Definition: VirtualFileSystem.cpp:675
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:1304
pathHasTraversal
static bool pathHasTraversal(StringRef Path)
Definition: VirtualFileSystem.cpp:162
llvm::vfs::Status::isOther
bool isOther() const
Definition: VirtualFileSystem.cpp:105
llvm::vfs::detail::IME_HardLink
@ IME_HardLink
Definition: VirtualFileSystem.cpp:563
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
llvm::Optional::getValueOr
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:298
llvm::vfs::detail::InMemoryDirectory::InMemoryDirectory
InMemoryDirectory(Status Stat)
Definition: VirtualFileSystem.cpp:665
llvm::SmallString::c_str
const char * c_str()
Definition: SmallString.h:262
isTraversalComponent
static bool isTraversalComponent(StringRef Component)
Definition: VirtualFileSystem.cpp:158
llvm::sys::fs::file_type::type_unknown
@ type_unknown
llvm::vfs::RedirectingFileSystem::EntryKind
EntryKind
Definition: VirtualFileSystem.h:625
llvm::sys::fs::UniqueID
Definition: UniqueID.h:26
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
UniqueID.h
llvm::vfs::Status::getName
StringRef getName() const
Returns the name that should be used for this file or directory.
Definition: VirtualFileSystem.h:75
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:716
llvm::vfs::getRealFileSystem
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition: VirtualFileSystem.cpp:360
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:519
llvm::vfs::recursive_directory_iterator::increment
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition: VirtualFileSystem.cpp:2454
llvm::StringRef::empty
constexpr LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:152
uint64_t
llvm::sys::path::get_separator
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition: Path.cpp:610
llvm::vfs::Status::copyWithNewSize
static Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
Definition: VirtualFileSystem.cpp:78
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:340
llvm::vfs::detail::InMemoryFile
Definition: VirtualFileSystem.cpp:583
llvm::vfs::File::getWithPath
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File >> Result, const Twine &P)
Definition: VirtualFileSystem.cpp:2091
llvm::vfs::detail::InMemoryDirectory::getStatus
Status getStatus(const Twine &RequestedName) const
Return the Status for this node.
Definition: VirtualFileSystem.cpp:671
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:595
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::vfs::Status::isDirectory
bool isDirectory() const
Definition: VirtualFileSystem.cpp:101
llvm::DenseMap
Definition: DenseMap.h:714
llvm::vfs::InMemoryFileSystem::toString
std::string toString() const
Definition: VirtualFileSystem.cpp:747
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:598
I
#define I(x, y, z)
Definition: MD5.cpp:58
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:1244
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:1300
llvm::sys::path::parent_path
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:468
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:1707
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:1449
iterator_range.h
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:903
llvm::vfs::RedirectingFileSystemParser
A helper class to hold the common YAML parsing state.
Definition: VirtualFileSystem.cpp:1348
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:923
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:2248
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:1094
llvm::vfs::RedirectingFileSystem::getRoots
std::vector< llvm::StringRef > getRoots() const
Definition: VirtualFileSystem.cpp:1312
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
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:1344
llvm::vfs::detail::InMemoryDirectory
Definition: VirtualFileSystem.cpp:660
llvm::vfs::detail::InMemoryDirectory::end
const_iterator end() const
Definition: VirtualFileSystem.cpp:692
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:82
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:2434
LLVM_FALLTHROUGH
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:290
llvm::vfs::InMemoryFileSystem::addHardLink
bool addHardLink(const Twine &From, const Twine &To)
Add a hard link to a file.
Definition: VirtualFileSystem.cpp:911
llvm::sys::path::const_iterator
Path iterator.
Definition: Path.h:74
llvm::vfs::File
Represents an open file.
Definition: VirtualFileSystem.h:101
VirtualFileSystem.h
llvm::vfs::directory_entry::type
llvm::sys::fs::file_type type() const
Definition: VirtualFileSystem.h:148
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:109
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:856
StringSet.h
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:156
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:1324
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:219
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:625
llvm::vfs::FileSystem
The virtual file system interface.
Definition: VirtualFileSystem.h:255
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::vfs::InMemoryFileSystem
An in-memory file system.
Definition: VirtualFileSystem.h:426
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:678
llvm::vfs::RedirectingFileSystem::LookupResult::LookupResult
LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
Definition: VirtualFileSystem.cpp:1908
llvm::vfs::detail::InMemoryNode::InMemoryNode
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
Definition: VirtualFileSystem.cpp:572
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:1945
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:550
Casting.h
llvm::vfs::RedirectingFileSystem::NK_Virtual
@ NK_Virtual
Definition: VirtualFileSystem.h:626
llvm::vfs::RedirectingFileSystem::NK_NotSet
@ NK_NotSet
Definition: VirtualFileSystem.h:626
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1590
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:2264
llvm::sys::fs::is_directory
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:1089
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:1124
llvm::vfs::OverlayFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition: VirtualFileSystem.cpp:442
llvm::vfs::Status::exists
bool exists() const
Definition: VirtualFileSystem.cpp:113
llvm::errorToErrorCode
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition: Error.cpp:96
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:1041
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:407
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:599
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:602
llvm::sys::fs::directory_iterator
directory_iterator - Iterates through the entries in path.
Definition: FileSystem.h:1423
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:425
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:588
llvm::sys::path::filename
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:578
Version
uint64_t Version
Definition: RawMemProfReader.cpp:25
llvm::vfs::RedirectingFileSystemParser::RedirectingFileSystemParser
RedirectingFileSystemParser(yaml::Stream &S)
Definition: VirtualFileSystem.cpp:1715
SmallVector.h
llvm::hash_combine
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:605
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:1377
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:45
llvm::vfs::detail::InMemoryFile::classof
static bool classof(const InMemoryNode *N)
Definition: VirtualFileSystem.cpp:604
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:732
llvm::vfs::detail::InMemoryDirectory::classof
static bool classof(const InMemoryNode *N)
Definition: VirtualFileSystem.cpp:702
llvm::vfs::detail::IME_File
@ IME_File
Definition: VirtualFileSystem.cpp:563
llvm::vfs::YAMLVFSWriter::addDirectoryMapping
void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
Definition: VirtualFileSystem.cpp:2268
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::sys::path::Style::windows_slash
@ windows_slash
llvm::SmallVectorImpl< char >
llvm::sys::path::rend
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
Definition: Path.cpp:307
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:143
llvm::vfs::detail::InMemoryNodeKind
InMemoryNodeKind
Definition: VirtualFileSystem.cpp:563
llvm::vfs::FileSystem::makeAbsolute
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
Definition: VirtualFileSystem.cpp:131
llvm::vfs::getFileID
static sys::fs::UniqueID getFileID(sys::fs::UniqueID Parent, llvm::StringRef Name, llvm::StringRef Contents)
Definition: VirtualFileSystem.cpp:727
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:409
llvm::vfs::detail::InMemoryFile::toString
std::string toString(unsigned Indent) const override
Definition: VirtualFileSystem.cpp:600
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:1207
llvm::vfs::Status::equivalent
bool equivalent(const Status &Other) const
Definition: VirtualFileSystem.cpp:96
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::vfs::OverlayFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition: VirtualFileSystem.cpp:449
llvm::vfs::detail::InMemoryDirectory::toString
std::string toString(unsigned Indent) const override
Definition: VirtualFileSystem.cpp:694
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:127
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:931
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::vfs::Status::isStatusKnown
bool isStatusKnown() const
Definition: VirtualFileSystem.cpp:111
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:283
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:1198
llvm::vfs::RedirectingFileSystem::Entry
A single file or directory in the VFS.
Definition: VirtualFileSystem.h:629
write
static void write(bool isBE, void *P, T V)
Definition: RuntimeDyldELF.cpp:37
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::vfs::FileSystem::~FileSystem
virtual ~FileSystem()
llvm::hash_code
An opaque object representing a hash code.
Definition: Hashing.h:73
llvm::vfs::OverlayFileSystem::OverlayFileSystem
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
Definition: VirtualFileSystem.cpp:403