summaryrefslogtreecommitdiff
path: root/utils/TableGen/AsmWriterEmitter.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-14 22:59:11 +0000
committerChris Lattner <sabre@nondot.org>2006-07-14 22:59:11 +0000
commit6af022f255257bee7c6d6903ff4caa2217d51502 (patch)
treedd1b689c75e8d7372b67adc5372c2550946fa57c /utils/TableGen/AsmWriterEmitter.cpp
parent53eca9466f5dc10bba86f94fa1a55a1e8f36baf2 (diff)
downloadllvm-6af022f255257bee7c6d6903ff4caa2217d51502.tar.gz
llvm-6af022f255257bee7c6d6903ff4caa2217d51502.tar.bz2
llvm-6af022f255257bee7c6d6903ff4caa2217d51502.tar.xz
Emit the string information for the asm writer as a single large string
and index into it, instead of emitting it like this: static const char * const OpStrs[] = { "PHINODE\n", // PHI 0, // INLINEASM "adc ", // ADC32mi "adc ", // ADC32mi8 ... The old way required thousands of relocations that slows down link time and dynamic load times. This also cuts about 10K off each of the X86 asmprinters, and should shrink the others as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29152 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/AsmWriterEmitter.cpp')
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp105
1 files changed, 69 insertions, 36 deletions
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index ab595ca9fb..2cd17d95fd 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -15,6 +15,7 @@
#include "AsmWriterEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <ostream>
using namespace llvm;
@@ -346,49 +347,81 @@ void AsmWriterEmitter::run(std::ostream &O) {
if (!I->second.AsmString.empty())
Instructions.push_back(AsmWriterInst(I->second, Variant));
- // If all of the instructions start with a constant string (a very very common
- // occurance), emit all of the constant strings as a big table lookup instead
- // of requiring a switch for them.
- bool AllStartWithString = true;
-
- for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
- if (Instructions[i].Operands.empty() ||
- Instructions[i].Operands[0].OperandType !=
- AsmWriterOperand::isLiteralTextOperand) {
- AllStartWithString = false;
- break;
- }
-
std::vector<const CodeGenInstruction*> NumberedInstructions;
Target.getInstructionsByEnumValue(NumberedInstructions);
- if (AllStartWithString) {
- // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
- // all machine instructions are necessarily being printed, so there may be
- // target instructions not in this map.
- std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
- for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
- CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
-
- // Emit a table of constant strings.
- O << " static const char * const OpStrs[] = {\n";
- for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
- AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
- if (AWI == 0) {
- // Something not handled by the asmwriter printer.
- O << " 0,\t// ";
+ // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
+ // all machine instructions are necessarily being printed, so there may be
+ // target instructions not in this map.
+ std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
+ CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
+
+ // Build an aggregate string, and build a table of offsets into it.
+ std::map<std::string, unsigned> StringOffset;
+ std::string AggregateString;
+ AggregateString += '\0';
+
+ O << " static unsigned short OpStrIdxs[] = {\n";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
+ unsigned Idx;
+ if (AWI == 0 || AWI->Operands[0].Str.empty()) {
+ // Something not handled by the asmwriter printer.
+ Idx = 0;
+ } else {
+ unsigned &Entry = StringOffset[AWI->Operands[0].Str];
+ if (Entry == 0) {
+ // Add the string to the aggregate if this is the first time found.
+ Entry = AggregateString.size();
+ std::string Str = AWI->Operands[0].Str;
+ UnescapeString(Str);
+ AggregateString += Str;
+ AggregateString += '\0';
+ }
+ Idx = Entry;
+ assert(Entry < 65536 && "Must not use unsigned short for table idx!");
+
+ // Nuke the string from the operand list. It is now handled!
+ AWI->Operands.erase(AWI->Operands.begin());
+ }
+ O << " " << Idx << ",\t// " << NumberedInstructions[i]->TheDef->getName()
+ << "\n";
+ }
+ O << " };\n\n";
+
+ // Emit the string itself.
+ O << " const char *AsmStrs = \n \"";
+ unsigned CharsPrinted = 0;
+ EscapeString(AggregateString);
+ for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
+ if (CharsPrinted > 70) {
+ O << "\"\n \"";
+ CharsPrinted = 0;
+ }
+ O << AggregateString[i];
+ ++CharsPrinted;
+
+ // Print escape sequences all together.
+ if (AggregateString[i] == '\\') {
+ assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
+ if (isdigit(AggregateString[i+1])) {
+ assert(isdigit(AggregateString[i+2]) && isdigit(AggregateString[i+3]) &&
+ "Expected 3 digit octal escape!");
+ O << AggregateString[++i];
+ O << AggregateString[++i];
+ O << AggregateString[++i];
+ CharsPrinted += 3;
} else {
- O << " \"" << AWI->Operands[0].Str << "\",\t// ";
- // Nuke the string from the operand list. It is now handled!
- AWI->Operands.erase(AWI->Operands.begin());
+ O << AggregateString[++i];
+ ++CharsPrinted;
}
- O << NumberedInstructions[i]->TheDef->getName() << "\n";
}
- O << " };\n\n"
- << " // Emit the opcode for the instruction.\n"
- << " if (const char *AsmStr = OpStrs[MI->getOpcode()])\n"
- << " O << AsmStr;\n\n";
}
+ O << "\";\n\n";
+
+ O << " // Emit the opcode for the instruction.\n"
+ << " O << AsmStrs+OpStrIdxs[MI->getOpcode()];\n\n";
// Because this is a vector we want to emit from the end. Reverse all of the
// elements in the vector.