Skip to content

Commit c07cbc8

Browse files
committed
raw_ostream: << operator for callables with raw_ostream argument
This is a revised version of r254655 which uses a Printable wrapper class to avoid ambiguous overload problems. Differential Revision: http://reviews.llvm.org/D14348 llvm-svn: 254681
1 parent 580b657 commit c07cbc8

File tree

5 files changed

+126
-140
lines changed

5 files changed

+126
-140
lines changed

llvm/include/llvm/Support/Printable.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- Printable.h - Print function helpers -------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file defines the Printable struct.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_SUPPORT_PRINTABLE_H
15+
#define LLVM_SUPPORT_PRINTABLE_H
16+
17+
#include <functional>
18+
19+
namespace llvm {
20+
21+
class raw_ostream;
22+
23+
/// Simple wrapper around std::function<void(raw_ostream&)>.
24+
/// This class is usefull to construct print helpers for raw_ostream.
25+
///
26+
/// Example:
27+
/// Printable PrintRegister(unsigned Register) {
28+
/// return Printable([Register](raw_ostream &OS) {
29+
/// OS << getRegisterName(Register);
30+
/// }
31+
/// }
32+
/// ... OS << PrintRegister(Register); ...
33+
///
34+
/// Implementation note: Ideally this would just be a typedef, but doing so
35+
/// leads to operator << being ambiguous as function has matching constructors
36+
/// in some STL versions. I have seen the problem on gcc 4.6 libstdc++ and
37+
/// microsoft STL.
38+
class Printable {
39+
public:
40+
std::function<void(raw_ostream &OS)> Print;
41+
Printable(const std::function<void(raw_ostream &OS)> Print)
42+
: Print(Print) {}
43+
};
44+
45+
static inline raw_ostream &operator<<(raw_ostream &OS, const Printable &P) {
46+
P.Print(OS);
47+
return OS;
48+
}
49+
50+
}
51+
52+
#endif

llvm/include/llvm/Target/TargetRegisterInfo.h

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/IR/CallingConv.h"
2323
#include "llvm/MC/MCRegisterInfo.h"
2424
#include "llvm/Support/CommandLine.h"
25+
#include "llvm/Support/Printable.h"
2526
#include <cassert>
2627
#include <functional>
2728

@@ -932,7 +933,6 @@ struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> {
932933
}
933934
};
934935

935-
/// Helper class for printing registers on a raw_ostream.
936936
/// Prints virtual and physical registers with or without a TRI instance.
937937
///
938938
/// The format is:
@@ -943,79 +943,25 @@ struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> {
943943
/// %physreg17 - a physical register when no TRI instance given.
944944
///
945945
/// Usage: OS << PrintReg(Reg, TRI) << '\n';
946-
///
947-
class PrintReg {
948-
const TargetRegisterInfo *TRI;
949-
unsigned Reg;
950-
unsigned SubIdx;
951-
public:
952-
explicit PrintReg(unsigned reg, const TargetRegisterInfo *tri = nullptr,
953-
unsigned subidx = 0)
954-
: TRI(tri), Reg(reg), SubIdx(subidx) {}
955-
void print(raw_ostream&) const;
956-
};
946+
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr,
947+
unsigned SubRegIdx = 0);
957948

958-
static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) {
959-
PR.print(OS);
960-
return OS;
961-
}
962-
963-
/// Helper class for printing register units on a raw_ostream.
949+
/// Create Printable object to print register units on a \ref raw_ostream.
964950
///
965951
/// Register units are named after their root registers:
966952
///
967953
/// AL - Single root.
968954
/// FP0~ST7 - Dual roots.
969955
///
970956
/// Usage: OS << PrintRegUnit(Unit, TRI) << '\n';
971-
///
972-
class PrintRegUnit {
973-
protected:
974-
const TargetRegisterInfo *TRI;
975-
unsigned Unit;
976-
public:
977-
PrintRegUnit(unsigned unit, const TargetRegisterInfo *tri)
978-
: TRI(tri), Unit(unit) {}
979-
void print(raw_ostream&) const;
980-
};
981-
982-
static inline raw_ostream &operator<<(raw_ostream &OS, const PrintRegUnit &PR) {
983-
PR.print(OS);
984-
return OS;
985-
}
957+
Printable PrintRegUnit(unsigned Unit, const TargetRegisterInfo *TRI);
986958

