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