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/dataflow/DataFlow.cpp b/dataflow/DataFlow.cpp
index 8a5d695..989675e 100644
--- a/dataflow/DataFlow.cpp
+++ b/dataflow/DataFlow.cpp
@@ -35,8 +35,7 @@
 // Run:
 //   # Collect data flow and coverage for INPUT_FILE
 //   # write to OUTPUT_FILE (default: stdout)
-//   export DFSAN_OPTIONS=fast16labels=1:warn_unimplemented=0
-//   ./a.out INPUT_FILE [OUTPUT_FILE]
+//   ./a.out FIRST_LABEL LAST_LABEL INPUT_FILE [OUTPUT_FILE]
 //
 //   # Print all instrumented functions. llvm-symbolizer must be present in PATH
 //   ./a.out
@@ -49,6 +48,8 @@
 //  C1 8
 //  ===============
 // "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on.
+//    The byte string is LEN+1 bytes. The last byte is set if the function
+//    depends on the input length.
 // "CN X Y Z T": tells that a function N has basic blocks X, Y, and Z covered
 //    in addition to the function's entry block, out of T total instrumented
 //    blocks.
@@ -71,20 +72,22 @@
 } // extern "C"
 
 static size_t InputLen;
-static size_t NumIterations;
+static size_t InputLabelBeg;
+static size_t InputLabelEnd;
+static size_t InputSizeLabel;
 static size_t NumFuncs, NumGuards;
 static uint32_t *GuardsBeg, *GuardsEnd;
 static const uintptr_t *PCsBeg, *PCsEnd;
-static __thread size_t CurrentFunc, CurrentIteration;
-static dfsan_label **FuncLabels;  // NumFuncs x NumIterations.
+static __thread size_t CurrentFunc;
+static dfsan_label *FuncLabels;  // Array of NumFuncs elements.
 static bool *BBExecuted;  // Array of NumGuards elements.
+static char *PrintableStringForLabel;  // InputLen + 2 bytes.
+static bool LabelSeen[1 << 8 * sizeof(dfsan_label)];
 
 enum {
   PCFLAG_FUNC_ENTRY = 1,
 };
 
-const int kNumLabels = 16;
-
 static inline bool BlockIsEntry(size_t BlockIdx) {
   return PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY;
 }
@@ -109,32 +112,35 @@
   return 0;
 }
 