987-
/// It is often convenient to track virtual registers and
988-
/// physical register units in the same list.
989-
class PrintVRegOrUnit : protected PrintRegUnit {
990-
public:
991-
PrintVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *tri)
992-
: PrintRegUnit(VRegOrUnit, tri) {}
993-
void print(raw_ostream&) const;
994-
};
995-
996-
static inline raw_ostream &operator<<(raw_ostream &OS,
997-
const PrintVRegOrUnit &PR) {
998-
PR.print(OS);
999-
return OS;
1000-
}
1001-
1002-
/// Helper class for printing lane masks.
1003-
///
1004-
/// They are currently printed out as hexadecimal numbers.
1005-
/// Usage: OS << PrintLaneMask(Mask);
1006-
class PrintLaneMask {
1007-
protected:
1008-
LaneBitmask LaneMask;
1009-
public:
1010-
PrintLaneMask(LaneBitmask LaneMask)
1011-
: LaneMask(LaneMask) {}
1012-
void print(raw_ostream&) const;
1013-
};
959+
/// \brief Create Printable object to print virtual registers and physical
960+
/// registers on a \ref raw_ostream.
961+
Printable PrintVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI);
1014962

1015-
static inline raw_ostream &operator<<(raw_ostream &OS, const PrintLaneMask &P) {
1016-
P.print(OS);
1017-
return OS;
1018-
}
963+
/// Create Printable object to print LaneBitmasks on a \ref raw_ostream.
964+
Printable PrintLaneMask(LaneBitmask LaneMask);
1019965

1020966
} // End llvm namespace
1021967

llvm/lib/CodeGen/RegAllocPBQP.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "llvm/IR/Module.h"
4848
#include "llvm/Support/Debug.h"
4949
#include "llvm/Support/FileSystem.h"
50+
#include "llvm/Support/Printable.h"
5051
#include "llvm/Support/raw_ostream.h"
5152
#include "llvm/Target/TargetInstrInfo.h"
5253
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -805,33 +806,17 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) {
805806
return true;
806807
}
807808

