Revert r363326 "[libFuzzer] simplify the DFT trace collection using the new faster DFSan mode that traces up to 16 labels at a time and never runs out of labels."

It broke the Windows build:

C:\b\s\w\ir\cache\builder\src\third_party\llvm\compiler-rt\lib\fuzzer\FuzzerDataFlowTrace.cpp(243): error C3861: 'setenv': identifier not found

This also reverts the follow-up r363327.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@363358 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/FuzzerDataFlowTrace.cpp b/FuzzerDataFlowTrace.cpp
index 311f53a..1fba391 100644
--- a/FuzzerDataFlowTrace.cpp
+++ b/FuzzerDataFlowTrace.cpp
@@ -120,6 +120,12 @@
   return DFT;
 }
 
+static std::ostream &operator<<(std::ostream &OS, const Vector<uint8_t> &DFT) {
+  for (auto B : DFT)
+    OS << (B ? "1" : "0");
+  return OS;
+}
+
 static bool ParseError(const char *Err, const std::string &Line) {
   Printf("DataFlowTrace: parse error: %s: Line: %s\n", Err, Line.c_str());
   return false;
@@ -240,24 +246,74 @@
                     const Vector<SizedFile> &CorporaFiles) {
   Printf("INFO: collecting data flow: bin: %s dir: %s files: %zd\n",
          DFTBinary.c_str(), DirPath.c_str(), CorporaFiles.size());
-  setenv("DFSAN_OPTIONS", "fast16labels=1:warn_unimplemented=0", 1);
   MkDir(DirPath);
+  auto Temp = TempPath(".dft");
   for (auto &F : CorporaFiles) {
     // For every input F we need to collect the data flow and the coverage.
     // Data flow collection may fail if we request too many DFSan tags at once.
     // So, we start from requesting all tags in range [0,Size) and if that fails
     // we then request tags in [0,Size/2) and [Size/2, Size), and so on.
     // Function number => DFT.
-    auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File)));
     std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
     std::unordered_set<std::string> Cov;
-    Command Cmd;
-    Cmd.addArgument(DFTBinary);
-    Cmd.addArgument(F.File);
-    Cmd.addArgument(OutPath);
-    Printf("CMD: %s\n", Cmd.toString().c_str());
-    ExecuteCommand(Cmd);
+    std::queue<std::pair<size_t, size_t>> Q;
+    Q.push({0, F.Size});
+    while (!Q.empty()) {
+      auto R = Q.front();
+      Printf("\n\n\n********* Trying: [%zd, %zd)\n", R.first, R.second);
+      Q.pop();
+      Command Cmd;
+      Cmd.addArgument(DFTBinary);
+      Cmd.addArgument(std::to_string(R.first));
+      Cmd.addArgument(std::to_string(R.second));
+      Cmd.addArgument(F.File);
+      Cmd.addArgument(Temp);
+      Printf("CMD: %s\n", Cmd.toString().c_str());
+      if (ExecuteCommand(Cmd)) {
+        // DFSan has failed, collect tags for two subsets.
+        if (R.second - R.first >= 2) {
+          size_t Mid = (R.second + R.first) / 2;
+          Q.push({R.first, Mid});
+          Q.push({Mid, R.second});
+        }
+      } else {
+        Printf("********* Success: [%zd, %zd)\n", R.first, R.second);
+        std::ifstream IF(Temp);
+        std::string L;
+        while (std::getline(IF, L, '\n')) {
+          // Data flow collection has succeeded.
+          // Merge the results with the other runs.
+          if (L.empty()) continue;
+          if (L[0] == 'C') {
+            // Take coverage lines as is, they will be the same in all attempts.
+            Cov.insert(L);
+          } else if (L[0] == 'F') {
+            size_t FunctionNum = 0;
+            std::string DFTString;
+            if (ParseDFTLine(L, &FunctionNum, &DFTString)) {
+              auto &DFT = DFTMap[FunctionNum];
+              if (DFT.empty()) {
+                // Haven't seen this function before, take DFT as is.
+                DFT = DFTStringToVector(DFTString);
+              } else if (DFT.size() == DFTString.size()) {
+                // Have seen this function already, merge DFTs.
+                DFTStringAppendToVector(&DFT, DFTString);
+              }
+            }
+          }
+        }
+      }
+    }
+    auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File)));
+    // Dump combined DFT to disk.
+    Printf("Producing DFT for %s\n", OutPath.c_str());
+    std::ofstream OF(OutPath);
+    for (auto &DFT: DFTMap)
+      OF << "F" << DFT.first << " " << DFT.second << std::endl;
+    for (auto &C : Cov)
+      OF << C << std::endl;
   }
+  RemoveFile(Temp);
   // Write functions.txt if it's currently empty or doesn't exist.
   auto FunctionsTxtPath = DirPlusFile(DirPath, kFunctionsTxt);
   if (FileToString(FunctionsTxtPath).empty()) {