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(); } }
void MultipleShape::RenderLoopPostfix() { if (NeedLoop) { Indenter::Unindent(); PrintIndented("} while(0);\n"); } }
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); }