[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-10-01 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

> I would call it a requirement instead of an assumption. The replay must be 
> exactly the same (even the file stats and reads). If Clang reads the file in 
> replay which was only stat()ed during compilation, it indicates 
> non-determinism or something wrong (in clang or FS).
>  We currently deal with such files by adding empty buffers for them based on 
> this assumption/requirement only.

Does adding a flag to clang to skip the module inputs checks seems 
feasible/reasonable? +1 to Sam's comments, the mode for FS that has the file 
sizes, but not the file contents seems too specific for the use-case at hand, 
does not fit well into the design.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: lib/Basic/VirtualFileSystem.cpp:2097
 void YAMLVFSWriter::write(llvm::raw_ostream ) {
-  llvm::sort(Mappings, [](const YAMLVFSEntry , const YAMLVFSEntry ) {
+  llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry , const YAMLVFSEntry ) {

kbobyrev wrote:
> This used `llvm::sort(Container &, Compare Comp)` before, I would think 
> that the range-based API is the preferred one. There's also a cleanup patch 
> migrating STL-like calls to idiomatic LLVM's STL Extension API: D52576.
I think these are some very recent changes and does not belong to my patch. 
Will sync these. Thanks for pointing out.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

> it sounds like this is for record-replay.

Yes this is for record-replay purpose.

> What are these files in practice?

During loading a modules the files that were required to make the module are 
stat()ed and their sizes are used to verify that the module is still valid. 
There are occurrences of more stat() only files (apart from the use in modules) 
which I am not aware of.

> In the replayed compilation, we assume the accessed files are the same, is it 
> safe to assume we never read files we previously stat()ed?

I would call it a requirement instead of an assumption. The replay must be 
exactly the same (even the file stats and reads). If Clang reads the file in 
replay which was only stat()ed during compilation, it indicates non-determinism 
or something wrong (in clang or FS).
We currently deal with such files by adding empty buffers for them based on 
this assumption/requirement only.

> it seems like this could also be achieved with an overlayFS adding a simple 
> specialized FS that only provides the stat-only files. If this is a 
> relatively niche feature, cramming it into InMemoryFileSystem may not be the 
> best option. Any thoughts on the tradeoff here?

We can reuse the InMemoryFS to make another FS which just serves stat-only 
files. A tradeoff I can think of is: we might need to store a random buffer of 
required size to make final status of the file correct.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread Kirill Bobyrev via Phabricator via cfe-commits
kbobyrev added inline comments.



Comment at: lib/Basic/VirtualFileSystem.cpp:2097
 void YAMLVFSWriter::write(llvm::raw_ostream ) {
-  llvm::sort(Mappings, [](const YAMLVFSEntry , const YAMLVFSEntry ) {
+  llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry , const YAMLVFSEntry ) {

This used `llvm::sort(Container &, Compare Comp)` before, I would think that 
the range-based API is the preferred one. There's also a cleanup patch 
migrating STL-like calls to idiomatic LLVM's STL Extension API: D52576.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread Sam McCall via Phabricator via cfe-commits
sammccall added a comment.

Could you give some more detail about what this is for?

- it sounds like this is for record-replay. In the replayed compilation, we 
assume the accessed files are the same, is it safe to assume we never read 
files we previously stat()ed? What are these files in practice?
- it seems like this could also be achieved with an overlayFS adding a simple 
specialized FS that only provides the stat-only files. If this is a relatively 
niche feature, cramming it into InMemoryFileSystem may not be the best option. 
Any thoughts on the tradeoff here?




Comment at: include/clang/Basic/VirtualFileSystem.h:414
+  // Add a file with the given size but with no contents. The buffer of this
+  // file must never be requested.
+  /// \return true if the file successfully added, false if the file already

Please add some motivation here, e.g. "such files are useful when replaying a 
recorded compilation, if the original compilation never read the file contents"



Comment at: lib/Basic/VirtualFileSystem.cpp:495
   std::unique_ptr Buffer;
+  bool StatOnlyFile;
 

can't you just represent this by a null buffer?


Repository:
  rC Clang

https://reviews.llvm.org/D52620



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-27 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: cfe-commits, mgrang.

Some files are only Statted by Clang and not read. Clang mostly uses
them for checking the existence of some files and in rare cases uses the
value of the Status to proceed further (for example while loading
module files, it checks the sizes of some files).

This change adds support to represent files that are supposed to be only
statted by Clang.


Repository:
  rC Clang

https://reviews.llvm.org/D52620

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -553,8 +553,8 @@
   for (DirIter E; !EC && I != E; I.increment(EC))
 InputToCheck.push_back(I->path());
 
-  llvm::sort(InputToCheck);
-  llvm::sort(Expected);
+  llvm::sort(InputToCheck.begin(), InputToCheck.end());
+  llvm::sort(Expected.begin(), Expected.end());
   EXPECT_EQ(InputToCheck.size(), Expected.size());
 
   unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
@@ -1063,15 +1063,50 @@
 TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) {
   std::error_code EC;
   FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string"));
+  FS.addStatOnlyFile("/a/d", 0, 10);
   EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b"));
   auto I = vfs::recursive_directory_iterator(FS, "/", EC);
   ASSERT_FALSE(EC);
   std::vector Nodes;
   for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
I.increment(EC)) {
 Nodes.push_back(getPosixPath(I->path()));
   }
-  EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d"));
+  EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/d", "/a/b",
+   "/c", "/c/d"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddStatOnlyFileWithCorrectSize) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  auto Stat = FS.status("/a/b");
+  EXPECT_EQ(Stat.get().getSize(), 10);
+}
+
+TEST_F(InMemoryFileSystemTest, AddMultipleFilesUnderStatOnlyFile) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  EXPECT_FALSE(FS.addStatOnlyFile("/a/b", 0, 11));
+  EXPECT_TRUE(FS.addStatOnlyFile("/a/b", 0, 10));
+  EXPECT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content")));
+}
+
+TEST_F(InMemoryFileSystemTest, DeathWhenBufferRequestedForStatOnlyFile) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  EXPECT_DEATH(FS.getBufferForFile("/a/b"),
+   "Cannot get buffer for StatOnlyFile");
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinksToStatOnlyFile) {
+  FS.addStatOnlyFile("/target", 0, 10);
+  FS.addHardLink("/link1", "/target");
+  FS.addHardLink("/link2", "/link1");
+  EXPECT_THAT("/link1", IsHardLinkTo(, "/target"));
+  EXPECT_THAT("/link2", IsHardLinkTo(, "/target"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileUnderHardLinkToStatOnlyFile) {
+  FS.addStatOnlyFile("/target", 0, 10);
+  FS.addHardLink("/link", "/target");
+  EXPECT_FALSE(FS.addFile("/link",  0, MemoryBuffer::getMemBuffer("content")));
 }
 
 // NOTE: in the tests below, we use '//root/' as our root directory, since it is
Index: lib/Basic/VirtualFileSystem.cpp
===
--- lib/Basic/VirtualFileSystem.cpp
+++ lib/Basic/VirtualFileSystem.cpp
@@ -492,20 +492,26 @@
 class InMemoryFile : public InMemoryNode {
   Status Stat;
   std::unique_ptr Buffer;
+  bool StatOnlyFile;
 
 public:
-  InMemoryFile(Status Stat, std::unique_ptr Buffer)
+  InMemoryFile(Status Stat, std::unique_ptr Buffer,
+   bool StatOnlyFile)
   : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
-Buffer(std::move(Buffer)) {}
+Buffer(std::move(Buffer)), StatOnlyFile(StatOnlyFile) {}
 
   /// Return the \p Status for this node. \p RequestedName should be the name
   /// through which the caller referred to this node. It will override
   /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
   Status getStatus(StringRef RequestedName) const {
 return Status::copyWithNewName(Stat, RequestedName);
   }
-  llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
+  llvm::MemoryBuffer *getBuffer() const {
+assert(!StatOnlyFile && "Cannot get buffer for StatOnlyFile");
+return Buffer.get();
+  }
 
+  bool IsStatOnlyFile() const { return StatOnlyFile; }
   std::string toString(unsigned Indent) const override {
 return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
   }
@@ -640,7 +646,8 @@
  Optional Group,
  Optional Type,
  Optional Perms,
- const detail::InMemoryFile *HardLinkTarget) {
+ const detail::InMemoryFile *HardLinkTarget,
+