diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e3d6074adc1..7cdf0a7c7bc 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -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; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 077d72e93d9..e19631fb425 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -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 { diff --git a/test/CodeGen/X86/2009-04-17-tls-fast.ll b/test/CodeGen/X86/2009-04-17-tls-fast.ll index 6a8054eae25..6e9485caa49 100644 --- a/test/CodeGen/X86/2009-04-17-tls-fast.ll +++ b/test/CodeGen/X86/2009-04-17-tls-fast.ll @@ -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 diff --git a/test/CodeGen/X86/tls1-pic.ll b/test/CodeGen/X86/tls1-pic.ll index e43bf7ce66e..8f443572337 100644 --- a/test/CodeGen/X86/tls1-pic.ll +++ b/test/CodeGen/X86/tls1-pic.ll @@ -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 diff --git a/test/CodeGen/X86/tls2-pic.ll b/test/CodeGen/X86/tls2-pic.ll index 6ab3ee0a69f..f1492f4fc57 100644 --- a/test/CodeGen/X86/tls2-pic.ll +++ b/test/CodeGen/X86/tls2-pic.ll @@ -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 diff --git a/test/CodeGen/X86/tls3-pic.ll b/test/CodeGen/X86/tls3-pic.ll index 8e6df29afbf..27c24da59dc 100644 --- a/test/CodeGen/X86/tls3-pic.ll +++ b/test/CodeGen/X86/tls3-pic.ll @@ -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 ; [#uses=2] diff --git a/test/CodeGen/X86/tls4-pic.ll b/test/CodeGen/X86/tls4-pic.ll index 94de78f7aef..650105436a3 100644 --- a/test/CodeGen/X86/tls4-pic.ll +++ b/test/CodeGen/X86/tls4-pic.ll @@ -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 ; [#uses=2] diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 069578056c4..5f1d3257681 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -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 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"