From ab9238e876dcf6da101d8ae626925bcd9e537a7e Mon Sep 17 00:00:00 2001 From: David Greene Date: Fri, 17 Jul 2009 14:24:46 +0000 Subject: Add logic to align instruction operands to columns for pretty-printing. No target uses this currently. This patch only adds the mechanism so that local installations can choose to enable this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76177 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/AsmWriterEmitter.cpp | 135 ++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 12 deletions(-) (limited to 'utils') diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index d1cb702..933f921 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include +#include #include using namespace llvm; @@ -32,7 +33,11 @@ static bool isIdentChar(char C) { // This should be an anon namespace, this works around a GCC warning. namespace llvm { struct AsmWriterOperand { - enum { isLiteralTextOperand, isMachineInstrOperand } OperandType; + enum OpType { + isLiteralTextOperand, + isMachineInstrOperand, + isLiteralStatementOperand + } OperandType; /// Str - For isLiteralTextOperand, this IS the literal text. For /// isMachineInstrOperand, this is the PrinterMethodName for the operand. @@ -47,14 +52,16 @@ namespace llvm { std::string MiModifier; // To make VS STL happy - AsmWriterOperand():OperandType(isLiteralTextOperand) {} + AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {} - explicit AsmWriterOperand(const std::string &LitStr) - : OperandType(isLiteralTextOperand), Str(LitStr) {} + AsmWriterOperand(const std::string &LitStr, + OpType op = isLiteralTextOperand) + : OperandType(op), Str(LitStr) {} AsmWriterOperand(const std::string &Printer, unsigned OpNo, - const std::string &Modifier) - : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo), + const std::string &Modifier, + OpType op = isMachineInstrOperand) + : OperandType(op), Str(Printer), MIOpNo(OpNo), MiModifier(Modifier) {} bool operator!=(const AsmWriterOperand &Other) const { @@ -78,6 +85,22 @@ namespace llvm { std::vector Operands; const CodeGenInstruction *CGI; + /// MAX_GROUP_NESTING_LEVEL - The maximum number of group nesting + /// levels we ever expect to see in an asm operand. + static const int MAX_GROUP_NESTING_LEVEL = 10; + + /// GroupLevel - The level of nesting of the current operand + /// group, such as [reg + (reg + offset)]. -1 means we are not in + /// a group. + int GroupLevel; + + /// GroupDelim - Remember the delimeter for a group operand. + char GroupDelim[MAX_GROUP_NESTING_LEVEL]; + + /// InGroup - Determine whether we are in the middle of an + /// operand group. + bool InGroup() const { return GroupLevel != -1; } + AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); /// MatchesAllButOneOp - If this instruction is exactly identical to the @@ -89,6 +112,70 @@ namespace llvm { void AddLiteralString(const std::string &Str) { // If the last operand was already a literal text string, append this to // it, otherwise add a new operand. + + std::string::size_type SearchStart = 0; + std::string::size_type SpaceStartPos = std::string::npos; + do { + // Search for whitespace and replace with calls to set the + // output column. + SpaceStartPos = Str.find_first_of(" \t", SearchStart); + // Assume grouped text is one operand. + std::string::size_type StartDelimPos = Str.find_first_of("[{(", SearchStart); + + SearchStart = std::string::npos; + + if (StartDelimPos != std::string::npos) { + ++GroupLevel; + assert(GroupLevel < MAX_GROUP_NESTING_LEVEL + && "Exceeded maximum operand group nesting level"); + GroupDelim[GroupLevel] = Str[StartDelimPos]; + if (SpaceStartPos != std::string::npos && + SpaceStartPos > StartDelimPos) { + // This space doesn't count. + SpaceStartPos = std::string::npos; + } + } + + if (InGroup()) { + // Find the end delimiter. + char EndDelim = (GroupDelim[GroupLevel] == '{' ? '}' : + (GroupDelim[GroupLevel] == '(' ? ')' : ']')); + std::string::size_type EndDelimSearchStart = + StartDelimPos == std::string::npos ? 0 : StartDelimPos+1; + std::string::size_type EndDelimPos = Str.find(EndDelim, + EndDelimSearchStart); + SearchStart = EndDelimPos; + if (EndDelimPos != std::string::npos) { + // Iterate. + SearchStart = EndDelimPos + 1; + --GroupLevel; + assert(GroupLevel > -2 && "Too many end delimeters!"); + } + if (InGroup()) + SpaceStartPos = std::string::npos; + } + } while (SearchStart != std::string::npos); + + + if (SpaceStartPos != std::string::npos) { + std::string::size_type SpaceEndPos = + Str.find_first_not_of(" \t", SpaceStartPos+1); + if (SpaceStartPos != 0) { + // Emit the first part of the string. + AddLiteralString(Str.substr(0, SpaceStartPos)); + } + Operands.push_back( + AsmWriterOperand( + "O.PadToColumn(TAI->getOperandColumn(OperandColumn++), 1);\n", + AsmWriterOperand::isLiteralStatementOperand)); + if (SpaceEndPos != std::string::npos) { + // Emit the last part of the string. + AddLiteralString(Str.substr(SpaceEndPos)); + } + // We've emitted the whole string. + return; + } + if (!Operands.empty() && Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand) Operands.back().Str.append(Str); @@ -103,6 +190,18 @@ std::string AsmWriterOperand::getCode() const { if (OperandType == isLiteralTextOperand) return "O << \"" + Str + "\"; "; + if (OperandType == isLiteralStatementOperand) { + return Str; + } + + if (OperandType == isLiteralStatementOperand) { + return Str; + } + + if (OperandType == isLiteralStatementOperand) { + return Str; + } + std::string Result = Str + "(MI"; if (MIOpNo != ~0U) Result += ", " + utostr(MIOpNo); @@ -115,7 +214,8 @@ std::string AsmWriterOperand::getCode() const { /// ParseAsmString - Parse the specified Instruction's AsmString into this /// AsmWriterInst. /// -AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { +AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) + : GroupLevel(-1) { this->CGI = &CGI; unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #. @@ -355,6 +455,9 @@ static void EmitInstructions(std::vector &Insts, } O << "\n"; } + O << " EmitComments(*MI);\n"; + // Print the final newline + O << " O << \"\\n\";\n"; O << " break;\n"; } @@ -681,8 +784,16 @@ void AsmWriterEmitter::run(raw_ostream &O) { O << " // Emit the opcode for the instruction.\n" << " unsigned Bits = OpInfo[MI->getOpcode()];\n" - << " if (Bits == 0) return false;\n" - << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\n"; + << " if (Bits == 0) return false;\n\n"; + + O << " std::string OpStr(AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << "));\n" + << " unsigned OperandColumn = 1;\n" + << " O << OpStr;\n\n"; + + O << " if (OpStr.find_last_of(\" \\t\") == OpStr.size()-1) {\n" + << " O.PadToColumn(TAI->getOperandColumn(1));\n" + << " OperandColumn = 2;\n" + << " }\n\n"; // Output the table driven operand information. BitsLeft = 32-AsmStrBits; @@ -746,10 +857,10 @@ void AsmWriterEmitter::run(raw_ostream &O) { O << " }\n"; O << " EmitComments(*MI);\n"; - // Print the final newline - O << " O << \"\\n\";\n"; - O << " return true;\n"; } + // Print the final newline + O << " O << \"\\n\";\n"; + O << " return true;\n"; O << "}\n"; } -- cgit v1.1