Simplify operand padding by keying off tabs in the asm stream. If
authorDavid Greene <greened@obbligato.org>
Fri, 31 Jul 2009 21:57:10 +0000 (21:57 +0000)
committerDavid Greene <greened@obbligato.org>
Fri, 31 Jul 2009 21:57:10 +0000 (21:57 +0000)
padding is disabled, tabs get replaced by spaces except in the case of
the first operand, where the tab is output to line up the operands after
the mnemonics.

Add some better comments and eliminate redundant code.

Fix some testcases to not assume tabs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77740 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/AsmPrinter.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
test/CodeGen/X86/2009-04-17-tls-fast.ll
test/CodeGen/X86/tls1-pic.ll
test/CodeGen/X86/tls2-pic.ll
test/CodeGen/X86/tls3-pic.ll
test/CodeGen/X86/tls4-pic.ll
utils/TableGen/AsmWriterEmitter.cpp

index e3d6074adc1a80c8ea434fcc3902a857a8c05c21..7cdf0a7c7bca4fe7856142a6300d6962c7241986 100644 (file)
@@ -226,11 +226,10 @@ namespace llvm {
                                        unsigned AsmVariant, 
                                        const char *ExtraCode);
     
-    
     /// PrintGlobalVariable - Emit the specified global variable and its
     /// initializer to the output stream.
     virtual void PrintGlobalVariable(const GlobalVariable *GV) = 0;
-    
+
     /// SetupMachineFunction - This should be called when a new MachineFunction
     /// is being processed from runOnMachineFunction.
     void SetupMachineFunction(MachineFunction &MF);
@@ -357,6 +356,13 @@ namespace llvm {
     void EmitComments(const MCInst &MI) const;
 
   protected:
+    /// PadToColumn - This gets called every time a tab is emitted.  If
+    /// column padding is turned on, we replace the tab with the
+    /// appropriate amount of padding.  If not, we replace the tab with a
+    /// space, except for the first operand so that initial operands are
+    /// always lined up by tabs.
+    void PadToColumn(unsigned Operand) const;
+
     /// EmitZeros - Emit a block of zeros.
     ///
     void EmitZeros(uint64_t NumZeros, unsigned AddrSpace = 0) const;
index 077d72e93d9995a84a06fb0d681da11c01e23d9e..e19631fb4251da8184c00f99cb8593938bc8086f 100644 (file)
@@ -847,8 +847,28 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV,
   }
   O << '\n';
 }
-
     
