summaryrefslogtreecommitdiff
path: root/utils/TableGen/AsmWriterEmitter.cpp
diff options
context:
space:
mode:
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.