mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-24 21:05:23 +00:00
[MC][TableGen] Add optional libpfm counter names for ProcResUnits.
Summary: Subtargets can define the libpfm counter names that can be used to measure cycles and uops issued on ProcResUnits. This allows making llvm-exegesis available on more targets. Fixes PR36984. Reviewers: gchatelet, RKSimon, andreadb, craig.topper Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D45360 llvm-svn: 329675
This commit is contained in:
parent
c9308fd1bc
commit
221e6ccd99
@ -172,6 +172,18 @@ struct MCExtraProcessorInfo {
|
||||
unsigned NumRegisterFiles;
|
||||
const MCRegisterCostEntry *RegisterCostTable;
|
||||
unsigned NumRegisterCostEntries;
|
||||
|
||||
struct PfmCountersInfo {
|
||||
// An optional name of a performance counter that can be used to measure
|
||||
// cycles.
|
||||
const char *CycleCounter;
|
||||
|
||||
// For each MCProcResourceDesc defined by the processor, an optional list of
|
||||
// names of performance counters that can be used to measure the resource
|
||||
// utilization.
|
||||
const char **IssueCounters;
|
||||
};
|
||||
PfmCountersInfo PfmCounters;
|
||||
};
|
||||
|
||||
/// Machine model for scheduling, bundling, and heuristics.
|
||||
|
@ -182,7 +182,8 @@ class ProcResourceKind;
|
||||
//
|
||||
// SchedModel ties these units to a processor for any stand-alone defs
|
||||
// of this class.
|
||||
class ProcResourceUnits<ProcResourceKind kind, int num> {
|
||||
class ProcResourceUnits<ProcResourceKind kind, int num,
|
||||
list<string> pfmCounters> {
|
||||
ProcResourceKind Kind = kind;
|
||||
int NumUnits = num;
|
||||
ProcResourceKind Super = ?;
|
||||
@ -197,8 +198,8 @@ def EponymousProcResourceKind : ProcResourceKind;
|
||||
|
||||
// Subtargets typically define processor resource kind and number of
|
||||
// units in one place.
|
||||
class ProcResource<int num> : ProcResourceKind,
|
||||
ProcResourceUnits<EponymousProcResourceKind, num>;
|
||||
class ProcResource<int num, list<string> pfmCounters = []> : ProcResourceKind,
|
||||
ProcResourceUnits<EponymousProcResourceKind, num, pfmCounters>;
|
||||
|
||||
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
|
||||
list<ProcResource> Resources = resources;
|
||||
@ -476,3 +477,23 @@ class RetireControlUnit<int bufferSize, int retirePerCycle> {
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Allow the definition of hardware counters.
|
||||
class PfmCounter {
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Each processor can define how to measure cycles by defining a
|
||||
// PfmCycleCounter.
|
||||
class PfmCycleCounter<string counter> : PfmCounter {
|
||||
string Counter = counter;
|
||||
}
|
||||
|
||||
// Each ProcResourceUnits can define how to measure issued uops by defining
|
||||
// a PfmIssueCounter.
|
||||
class PfmIssueCounter<ProcResourceUnits resource, list<string> counters>
|
||||
: PfmCounter{
|
||||
// The resource units on which uops are issued.
|
||||
ProcResourceUnits Resource = resource;
|
||||
// The list of counters that measure issue events.
|
||||
list<string> Counters = counters;
|
||||
}
|
||||
|
@ -1132,3 +1132,9 @@ def X86 : Target {
|
||||
let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
|
||||
let AllowRegisterRenaming = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pfm Counters
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "X86PfmCounters.td"
|
||||
|
71
lib/Target/X86/X86PfmCounters.td
Normal file
71
lib/Target/X86/X86PfmCounters.td
Normal file
@ -0,0 +1,71 @@
|
||||
//===-- X86PfmCounters.td - X86 Hardware Counters ----------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This describes the available hardware counters for various subtargets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let SchedModel = SandyBridgeModel in {
|
||||
def SBCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def SBPort0Counter : PfmIssueCounter<SBPort0, ["uops_dispatched_port:port_0"]>;
|
||||
def SBPort1Counter : PfmIssueCounter<SBPort1, ["uops_dispatched_port:port_1"]>;
|
||||
def SBPort23Counter : PfmIssueCounter<SBPort23,
|
||||
["uops_dispatched_port:port_2",
|
||||
"uops_dispatched_port:port_3"]>;
|
||||
def SBPort4Counter : PfmIssueCounter<SBPort4, ["uops_dispatched_port:port_4"]>;
|
||||
def SBPort5Counter : PfmIssueCounter<SBPort5, ["uops_dispatched_port:port_5"]>;
|
||||
}
|
||||
|
||||
let SchedModel = HaswellModel in {
|
||||
def HWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def HWPort0Counter : PfmIssueCounter<HWPort0, ["uops_dispatched_port:port_0"]>;
|
||||
def HWPort1Counter : PfmIssueCounter<HWPort1, ["uops_dispatched_port:port_1"]>;
|
||||
def HWPort2Counter : PfmIssueCounter<HWPort2, ["uops_dispatched_port:port_2"]>;
|
||||
def HWPort3Counter : PfmIssueCounter<HWPort3, ["uops_dispatched_port:port_3"]>;
|
||||
def HWPort4Counter : PfmIssueCounter<HWPort4, ["uops_dispatched_port:port_4"]>;
|
||||
def HWPort5Counter : PfmIssueCounter<HWPort5, ["uops_dispatched_port:port_5"]>;
|
||||
def HWPort6Counter : PfmIssueCounter<HWPort6, ["uops_dispatched_port:port_6"]>;
|
||||
def HWPort7Counter : PfmIssueCounter<HWPort7, ["uops_dispatched_port:port_7"]>;
|
||||
}
|
||||
|
||||
let SchedModel = BroadwellModel in {
|
||||
def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def BWPort0Counter : PfmIssueCounter<BWPort0, ["uops_dispatched_port:port_0"]>;
|
||||
def BWPort1Counter : PfmIssueCounter<BWPort1, ["uops_dispatched_port:port_1"]>;
|
||||
def BWPort2Counter : PfmIssueCounter<BWPort2, ["uops_dispatched_port:port_2"]>;
|
||||
def BWPort3Counter : PfmIssueCounter<BWPort3, ["uops_dispatched_port:port_3"]>;
|
||||
def BWPort4Counter : PfmIssueCounter<BWPort4, ["uops_dispatched_port:port_4"]>;
|
||||
def BWPort5Counter : PfmIssueCounter<BWPort5, ["uops_dispatched_port:port_5"]>;
|
||||
def BWPort6Counter : PfmIssueCounter<BWPort6, ["uops_dispatched_port:port_6"]>;
|
||||
def BWPort7Counter : PfmIssueCounter<BWPort7, ["uops_dispatched_port:port_7"]>;
|
||||
}
|
||||
|
||||
let SchedModel = SkylakeClientModel in {
|
||||
def SKLCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def SKLPort0Counter : PfmIssueCounter<SKLPort0, ["uops_dispatched_port:port_0"]>;
|
||||
def SKLPort1Counter : PfmIssueCounter<SKLPort1, ["uops_dispatched_port:port_1"]>;
|
||||
def SKLPort2Counter : PfmIssueCounter<SKLPort2, ["uops_dispatched_port:port_2"]>;
|
||||
def SKLPort3Counter : PfmIssueCounter<SKLPort3, ["uops_dispatched_port:port_3"]>;
|
||||
def SKLPort4Counter : PfmIssueCounter<SKLPort4, ["uops_dispatched_port:port_4"]>;
|
||||
def SKLPort5Counter : PfmIssueCounter<SKLPort5, ["uops_dispatched_port:port_5"]>;
|
||||
def SKLPort6Counter : PfmIssueCounter<SKLPort6, ["uops_dispatched_port:port_6"]>;
|
||||
def SKLPort7Counter : PfmIssueCounter<SKLPort7, ["uops_dispatched_port:port_7"]>;
|
||||
}
|
||||
|
||||
let SchedModel = SkylakeServerModel in {
|
||||
def SKXCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def SKXPort0Counter : PfmIssueCounter<SKXPort0, ["uops_dispatched_port:port_0"]>;
|
||||
def SKXPort1Counter : PfmIssueCounter<SKXPort1, ["uops_dispatched_port:port_1"]>;
|
||||
def SKXPort2Counter : PfmIssueCounter<SKXPort2, ["uops_dispatched_port:port_2"]>;
|
||||
def SKXPort3Counter : PfmIssueCounter<SKXPort3, ["uops_dispatched_port:port_3"]>;
|
||||
def SKXPort4Counter : PfmIssueCounter<SKXPort4, ["uops_dispatched_port:port_4"]>;
|
||||
def SKXPort5Counter : PfmIssueCounter<SKXPort5, ["uops_dispatched_port:port_5"]>;
|
||||
def SKXPort6Counter : PfmIssueCounter<SKXPort6, ["uops_dispatched_port:port_6"]>;
|
||||
def SKXPort7Counter : PfmIssueCounter<SKXPort7, ["uops_dispatched_port:port_7"]>;
|
||||
}
|
@ -76,10 +76,15 @@ LatencyBenchmarkRunner::runMeasurements(const LLVMState &State,
|
||||
// measure several times and take the minimum value.
|
||||
constexpr const int NumMeasurements = 30;
|
||||
int64_t MinLatency = std::numeric_limits<int64_t>::max();
|
||||
// FIXME: Read the perf event from the MCSchedModel (see PR36984).
|
||||
const pfm::PerfEvent CyclesPerfEvent("UNHALTED_CORE_CYCLES");
|
||||
const char *CounterName = State.getSubtargetInfo()
|
||||
.getSchedModel()
|
||||
.getExtraProcessorInfo()
|
||||
.PfmCounters.CycleCounter;
|
||||
if (!CounterName)
|
||||
llvm::report_fatal_error("sched model does not define a cycle counter");
|
||||
const pfm::PerfEvent CyclesPerfEvent(CounterName);
|
||||
if (!CyclesPerfEvent.valid())
|
||||
llvm::report_fatal_error("invalid perf event 'UNHALTED_CORE_CYCLES'");
|
||||
llvm::report_fatal_error("invalid perf event");
|
||||
for (size_t I = 0; I < NumMeasurements; ++I) {
|
||||
pfm::Counter Counter(CyclesPerfEvent);
|
||||
Counter.start();
|
||||
|
@ -38,43 +38,6 @@ static llvm::Error makeError(llvm::Twine Msg) {
|
||||
llvm::inconvertibleErrorCode());
|
||||
}
|
||||
|
||||
// FIXME: Read the counter names from the ProcResourceUnits when PR36984 is
|
||||
// fixed.
|
||||
static const std::string *getEventNameFromProcResName(const char *ProcResName) {
|
||||
static const std::unordered_map<std::string, std::string> Entries = {
|
||||
{"SBPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
||||
{"SBPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
||||
{"SBPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
||||
{"SBPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
||||
{"HWPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
||||
{"HWPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
||||
{"HWPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
||||
{"HWPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
||||
{"HWPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
||||
{"HWPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
||||
{"HWPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
||||
{"HWPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
||||
{"SKLPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
||||
{"SKLPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
||||
{"SKLPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
||||
{"SKLPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
||||
{"SKLPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
||||
{"SKLPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
||||
{"SKLPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
||||
{"SKXPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
||||
{"SKXPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
||||
{"SKXPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
||||
{"SKXPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
||||
{"SKXPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
||||
{"SKXPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
||||
{"SKXPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
||||
{"SKXPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
||||
{"SKXPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
||||
};
|
||||
const auto It = Entries.find(ProcResName);
|
||||
return It == Entries.end() ? nullptr : &It->second;
|
||||
}
|
||||
|
||||
static std::vector<llvm::MCInst> generateIndependentAssignments(
|
||||
const LLVMState &State, const llvm::MCInstrDesc &InstrDesc,
|
||||
llvm::SmallVector<Variable, 8> Vars, int MaxAssignments) {
|
||||
@ -228,19 +191,19 @@ UopsBenchmarkRunner::runMeasurements(const LLVMState &State,
|
||||
std::vector<BenchmarkMeasure> Result;
|
||||
for (unsigned ProcResIdx = 1;
|
||||
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
|
||||
const llvm::MCProcResourceDesc &ProcRes =
|
||||
*SchedModel.getProcResource(ProcResIdx);
|
||||
const std::string *const EventName =
|
||||
getEventNameFromProcResName(ProcRes.Name);
|
||||
if (!EventName)
|
||||
const char *const PfmCounters = SchedModel.getExtraProcessorInfo()
|
||||
.PfmCounters.IssueCounters[ProcResIdx];
|
||||
if (!PfmCounters)
|
||||
continue;
|
||||
pfm::Counter Counter{pfm::PerfEvent(*EventName)};
|
||||
// FIXME: Sum results when there are several counters for a single ProcRes
|
||||
// (e.g. P23 on SandyBridge).
|
||||
pfm::Counter Counter{pfm::PerfEvent(PfmCounters)};
|
||||
Counter.start();
|
||||
Function();
|
||||
Counter.stop();
|
||||
Result.push_back({llvm::itostr(ProcResIdx),
|
||||
static_cast<double>(Counter.read()) / NumRepetitions,
|
||||
ProcRes.Name});
|
||||
SchedModel.getProcResource(ProcResIdx)->Name});
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
@ -239,6 +239,11 @@ void CodeGenSchedModels::collectOptionalProcessorInfo() {
|
||||
|
||||
// Collect processor RetireControlUnit descriptors if available.
|
||||
collectRetireControlUnits();
|
||||
|
||||
// Find pfm counter definitions for each processor.
|
||||
collectPfmCounters();
|
||||
|
||||
checkCompleteness();
|
||||
}
|
||||
|
||||
/// Gather all processor models.
|
||||
@ -1537,6 +1542,23 @@ void CodeGenSchedModels::collectRegisterFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
// Collect all the RegisterFile definitions available in this target.
|
||||
void CodeGenSchedModels::collectPfmCounters() {
|
||||
for (Record *Def : Records.getAllDerivedDefinitions("PfmIssueCounter")) {
|
||||
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
|
||||
PM.PfmIssueCounterDefs.emplace_back(Def);
|
||||
}
|
||||
for (Record *Def : Records.getAllDerivedDefinitions("PfmCycleCounter")) {
|
||||
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
|
||||
if (PM.PfmCycleCounterDef) {
|
||||
PrintFatalError(Def->getLoc(),
|
||||
"multiple cycle counters for " +
|
||||
Def->getValueAsDef("SchedModel")->getName());
|
||||
}
|
||||
PM.PfmCycleCounterDef = Def;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and sort WriteRes, ReadAdvance, and ProcResources.
|
||||
void CodeGenSchedModels::collectProcResources() {
|
||||
ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
|
||||
|
@ -238,6 +238,10 @@ struct CodeGenProcModel {
|
||||
// Optional Retire Control Unit definition.
|
||||
Record *RetireControlUnit;
|
||||
|
||||
// List of PfmCounters.
|
||||
RecVec PfmIssueCounterDefs;
|
||||
Record *PfmCycleCounterDef = nullptr;
|
||||
|
||||
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
|
||||
Record *IDef) :
|
||||
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
|
||||
@ -252,7 +256,9 @@ struct CodeGenProcModel {
|
||||
}
|
||||
|
||||
bool hasExtraProcessorInfo() const {
|
||||
return RetireControlUnit || !RegisterFiles.empty();
|
||||
return RetireControlUnit || !RegisterFiles.empty() ||
|
||||
!PfmIssueCounterDefs.empty() ||
|
||||
PfmCycleCounterDef != nullptr;
|
||||
}
|
||||
|
||||
unsigned getProcResourceIdx(Record *PRDef) const;
|
||||
@ -444,6 +450,8 @@ private:
|
||||
|
||||
void collectRegisterFiles();
|
||||
|
||||
void collectPfmCounters();
|
||||
|
||||
void collectOptionalProcessorInfo();
|
||||
|
||||
std::string createSchedClassName(Record *ItinClassDef,
|
||||
|
@ -635,7 +635,7 @@ static void EmitRegisterFileInfo(const CodeGenProcModel &ProcModel,
|
||||
OS << ProcModel.ModelName << "RegisterCosts,\n ";
|
||||
else
|
||||
OS << "nullptr,\n ";
|
||||
OS << NumCostEntries << " // Number of register cost entries.\n";
|
||||
OS << NumCostEntries << ", // Number of register cost entries.\n";
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -686,6 +686,57 @@ SubtargetEmitter::EmitRegisterFileTables(const CodeGenProcModel &ProcModel,
|
||||
|
||||
return CostTblIndex;
|
||||
}
|
||||
static bool EmitPfmIssueCountersTable(const CodeGenProcModel &ProcModel,
|
||||
raw_ostream &OS) {
|
||||
std::vector<const Record *> CounterDefs(ProcModel.ProcResourceDefs.size());
|
||||
bool HasCounters = false;
|
||||
for (const Record *CounterDef : ProcModel.PfmIssueCounterDefs) {
|
||||
const Record *&CD = CounterDefs[ProcModel.getProcResourceIdx(
|
||||
CounterDef->getValueAsDef("Resource"))];
|
||||
if (CD) {
|
||||
PrintFatalError(CounterDef->getLoc(),
|
||||
"multiple issue counters for " +
|
||||
CounterDef->getValueAsDef("Resource")->getName());
|
||||
}
|
||||
CD = CounterDef;
|
||||
HasCounters = true;
|
||||
}
|
||||
if (!HasCounters) {
|
||||
return false;
|
||||
}
|
||||
OS << "\nstatic const char* " << ProcModel.ModelName
|
||||
<< "PfmIssueCounters[] = {\n";
|
||||
for (const Record *CounterDef : CounterDefs) {
|
||||
if (CounterDef) {
|
||||
const auto PfmCounters = CounterDef->getValueAsListOfStrings("Counters");
|
||||
if (PfmCounters.empty())
|
||||
PrintFatalError(CounterDef->getLoc(), "empty counter list");
|
||||
for (const StringRef CounterName : PfmCounters)
|
||||
OS << " \"" << CounterName << ",\"";
|
||||
OS << ", //" << CounterDef->getValueAsDef("Resource")->getName() << "\n";
|
||||
} else {
|
||||
OS << " nullptr,\n";
|
||||
}
|
||||
}
|
||||
OS << "};\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
static void EmitPfmCounters(const CodeGenProcModel &ProcModel,
|
||||
const bool HasPfmIssueCounters, raw_ostream &OS) {
|
||||
// Emit the cycle counter.
|
||||
if (ProcModel.PfmCycleCounterDef)
|
||||
OS << " \"" << ProcModel.PfmCycleCounterDef->getValueAsString("Counter")
|
||||
<< "\", // Cycle counter.\n";
|
||||
else
|
||||
OS << " nullptr, // No cycle counter.\n";
|
||||
|
||||
// Emit a reference to issue counters table.
|
||||
if (HasPfmIssueCounters)
|
||||
OS << " " << ProcModel.ModelName << "PfmIssueCounters\n";
|
||||
else
|
||||
OS << " nullptr, // No issue counters.\n";
|
||||
}
|
||||
|
||||
void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||
raw_ostream &OS) {
|
||||
@ -693,6 +744,9 @@ void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||
// defined register file), and a table of register costs.
|
||||
unsigned NumCostEntries = EmitRegisterFileTables(ProcModel, OS);
|
||||
|
||||
// Generate a table of ProcRes counter names.
|
||||
const bool HasPfmIssueCounters = EmitPfmIssueCountersTable(ProcModel, OS);
|
||||
|
||||
// Now generate a table for the extra processor info.
|
||||
OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
|
||||
<< "ExtraInfo = {\n ";
|
||||
@ -705,6 +759,8 @@ void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||
EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
|
||||
NumCostEntries, OS);
|
||||
|
||||
EmitPfmCounters(ProcModel, HasPfmIssueCounters, OS);
|
||||
|
||||
OS << "};\n";
|
||||
}
|
||||
|
||||
@ -1308,9 +1364,9 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
|
||||
else
|
||||
OS << " nullptr, // No Itinerary\n";
|
||||
if (PM.hasExtraProcessorInfo())
|
||||
OS << " &" << PM.ModelName << "ExtraInfo\n";
|
||||
OS << " &" << PM.ModelName << "ExtraInfo,\n";
|
||||
else
|
||||
OS << " nullptr // No extra processor descriptor\n";
|
||||
OS << " nullptr // No extra processor descriptor\n";
|
||||
OS << "};\n";
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user