Skip to content

Commit bd087b1

Browse files
committed
Print the inferred switch_enum default case as a comment.
Add a LineComments utility to centralize logic. And fix other comments while we're at it.
1 parent a9fd623 commit bd087b1

File tree

1 file changed

+118
-67
lines changed

1 file changed

+118
-67
lines changed

lib/SIL/IR/SILPrinter.cpp

Lines changed: 118 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,69 @@ namespace {
523523

524524
class SILPrinter;
525525

526+
// 1. Accumulate opcode-specific comments in this stream.
527+
// 2. Start emitting comments: lineComments.start()
528+
// 3. Emit each comment section: lineComments.delim()
529+
// 4. End emitting comments: LineComments::end()
530+
class LineComments : public raw_ostream {
531+
llvm::formatted_raw_ostream &os;
532+
// Opcode-specific comments to be printed at the end of the current line.
533+
std::string opcodeCommentString;
534+
llvm::raw_string_ostream opcodeCommentStream;
535+
bool emitting = false;
536+
bool printedSlashes = false;
537+
538+
public:
539+
LineComments(llvm::formatted_raw_ostream &os)
540+
: os(os), opcodeCommentStream(opcodeCommentString) {
541+
SetUnbuffered(); // pass through to the underlying stream
542+
}
543+
544+
// Call to start emitting line comments into the underlying stream.
545+
void start() {
546+
emitting = true;
547+
printedSlashes = false;
548+
549+
if (opcodeCommentString.empty())
550+
return;
551+
552+
delim();
553+
os << opcodeCommentString;
554+
opcodeCommentString.clear();
555+
}
556+
// Call for each section of line
557+
void delim() {
558+
assert(emitting);
559+
if (printedSlashes) {
560+
os << "; ";
561+
} else {
562+
os.PadToColumn(50);
563+
os << "// ";
564+
printedSlashes = true;
565+
}
566+
}
567+
void end() {
568+
assert(emitting);
569+
emitting = false;
570+
printedSlashes = false;
571+
os << "\n";
572+
}
573+
574+
protected:
575+
void write_impl(const char *ptr, size_t size) override {
576+
if (emitting)
577+
os.write(ptr, size);
578+
else
579+
opcodeCommentStream.write(ptr, size);
580+
}
581+
uint64_t current_pos() const override {
582+
if (emitting)
583+
return os.tell() - os.GetNumBytesInBuffer();
584+
585+
return opcodeCommentString.size();
586+
}
587+
};
588+
526589
/// SILPrinter class - This holds the internal implementation details of
527590
/// printing SIL structures.
528591
class SILPrinter : public SILInstructionVisitor<SILPrinter> {
@@ -531,6 +594,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
531594
llvm::formatted_raw_ostream OS;
532595
PrintOptions ASTOptions;
533596
} PrintState;
597+
LineComments lineComments;
534598
unsigned LastBufferID;
535599

536600
// Printers for the underlying stream.
@@ -581,7 +645,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
581645
llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr)
582646
: Ctx(PrintCtx), PrintState{{PrintCtx.OS()},
583647
PrintOptions::printSIL(&PrintCtx)},
584-
LastBufferID(0) {
648+
lineComments(PrintState.OS), LastBufferID(0) {
585649
PrintState.ASTOptions.AlternativeTypeNames = AlternativeTypeNames;
586650
PrintState.ASTOptions.PrintForSIL = true;
587651
}
@@ -755,33 +819,33 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
755819
//===--------------------------------------------------------------------===//
756820
// SILInstruction Printing Logic
757821

758-
bool printTypeDependentOperands(const SILInstruction *I) {
822+
void printTypeDependentOperands(const SILInstruction *I) {
759823
ArrayRef<Operand> TypeDepOps = I->getTypeDependentOperands();
760824
if (TypeDepOps.empty())
761-
return false;
825+
return;
762826

763-
PrintState.OS.PadToColumn(50);
764-
*this << "// type-defs: ";
827+
lineComments.delim();
828+
*this << "type-defs: ";
765829
interleave(TypeDepOps,
766830
[&](const Operand &op) { *this << Ctx.getID(op.get()); },
767831
[&] { *this << ", "; });
768-
return true;
769832
}
770833

771834
/// Print out the users of the SILValue \p V. Return true if we printed out
772835
/// either an id or a use list. Return false otherwise.
773-
bool printUsersOfValue(SILValue value, bool printedSlashes) {
774-
return printUserList({value}, value, printedSlashes);
836+
void printUsersOfValue(SILValue value) {
837+
lineComments.start();
838+
printUserList({value}, value);
839+
lineComments.end();
775840
}
776841

777-
bool printUsersOfInstruction(const SILInstruction *inst, bool printedSlashes) {
842+
void printUsersOfInstruction(const SILInstruction *inst) {
778843
llvm::SmallVector<SILValue, 8> values;
779844
llvm::copy(inst->getResults(), std::back_inserter(values));
780-
return printUserList(values, inst, printedSlashes);
845+
printUserList(values, inst);
781846
}
782847

783-
bool printUserList(ArrayRef<SILValue> values, SILNodePointer node,
784-
bool printedSlashes) {
848+
void printUserList(ArrayRef<SILValue> values, SILNodePointer node) {
785849
// If the set of values is empty, we need to print the ID of
786850
// the instruction. Otherwise, if none of the values has a use,
787851
// we don't need to do anything.
@@ -791,18 +855,13 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
791855
if (!value->use_empty()) hasUse = true;
792856
}
793857
if (!hasUse)
794-
return printedSlashes;
858+
return;
795859
}
860+
lineComments.delim();
796861

797-
if (printedSlashes) {
798-
*this << "; ";
799-
} else {
800-
PrintState.OS.PadToColumn(50);
801-
*this << "// ";
802-
}
803862
if (values.empty()) {
804863
*this << "id: " << Ctx.getID(node);
805-
return true;
864+
return;
806865
}
807866

808867
llvm::SmallVector<ID, 32> UserIDs;
@@ -825,17 +884,16 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
825884
llvm::interleave(
826885
UserIDs.begin(), UserIDs.end(), [&](ID id) { *this << id; },
827886
[&] { *this << ", "; });
828-
return true;
829887
}
830888

831889
void printConformances(ArrayRef<ProtocolConformanceRef> conformances) {
832890
// FIXME: conformances should always be printed and parsed!
833891
if (!Ctx.printVerbose()) {
834892
return;
835893
}
836-
*this << " // ";
837-
for (ProtocolConformanceRef conformance : conformances)
838-
conformance.dump(PrintState.OS, /*indent*/ 0, /*details*/ false);
894+
for (ProtocolConformanceRef conformance : conformances) {
895+
conformance.dump(lineComments, /*indent*/ 0, /*details*/ false);
896+
}
839897
}
840898

841899
void printDebugLocRef(SILLocation Loc, const SourceManager &SM,
@@ -881,15 +939,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
881939
}
882940
}
883941

884-
void printSILLocation(SILLocation L, SILModule &M, const SILDebugScope *DS,
885-
bool printedSlashes) {
942+
void printSILLocation(SILLocation L, SILModule &M, const SILDebugScope *DS) {
943+
lineComments.delim();
886944
if (!L.isNull()) {
887-
if (!printedSlashes) {
888-
PrintState.OS.PadToColumn(50);
889-
*this << "//";
890-
}
891-
*this << " ";
892-
893945
// To minimize output, only print the line and column number for
894946
// everything but the first instruction.
895947
L.getSourceLoc().printLineAndColumn(PrintState.OS,
@@ -924,12 +976,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
924976
*this << ":auto_gen";
925977
if (L.isInPrologue())
926978
*this << ":in_prologue";
927-
}
928-
if (L.isNull()) {
929-
if (!printedSlashes) {
930-
PrintState.OS.PadToColumn(50);
931-
*this << "//";
932-
}
979+
} else {
933980
if (L.isAutoGenerated())
934981
*this << " auto_gen";
935982
else
@@ -1009,25 +1056,25 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
10091056
visit(const_cast<SILInstruction*>(I));
10101057

10111058
// Maybe print debugging information.
1012-
bool printedSlashes = false;
10131059
if (Ctx.printDebugInfo() && !I->isDeleted()
10141060
&& !I->isStaticInitializerInst()) {
10151061
auto &SM = I->getModule().getASTContext().SourceMgr;
10161062
printDebugLocRef(I->getLoc(), SM);
10171063
printDebugScopeRef(I->getDebugScope(), SM);
10181064
}
1019-
printedSlashes = printTypeDependentOperands(I);
1065+
1066+
lineComments.start();
1067+
1068+
printTypeDependentOperands(I);
10201069

10211070
// Print users, or id for valueless instructions.
1022-
printedSlashes = printUsersOfInstruction(I, printedSlashes);
1071+
printUsersOfInstruction(I);
10231072

10241073
// Print SIL location.
10251074
if (Ctx.printVerbose()) {
1026-
printSILLocation(I->getLoc(), I->getModule(), I->getDebugScope(),
1027-
printedSlashes);
1075+
printSILLocation(I->getLoc(), I->getModule(), I->getDebugScope());
10281076
}
1029-
1030-
*this << '\n';
1077+
lineComments.end();
10311078
}
10321079

10331080
void print(const SILNode *node) {
@@ -1068,9 +1115,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
10681115
<< Ctx.getID(arg->getParent()) << " : " << arg->getType();
10691116

10701117
// Print users.
1071-
(void) printUsersOfValue(arg, false);
1072-
1073-
*this << '\n';
1118+
printUsersOfValue(arg);
10741119
}
10751120

10761121
void printSILUndef(const SILUndef *undef) {
@@ -1105,9 +1150,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
11051150
visit(static_cast<SILInstruction *>(nonConstParent));
11061151

11071152
// Print users.
1108-
(void)printUsersOfValue(result, false);
1109-
1110-
*this << '\n';
1153+
printUsersOfValue(result);
11111154
}
11121155

11131156
void printInContext(const SILNode *node) {
@@ -1630,6 +1673,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
16301673
*this << " !true_count(" << CI->getTrueBBCount().getValue() << ")";
16311674
if (CI->getFalseBBCount())
16321675
*this << " !false_count(" << CI->getFalseBBCount().getValue() << ")";
1676+
printForwardingOwnershipKind(CI, CI->getOperand());
16331677
}
16341678

16351679
void visitCheckedCastValueBranchInst(CheckedCastValueBranchInst *CI) {
@@ -2238,34 +2282,41 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
22382282
*this << ", default " << Ctx.getID(SII->getDefaultBB());
22392283
}
22402284

2241-
void printSwitchEnumInst(SwitchEnumTermInst SOI) {
2242-
*this << getIDAndType(SOI.getOperand());
2243-
for (unsigned i = 0, e = SOI.getNumCases(); i < e; ++i) {
2285+
void printSwitchEnumInst(SwitchEnumTermInst switchEnum) {
2286+
*this << getIDAndType(switchEnum.getOperand());
2287+
for (unsigned i = 0, e = switchEnum.getNumCases(); i < e; ++i) {
22442288
EnumElementDecl *elt;
22452289
SILBasicBlock *dest;
2246-
std::tie(elt, dest) = SOI.getCase(i);
2290+
std::tie(elt, dest) = switchEnum.getCase(i);
22472291
*this << ", case " << SILDeclRef(elt, SILDeclRef::Kind::EnumElement)
22482292
<< ": " << Ctx.getID(dest);
2249-
if (SOI.getCaseCount(i)) {
2250-
*this << " !case_count(" << SOI.getCaseCount(i).getValue() << ")";
2293+
if (switchEnum.getCaseCount(i)) {
2294+
*this << " !case_count(" << switchEnum.getCaseCount(i).getValue()
2295+
<< ")";
22512296
}
22522297
}
2253-
if (SOI.hasDefault()) {
2254-
*this << ", default " << Ctx.getID(SOI.getDefaultBB());
2255-
if (SOI.getDefaultCount()) {
2256-
*this << " !default_count(" << SOI.getDefaultCount().getValue() << ")";
2298+
if (switchEnum.hasDefault()) {
2299+
*this << ", default " << Ctx.getID(switchEnum.getDefaultBB());
2300+
if (switchEnum.getDefaultCount()) {
2301+
*this << " !default_count(" << switchEnum.getDefaultCount().getValue()
2302+
<< ")";
2303+
}
2304+
if (NullablePtr<EnumElementDecl> uniqueCase =
2305+
switchEnum.getUniqueCaseForDefault()) {
2306+
lineComments << SILDeclRef(uniqueCase.get(),
2307+
SILDeclRef::Kind::EnumElement);
22572308
}
22582309
}
22592310
}
22602311

2261-
void visitSwitchEnumInst(SwitchEnumInst *SOI) {
2262-
printSwitchEnumInst(SOI);
2263-
printForwardingOwnershipKind(SOI, SOI->getOperand());
2312+
void visitSwitchEnumInst(SwitchEnumInst *switchEnum) {
2313+
printSwitchEnumInst(switchEnum);
2314+
printForwardingOwnershipKind(switchEnum, switchEnum->getOperand());
22642315
}
2265-
void visitSwitchEnumAddrInst(SwitchEnumAddrInst *SOI) {
2266-
printSwitchEnumInst(SOI);
2316+
void visitSwitchEnumAddrInst(SwitchEnumAddrInst *switchEnum) {
2317+
printSwitchEnumInst(switchEnum);
22672318
}
2268-
2319+
22692320
void printSelectEnumInst(SelectEnumInstBase *SEI) {
22702321
*this << getIDAndType(SEI->getEnumOperand());
22712322

0 commit comments

Comments
 (0)