Ejemplo n.º 1
0
void Block::Render(bool InLoop) {
  if (IsCheckedMultipleEntry && InLoop) {
    PrintIndented("label = 0;\n");
  }

  if (Code) {
    // Print code in an indented manner, even over multiple lines
    char *Start = const_cast<char*>(Code);
    while (*Start) {
      char *End = strchr(Start, '\n');
      if (End) *End = 0;
      PutIndented(Start);
      if (End) *End = '\n'; else break;
      Start = End+1;
    }
  }

  if (!ProcessedBranchesOut.size()) return;

  bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later
  bool ForceSetLabel = Shape::IsEmulated(Parent);

  // A setting of the label variable (label = x) is necessary if it can
  // cause an impact. The main case is where we set label to x, then elsewhere
  // we check if label is equal to that value, i.e., that label is an entry
  // in a multiple block. We also need to reset the label when we enter
  // that block, so that each setting is a one-time action: consider
  //
  //    while (1) {
  //      if (check) label = 1;
  //      if (label == 1) { label = 0 }
  //    }
  //
  // (Note that this case is impossible due to fusing, but that is not
  // material here.) So setting to 0 is important just to clear the 1 for
  // future iterations.
  // TODO: When inside a loop, if necessary clear the label variable
  //       once on the top, and never do settings that are in effect clears

  // Fusing: If the next is a Multiple, we can fuse it with this block. Note
  // that we must be the Inner of a Simple, so fusing means joining a Simple
  // to a Multiple. What happens there is that all options in the Multiple
  // *must* appear in the Simple (the Simple is the only one reaching the
  // Multiple), so we can remove the Multiple and add its independent groups
  // into the Simple's branches.
  MultipleShape *Fused = Shape::IsMultiple(Parent->Next);
  if (Fused) {
    PrintDebug("Fusing Multiple to Simple\n");
    Parent->Next = Parent->Next->Next;
    Fused->RenderLoopPrefix();

    // When the Multiple has the same number of groups as we have branches,
    // they will all be fused, so it is safe to not set the label at all
    if (SetLabel && Fused->InnerMap.size() == ProcessedBranchesOut.size()) {
      SetLabel = false;
    }
  }

  Block *DefaultTarget(NULL); // The block we branch to without checking the condition, if none of the other conditions held.

  // Find the default target, the one without a condition
  for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) {
    if (!iter->second->Condition) {
      assert(!DefaultTarget); // Must be exactly one default
      DefaultTarget = iter->first;
    }
  }
  assert(DefaultTarget); // Since each block *must* branch somewhere, this must be set

  bool useSwitch = BranchVar != NULL;

  if (useSwitch) {
    PrintIndented("switch (%s) {\n", BranchVar);
  }

  ministring RemainingConditions;
  bool First = !useSwitch; // when using a switch, there is no special first
  for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin();; iter++) {
    Block *Target;
    Branch *Details;
    if (iter != ProcessedBranchesOut.end()) {
      Target = iter->first;
      if (Target == DefaultTarget) continue; // done at the end
      Details = iter->second;
      assert(Details->Condition); // must have a condition if this is not the default target
    } else {
      Target = DefaultTarget;
      Details = ProcessedBranchesOut[DefaultTarget];
    }
    bool SetCurrLabel = (SetLabel && Target->IsCheckedMultipleEntry) || ForceSetLabel;
    bool HasFusedContent = Fused && contains(Fused->InnerMap, Target);
    bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code;
    if (iter != ProcessedBranchesOut.end()) {
      // If there is nothing to show in this branch, omit the condition
      if (useSwitch) {
        PrintIndented("%s {\n", Details->Condition);
      } else {
        if (HasContent) {
          PrintIndented("%sif (%s) {\n", First ? "" : "} else ", Details->Condition);
          First = false;
        } else {
          if (RemainingConditions.size() > 0) RemainingConditions += " && ";
          RemainingConditions += "!(";
          if (BranchVar) {
            RemainingConditions += BranchVar;
            RemainingConditions += " == ";
          }
          RemainingConditions += Details->Condition;
          RemainingConditions += ")";
        }
      }
    } else {
      // this is the default
      if (useSwitch) {
        PrintIndented("default: {\n");
      } else {
        if (HasContent) {
          if (RemainingConditions.size() > 0) {
            if (First) {
              PrintIndented("if (%s) {\n", RemainingConditions.c_str());
              First = false;
            } else {
              PrintIndented("} else if (%s) {\n", RemainingConditions.c_str());
            }
          } else if (!First) {
            PrintIndented("} else {\n");
          }
        }
      }
    }
    if (!First) Indenter::Indent();
    Details->Render(Target, SetCurrLabel);
    if (HasFusedContent) {
      Fused->InnerMap.find(Target)->second->Render(InLoop);
    }
    if (useSwitch && iter != ProcessedBranchesOut.end()) {
      PrintIndented("break;\n");
    }
    if (!First) Indenter::Unindent();
    if (useSwitch) {
      PrintIndented("}\n");
    }
    if (iter == ProcessedBranchesOut.end()) break;
  }
  if (!First) PrintIndented("}\n");

  if (Fused) {
    Fused->RenderLoopPostfix();
  }
}
Ejemplo n.º 2
0
void MultipleShape::RenderLoopPostfix() {
  if (NeedLoop) {
    Indenter::Unindent();
    PrintIndented("} while(0);\n");
  }
}
Ejemplo n.º 3
0
void DumpPerfEventAttr(const perf_event_attr& attr, size_t indent) {
  std::string event_name = "unknown";
  const EventType* event_type = FindEventTypeByConfig(attr.type, attr.config);
  if (event_type != nullptr) {
    event_name = event_type->name;
  }

  PrintIndented(indent, "event_attr: for event type %s\n", event_name.c_str());

  PrintIndented(indent + 1, "type %u, size %u, config %llu\n", attr.type, attr.size, attr.config);

  if (attr.freq != 0) {
    PrintIndented(indent + 1, "sample_freq %llu\n", attr.sample_freq);
  } else {
    PrintIndented(indent + 1, "sample_period %llu\n", attr.sample_period);
  }

  PrintIndented(indent + 1, "sample_type (0x%llx) %s\n", attr.sample_type,
                SampleTypeToString(attr.sample_type).c_str());

  PrintIndented(indent + 1, "read_format (0x%llx) %s\n", attr.read_format,
                ReadFormatToString(attr.read_format).c_str());

  PrintIndented(indent + 1, "disabled %u, inherit %u, pinned %u, exclusive %u\n", attr.disabled,
                attr.inherit, attr.pinned, attr.exclusive);

  PrintIndented(indent + 1, "exclude_user %u, exclude_kernel %u, exclude_hv %u\n",
                attr.exclude_user, attr.exclude_kernel, attr.exclude_hv);

  PrintIndented(indent + 1, "exclude_idle %u, mmap %u, comm %u, freq %u\n", attr.exclude_idle,
                attr.mmap, attr.comm, attr.freq);

  PrintIndented(indent + 1, "inherit_stat %u, enable_on_exec %u, task %u\n", attr.inherit_stat,
                attr.enable_on_exec, attr.task);

  PrintIndented(indent + 1, "watermark %u, precise_ip %u, mmap_data %u\n", attr.watermark,
                attr.precise_ip, attr.mmap_data);

  PrintIndented(indent + 1, "sample_id_all %u, exclude_host %u, exclude_guest %u\n",
                attr.sample_id_all, attr.exclude_host, attr.exclude_guest);
}