+/// PadToColumn - This gets called every time a tab is emitted.  If
+/// column padding is turned on, we replace the tab with the
+/// appropriate amount of padding.  If not, we replace the tab with a
+/// space, except for the first operand so that initial operands are
+/// always lined up by tabs.
+void AsmPrinter::PadToColumn(unsigned Operand) const {
+  if (TAI->getOperandColumn(Operand) > 0) {
+    O.PadToColumn(TAI->getOperandColumn(Operand), 1);
+  }
+  else {
+    if (Operand == 1) {
+      // Emit the tab after the mnemonic.
+      O << '\t';
+    }
+    else {
+      // Replace the tab with a space.
+      O << ' ';
+    }
+  }
+}
+
 /// EmitZeros - Emit a block of zeros.
 ///
 void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const {
index 6a8054eae25eab1c5f0c8f4dd64d7c6e6e1b49a0..6e9485caa49e44006ae0b10dc99b63760a72e5a8 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic -regalloc=local > %t
-; RUN: grep {leaq      foo@TLSGD(%rip), %rdi} %t
+; RUN: grep {leaq foo@TLSGD(%rip), %rdi} %t
 
 @foo = internal thread_local global i32 100
 
index e43bf7ce66e6b504deb3d5ecd3231c1926768d10..8f4435723373c361f85c535228990f45641a7ab8 100644 (file)
@@ -1,9 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -relocation-model=pic > %t
 ; RUN: grep {leal      i@TLSGD(,%ebx), %eax} %t
-; RUN: grep {call      ___tls_get_addr@PLT} %t
+; RUN: grep {call ___tls_get_addr@PLT} %t
 ; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic > %t2
-; RUN: grep {leaq      i@TLSGD(%rip), %rdi} %t2
-; RUN: grep {call      __tls_get_addr@PLT} %t2
+; RUN: grep {leaq i@TLSGD(%rip), %rdi} %t2
+; RUN: grep {call __tls_get_addr@PLT} %t2
 
 @i = thread_local global i32 15
 
index 6ab3ee0a69fd8e05a1d62f6c929bde151be934c3..f1492f4fc573787d0f04efdd3290e4ec5faa68e9 100644 (file)
@@ -1,9 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -relocation-model=pic > %t
 ; RUN: grep {leal      i@TLSGD(,%ebx), %eax} %t
-; RUN: grep {call      ___tls_get_addr@PLT} %t
+; RUN: grep {call ___tls_get_addr@PLT} %t
 ; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic > %t2
-; RUN: grep {leaq      i@TLSGD(%rip), %rdi} %t2
-; RUN: grep {call      __tls_get_addr@PLT} %t2
+; RUN: grep {leaq i@TLSGD(%rip), %rdi} %t2
+; RUN: grep {call __tls_get_addr@PLT} %t2
 
 @i = thread_local global i32 15
 
index 8e6df29afbf9deed90f691aa30a78bb14640c00b..27c24da59dc63f6bd33c7124172eb4762312699e 100644 (file)
@@ -1,9 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -relocation-model=pic  > %t
 ; RUN: grep {leal      i@TLSGD(,%ebx), %eax} %t
-; RUN: grep {call      ___tls_get_addr@PLT} %t
+; RUN: grep {call ___tls_get_addr@PLT} %t
 ; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic > %t2
-; RUN: grep {leaq      i@TLSGD(%rip), %rdi} %t2
-; RUN: grep {call      __tls_get_addr@PLT} %t2
+; RUN: grep {leaq i@TLSGD(%rip), %rdi} %t2
+; RUN: grep {call __tls_get_addr@PLT} %t2
 
 @i = external thread_local global i32          ; <i32*> [#uses=2]
 
index 94de78f7aef78b18f63abee61d14e2bae473f898..650105436a321393bcbe3ae0767a0d56b6ba0103 100644 (file)
@@ -1,9 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -relocation-model=pic > %t
 ; RUN: grep {leal      i@TLSGD(,%ebx), %eax} %t
-; RUN: grep {call      ___tls_get_addr@PLT} %t
+; RUN: grep {call ___tls_get_addr@PLT} %t
 ; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic > %t2
-; RUN: grep {leaq      i@TLSGD(%rip), %rdi} %t2
-; RUN: grep {call      __tls_get_addr@PLT} %t2
+; RUN: grep {leaq i@TLSGD(%rip), %rdi} %t2
+; RUN: grep {call __tls_get_addr@PLT} %t2
 
 @i = external thread_local global i32          ; <i32*> [#uses=2]
 
index 069578056c40745d4da9fe296653365d49b7dbe1..5f1d32576815fd30690004ad7465760815ede27b 100644 (file)
@@ -34,13 +34,19 @@ static bool isIdentChar(char C) {
 namespace llvm {  
   struct AsmWriterOperand {
     enum OpType {
+      // Output this text surrounded by quotes to the asm.
       isLiteralTextOperand, 
+      // This is the name of a routine to call to print the operand.
       isMachineInstrOperand,
+      // Output this text verbatim to the asm writer.  It is code that
+      // will output some text to the asm.
       isLiteralStatementOperand
     } OperandType;
 
     /// Str - For isLiteralTextOperand, this IS the literal text.  For
-    /// isMachineInstrOperand, this is the PrinterMethodName for the operand.
+    /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
+    /// For isLiteralStatementOperand, this is the code to insert verbatim 
+    /// into the asm writer.
     std::string Str;
 
     /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
@@ -85,29 +91,6 @@ namespace llvm {
     std::vector<AsmWriterOperand> 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];
-
-    /// ReadingWhitespace - Tell whether we just read some whitespace.
-    bool ReadingWhitespace;
-
-    /// InGroup - Determine whether we are in the middle of an
-    /// operand group.
-    bool InGroup() const { return GroupLevel != -1; }
-
-    /// InWhitespace - Determine whether we are in the middle of
-    /// emitting whitespace.
-    bool InWhitespace() const { return ReadingWhitespace; }
-
     AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);
 
     /// MatchesAllButOneOp - If this instruction is exactly identical to the
@@ -137,14 +120,6 @@ std::string AsmWriterOperand::getCode() const {
     return Str;
   }
 
-  if (OperandType == isLiteralStatementOperand) {
-    return Str;
-  }
-
-  if (OperandType == isLiteralStatementOperand) {
-    return Str;
-  }
-
   std::string Result = Str + "(MI";
   if (MIOpNo != ~0U)
     Result += ", " + utostr(MIOpNo);
@@ -157,8 +132,7 @@ std::string AsmWriterOperand::getCode() const {
 /// ParseAsmString - Parse the specified Instruction's AsmString into this
 /// AsmWriterInst.
 ///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant)
-    : GroupLevel(-1), ReadingWhitespace(false) {
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
   this->CGI = &CGI;
   unsigned CurVariant = ~0U;  // ~0 if we are outside a {.|.|.} region, other #.
 
@@ -181,84 +155,22 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant)
         for (; LastEmitted != DollarPos; ++LastEmitted)
           switch (AsmString[LastEmitted]) {
           case '\n':
-            assert(!InGroup() && "Missing matching group delimeter");
-            ReadingWhitespace = false;
             AddLiteralString("\\n");
             break;
           case '\t': 
-            if (!InGroup()) {
-              ReadingWhitespace = true;
-            }
-            AddLiteralString("\\t"); 
+            Operands.push_back(
+              // We recognize a tab as an operand delimeter.  Either
+              // output column padding if enabled or emit a space.
+              AsmWriterOperand("PadToColumn(OperandColumn++);\n",
+                               AsmWriterOperand::isLiteralStatementOperand));
             break;
           case '"':
-            if (InWhitespace() && !InGroup())
-              Operands.push_back(
-                AsmWriterOperand(
-                  "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                  AsmWriterOperand::isLiteralStatementOperand));
-            ReadingWhitespace = false;
             AddLiteralString("\\\"");
             break;
           case '\\':
-            if (InWhitespace() && !InGroup())
-              Operands.push_back(
-                AsmWriterOperand(
-                  "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                  AsmWriterOperand::isLiteralStatementOperand));
-            ReadingWhitespace = false;
             AddLiteralString("\\\\");
             break;
-
-          case '(':  // Fallthrough
-          case '[':
-            if (InWhitespace() && !InGroup())
-              Operands.push_back(
-                AsmWriterOperand(
-                  "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                  AsmWriterOperand::isLiteralStatementOperand));
-            ReadingWhitespace = false;
-
-            ++GroupLevel;
-            assert(GroupLevel < MAX_GROUP_NESTING_LEVEL
-                   && "Exceeded maximum operand group nesting level");
-            GroupDelim[GroupLevel] = AsmString[LastEmitted];
-            AddLiteralString(std::string(1, AsmString[LastEmitted]));
-            break;
-
-          case ')':  // Fallthrough
-          case ']':
-            if (InWhitespace() && !InGroup())
-              Operands.push_back(
-                AsmWriterOperand(
-                  "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                  AsmWriterOperand::isLiteralStatementOperand));
-            ReadingWhitespace = false;
-
-            if (AsmString[LastEmitted] == ')')
-              assert(GroupDelim[GroupLevel] == '(' && "Mismatched delimeters");
-            else
-              assert(GroupDelim[GroupLevel] == '[' && "Mismatched delimeters");
-            
-            --GroupLevel;
-            assert(GroupLevel > -2 && "Too many end delimeters!");
-            AddLiteralString(std::string(1, AsmString[LastEmitted]));
-            break;
-            
           default:
-            if (AsmString[LastEmitted] != ' ' &&
-                AsmString[LastEmitted] != '\t') {
-              if (!InGroup() && InWhitespace())
-                Operands.push_back(
-                  AsmWriterOperand(
-                    "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                    AsmWriterOperand::isLiteralStatementOperand));
-              ReadingWhitespace = false;
-            }
-            else 
-              if (!InGroup())
-                ReadingWhitespace = true;
-
             AddLiteralString(std::string(1, AsmString[LastEmitted]));
             break;
           }
@@ -269,33 +181,15 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant)
       if (DollarPos+1 != AsmString.size() &&
           (CurVariant == Variant || CurVariant == ~0U)) {
         if (AsmString[DollarPos+1] == 'n') {
-          assert(!InGroup() && "Missing matching group delimeter");
-          ReadingWhitespace = false;
           AddLiteralString("\\n");
         } else if (AsmString[DollarPos+1] == 't') {
-          if (!InGroup()) {
-            ReadingWhitespace = true;
-          }
-          AddLiteralString("\\t");
+          Operands.push_back(
+            // We recognize a tab as an operand delimeter.  Either
+            // output column padding if enabled or emit a space.
+            AsmWriterOperand("PadToColumn(OperandColumn++);\n",
+                             AsmWriterOperand::isLiteralStatementOperand));
         } else if (std::string("${|}\\").find(AsmString[DollarPos+1]) 
                    != std::string::npos) {
-          if (InWhitespace() && !InGroup())
-            Operands.push_back(
-              AsmWriterOperand(
-                "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-                AsmWriterOperand::isLiteralStatementOperand));
-          ReadingWhitespace = false;
-
-          if (AsmString[DollarPos+1] == '{') {
-            ++GroupLevel;
-            assert(GroupLevel < MAX_GROUP_NESTING_LEVEL
-                   && "Exceeded maximum operand group nesting level");
-            GroupDelim[GroupLevel] = AsmString[DollarPos+1];
-          } else if (AsmString[DollarPos+1] == '}') {
-            assert(GroupDelim[GroupLevel] == '{' && "Mismatched delimeters");
-            --GroupLevel;
-            assert(GroupLevel > -2 && "Too many end delimeters!");
-          }
           AddLiteralString(std::string(1, AsmString[DollarPos+1]));
         } else {
           throw "Non-supported escaped character found in instruction '" +
@@ -325,23 +219,10 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant)
     } else if (DollarPos+1 != AsmString.size() &&
                AsmString[DollarPos+1] == '$') {
       if (CurVariant == Variant || CurVariant == ~0U) {
-        if (InWhitespace() && !InGroup())
-          Operands.push_back(
-            AsmWriterOperand(
-              "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-              AsmWriterOperand::isLiteralStatementOperand));
-        ReadingWhitespace = false;
         AddLiteralString("$");  // "$$" -> $
       }
       LastEmitted = DollarPos+2;
     } else {
-      if (InWhitespace() && !InGroup())
-        Operands.push_back(
-          AsmWriterOperand(
-            "O.PadToColumn(TAI->getOperandColumn(OperandColumn++));\n",
-            AsmWriterOperand::isLiteralStatementOperand));
-      ReadingWhitespace = false;
-
       // Get the name of the variable.
       std::string::size_type VarEnd = DollarPos+1;
  
@@ -852,6 +733,8 @@ void AsmWriterEmitter::run(raw_ostream &O) {
     << "  if (TAI->getOperandColumn(1) > 0) {\n"
     << "    // Don't emit trailing whitespace, let the column padding do it.  This\n"
     << "    // guarantees that a stray long opcode + tab won't upset the alignment.\n"
+    << "    // We need to handle this special case here because sometimes the initial\n"
+    << "    // mnemonic string includes a tab or space and sometimes it doesn't.\n"
     << "    unsigned OpLength = std::strlen(AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << "));\n"
     << "    if (OpLength > 0 &&\n"
     << "        ((AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << "))[OpLength-1] == ' ' ||\n"