-static void PrintBinary(FILE *Out, dfsan_label L, size_t Len) {
-  char buf[kNumLabels + 1];
-  assert(Len <= kNumLabels);
-  for (int i = 0; i < kNumLabels; i++)
-    buf[i] = (L & (1 << i)) ? '1' : '0';
-  buf[Len] = 0;
-  fprintf(Out, "%s", buf);
+extern "C"
+void SetBytesForLabel(dfsan_label L, char *Bytes) {
+  if (LabelSeen[L])
+    return;
+  LabelSeen[L] = true;
+  assert(L);
+  if (L < InputSizeLabel) {
+    Bytes[L + InputLabelBeg - 1] = '1';
+  } else if (L == InputSizeLabel) {
+    Bytes[InputLen] = '1';
+  } else {
+    auto *DLI = dfsan_get_label_info(L);
+    SetBytesForLabel(DLI->l1, Bytes);
+    SetBytesForLabel(DLI->l2, Bytes);
+  }
+}
+
+static char *GetPrintableStringForLabel(dfsan_label L) {
+  memset(PrintableStringForLabel, '0', InputLen + 1);
+  PrintableStringForLabel[InputLen + 1] = 0;
+  memset(LabelSeen, 0, sizeof(LabelSeen));
+  SetBytesForLabel(L, PrintableStringForLabel);
+  return PrintableStringForLabel;
 }
 
 static void PrintDataFlow(FILE *Out) {
-  for (size_t Func = 0; Func < NumFuncs; Func++) {
-    bool HasAny = false;
-    for (size_t Iter = 0; Iter < NumIterations; Iter++)
-      if (FuncLabels[Func][Iter])
-        HasAny = true;
-    if (!HasAny)
-      continue;
-    fprintf(Out, "F%zd ", Func);
-    size_t LenOfLastIteration = kNumLabels;
-    if (auto Tail = InputLen % kNumLabels)
-        LenOfLastIteration = Tail;
-    for (size_t Iter = 0; Iter < NumIterations; Iter++)
-      PrintBinary(Out, FuncLabels[Func][Iter],
-                  Iter == NumIterations - 1 ? LenOfLastIteration : kNumLabels);
-    fprintf(Out, "\n");
-  }
+  for (size_t I = 0; I < NumFuncs; I++)
+    if (FuncLabels[I])
+      fprintf(Out, "F%zd %s\n", I, GetPrintableStringForLabel(FuncLabels[I]));
 }
 
 static void PrintCoverage(FILE *Out) {
@@ -163,9 +169,12 @@
     LLVMFuzzerInitialize(&argc, &argv);
   if (argc == 1)
     return PrintFunctions();
-  assert(argc == 2 || argc == 3);
+  assert(argc == 4 || argc == 5);
+  InputLabelBeg = atoi(argv[1]);
+  InputLabelEnd = atoi(argv[2]);
+  assert(InputLabelBeg < InputLabelEnd);
 
-  const char *Input = argv[1];
+  const char *Input = argv[3];
   fprintf(stderr, "INFO: reading '%s'\n", Input);
   FILE *In = fopen(Input, "r");
   assert(In);
@@ -175,35 +184,30 @@
   unsigned char *Buf = (unsigned char*)malloc(InputLen);
   size_t NumBytesRead = fread(Buf, 1, InputLen, In);
   assert(NumBytesRead == InputLen);
+  PrintableStringForLabel = (char*)malloc(InputLen + 2);
   fclose(In);
 
-  NumIterations = (NumBytesRead + kNumLabels - 1) / kNumLabels;
-  FuncLabels = (dfsan_label**)calloc(NumFuncs, sizeof(dfsan_label*));
-  for (size_t Func = 0; Func < NumFuncs; Func++)
-    FuncLabels[Func] =
-        (dfsan_label *)calloc(NumIterations, sizeof(dfsan_label));
-
-  for (CurrentIteration = 0; CurrentIteration < NumIterations;
-       CurrentIteration++) {
-    fprintf(stderr, "INFO: running '%s' %zd/%zd\n", Input, CurrentIteration,
-            NumIterations);
-    dfsan_flush();
-    dfsan_set_label(0, Buf, InputLen);
-
-    size_t BaseIdx = CurrentIteration * kNumLabels;
-    size_t LastIdx = BaseIdx + kNumLabels < NumBytesRead ? BaseIdx + kNumLabels
-                                                         : NumBytesRead;
-    assert(BaseIdx < LastIdx);
-    for (size_t Idx = BaseIdx; Idx < LastIdx; Idx++)
-      dfsan_set_label(1 << (Idx - BaseIdx), Buf + Idx, 1);
-    LLVMFuzzerTestOneInput(Buf, InputLen);
+  fprintf(stderr, "INFO: running '%s'\n", Input);
+  for (size_t I = 1; I <= InputLen; I++) {
+    size_t Idx = I - 1;
+    if (Idx >= InputLabelBeg && Idx < InputLabelEnd) {
+      dfsan_label L = dfsan_create_label("", nullptr);
+      assert(L == I - InputLabelBeg);
+      dfsan_set_label(L, Buf + Idx, 1);
+    }
   }
+  dfsan_label SizeL = dfsan_create_label("", nullptr);
+  InputSizeLabel = SizeL;
+  assert(InputSizeLabel == InputLabelEnd - InputLabelBeg + 1);
+  dfsan_set_label(SizeL, &InputLen, sizeof(InputLen));
+
+  LLVMFuzzerTestOneInput(Buf, InputLen);
   free(Buf);
 
-  bool OutIsStdout = argc == 2;
+  bool OutIsStdout = argc == 4;
   fprintf(stderr, "INFO: writing dataflow to %s\n",
-          OutIsStdout ? "<stdout>" : argv[2]);
-  FILE *Out = OutIsStdout ? stdout : fopen(argv[2], "w");
+          OutIsStdout ? "<stdout>" : argv[4]);
+  FILE *Out = OutIsStdout ? stdout : fopen(argv[4], "w");
   PrintDataFlow(Out);
   PrintCoverage(Out);
   if (!OutIsStdout) fclose(Out);
@@ -233,6 +237,7 @@
       GuardsBeg[i] = NumFuncs;
     }
   }
+  FuncLabels = (dfsan_label*)calloc(NumFuncs, sizeof(dfsan_label));
   BBExecuted = (bool*)calloc(NumGuards, sizeof(bool));
   fprintf(stderr, "INFO: %zd instrumented function(s) observed "
           "and %zd basic blocks\n", NumFuncs, NumGuards);
@@ -253,13 +258,14 @@
 void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases,
                                          dfsan_label L1, dfsan_label UnusedL) {
   assert(CurrentFunc < NumFuncs);
-  FuncLabels[CurrentFunc][CurrentIteration] |= L1;
+  FuncLabels[CurrentFunc] = dfsan_union(FuncLabels[CurrentFunc], L1);
 }
 
 #define HOOK(Name, Type)                                                       \
   void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) {            \
     assert(CurrentFunc < NumFuncs);                                            \
-    FuncLabels[CurrentFunc][CurrentIteration] |= L1 | L2;                      \
+    FuncLabels[CurrentFunc] =                                                  \
+        dfsan_union(FuncLabels[CurrentFunc], dfsan_union(L1, L2));             \
   }
 
 HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t)