808-
namespace {
809-
// A helper class for printing node and register info in a consistent way
810-
class PrintNodeInfo {
811-
public:
812-
typedef PBQP::RegAlloc::PBQPRAGraph Graph;
813-
typedef PBQP::RegAlloc::PBQPRAGraph::NodeId NodeId;
814-
815-
PrintNodeInfo(NodeId NId, const Graph &G) : G(G), NId(NId) {}
816-
817-
void print(raw_ostream &OS) const {
809+
/// Create Printable object for node and register info.
810+
static Printable PrintNodeInfo(PBQP::RegAlloc::PBQPRAGraph::NodeId NId,
811+
const PBQP::RegAlloc::PBQPRAGraph &G) {
812+
return Printable([NId, &G](raw_ostream &OS) {
818813
const MachineRegisterInfo &MRI = G.getMetadata().MF.getRegInfo();
819814
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
820815
unsigned VReg = G.getNodeMetadata(NId).getVReg();
821816
const char *RegClassName = TRI->getRegClassName(MRI.getRegClass(VReg));
822817
OS << NId << " (" << RegClassName << ':' << PrintReg(VReg, TRI) << ')';
823-
}
824-
825-
private:
826-
const Graph &G;
827-
NodeId NId;
828-
};
829-
830-
inline raw_ostream &operator<<(raw_ostream &OS, const PrintNodeInfo &PR) {
831-
PR.print(OS);
832-
return OS;
818+
});
833819
}
834-
} // anonymous namespace
835820

836821
void PBQP::RegAlloc::PBQPRAGraph::dump(raw_ostream &OS) const {
837822
for (auto NId : nodeIds()) {

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/IR/Intrinsics.h"
2323
#include "llvm/Support/Debug.h"
2424
#include "llvm/Support/GraphWriter.h"
25+
#include "llvm/Support/Printable.h"
2526
#include "llvm/Support/raw_ostream.h"
2627
#include "llvm/Target/TargetInstrInfo.h"
2728
#include "llvm/Target/TargetIntrinsicInfo.h"
@@ -369,25 +370,14 @@ const char *SDNode::getIndexedModeName(ISD::MemIndexedMode AM) {
369370
}
370371
}
371372

372-
namespace {
373-
class PrintNodeId {
374-
const SDNode &Node;
375-
public:
376-
explicit PrintNodeId(const SDNode &Node)
377-
: Node(Node) {}
378-
void print(raw_ostream &OS) const {
373+
static Printable PrintNodeId(const SDNode &Node) {
374+
return Printable([&Node](raw_ostream &OS) {
379375
#ifndef NDEBUG
380376
OS << 't' << Node.PersistentId;
381377
#else
382378
OS << (const void*)&Node;
383379
#endif
384-
}
385-
};
386-
387-
static inline raw_ostream &operator<<(raw_ostream &OS, const PrintNodeId &P) {
388-
P.print(OS);
389-
return OS;
390-
}
380+
});
391381
}
392382

393383
void SDNode::dump() const { dump(nullptr); }

llvm/lib/CodeGen/TargetRegisterInfo.cpp

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -40,58 +40,71 @@ TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID,
4040

4141
TargetRegisterInfo::~TargetRegisterInfo() {}
4242

43-
void PrintReg::print(raw_ostream &OS) const {
44-
if (!Reg)
45-
OS << "%noreg";
46-
else if (TargetRegisterInfo::isStackSlot(Reg))
47-
OS << "SS#" << TargetRegisterInfo::stackSlot2Index(Reg);
48-
else if (TargetRegisterInfo::isVirtualRegister(Reg))
49-
OS << "%vreg" << TargetRegisterInfo::virtReg2Index(Reg);
50-
else if (TRI && Reg < TRI->getNumRegs())
51-
OS << '%' << TRI->getName(Reg);
52-
else
53-
OS << "%physreg" << Reg;
54-
if (SubIdx) {
55-
if (TRI)
56-
OS << ':' << TRI->getSubRegIndexName(SubIdx);
43+
namespace llvm {
44+
45+
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI,
46+
unsigned SubIdx) {
47+
return Printable([Reg, TRI, SubIdx](raw_ostream &OS) {
48+
if (!Reg)
49+
OS << "%noreg";
50+
else if (TargetRegisterInfo::isStackSlot(Reg))
51+
OS << "SS#" << TargetRegisterInfo::stackSlot2Index(Reg);
52+
else if (TargetRegisterInfo::isVirtualRegister(Reg))
53+
OS << "%vreg" << TargetRegisterInfo::virtReg2Index(Reg);
54+
else if (TRI && Reg < TRI->getNumRegs())
55+
OS << '%' << TRI->getName(Reg);
5756
else
58-
OS << ":sub(" << SubIdx << ')';
59-
}
57+
OS << "%physreg" << Reg;
58+
if (SubIdx) {
59+
if (TRI)
60+
OS << ':' << TRI->getSubRegIndexName(SubIdx);
61+
else
62+
OS << ":sub(" << SubIdx << ')';
63+
}
64+
});
6065
}
6166

62-
void PrintRegUnit::print(raw_ostream &OS) const {
63-
// Generic printout when TRI is missing.
64-
if (!TRI) {
65-
OS << "Unit~" << Unit;
66-
return;
67-
}
67+
Printable PrintRegUnit(unsigned Unit, const TargetRegisterInfo *TRI) {
68+
return Printable([Unit, TRI](raw_ostream &OS) {
69+
// Generic printout when TRI is missing.
70+
if (!TRI) {
71+
OS << "Unit~" << Unit;
72+
return;
73+
}
6874

69-
// Check for invalid register units.
70-
if (Unit >= TRI->getNumRegUnits()) {
71-
OS << "BadUnit~" << Unit;
72-
return;
73-
}
75+
// Check for invalid register units.
76+
if (Unit >= TRI->getNumRegUnits()) {
77+
OS << "BadUnit~" << Unit;
78+
return;
79+
}
7480

75-
// Normal units have at least one root.
76-
MCRegUnitRootIterator Roots(Unit, TRI);
77-
assert(Roots.isValid() && "Unit has no roots.");
78-
OS << TRI->getName(*Roots);
79-
for (++Roots; Roots.isValid(); ++Roots)
80-
OS << '~' << TRI->getName(*Roots);
81+
// Normal units have at least one root.
82+
MCRegUnitRootIterator Roots(Unit, TRI);
83+
assert(Roots.isValid() && "Unit has no roots.");
84+
OS << TRI->getName(*Roots);
85+
for (++Roots; Roots.isValid(); ++Roots)
86+
OS << '~' << TRI->getName(*Roots);
87+
});
8188
}
8289

83-
void PrintVRegOrUnit::print(raw_ostream &OS) const {
84-
if (TRI && TRI->isVirtualRegister(Unit)) {
85-
OS << "%vreg" << TargetRegisterInfo::virtReg2Index(Unit);
86-
return;
87-
}
88-
PrintRegUnit::print(OS);
90+
Printable PrintVRegOrUnit(unsigned Unit, const TargetRegisterInfo *TRI) {
91+
return Printable([Unit, TRI](raw_ostream &OS) {
92+
if (TRI && TRI->isVirtualRegister(Unit)) {
93+
OS << "%vreg" << TargetRegisterInfo::virtReg2Index(Unit);
94+
} else {
95+
OS << PrintRegUnit(Unit, TRI);
96+
}
97+
});
8998
}
9099

91-
void PrintLaneMask::print(raw_ostream &OS) const {
92-
OS << format("%08X", LaneMask);
100+
Printable PrintLaneMask(LaneBitmask LaneMask) {
101+
return Printable([LaneMask](raw_ostream &OS) {
102+
OS << format("%08X", LaneMask);
103+
});
93104
}
94105

106+
} // End of llvm namespace
107+
95108
/// getAllocatableClass - Return the maximal subclass of the given register
96109
/// class that is alloctable, or NULL.
97110
const TargetRegisterClass *

0 commit comments

Comments
 (0)