forked from OSchip/llvm-project
parent
8e861d7eee
commit
a5497345ad
|
@ -101,22 +101,22 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
|
|||
}
|
||||
|
||||
void AsmWriterEmitter::
|
||||
FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
||||
FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
||||
std::vector<unsigned> &InstIdxs,
|
||||
std::vector<unsigned> &InstOpsUsed) const {
|
||||
InstIdxs.assign(NumberedInstructions.size(), ~0U);
|
||||
|
||||
|
||||
// This vector parallels UniqueOperandCommands, keeping track of which
|
||||
// instructions each case are used for. It is a comma separated string of
|
||||
// enums.
|
||||
std::vector<std::string> InstrsForCase;
|
||||
InstrsForCase.resize(UniqueOperandCommands.size());
|
||||
InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
|
||||
|
||||
|
||||
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
|
||||
const AsmWriterInst *Inst = getAsmWriterInstByID(i);
|
||||
if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc.
|
||||
|
||||
|
||||
std::string Command;
|
||||
if (Inst->Operands.empty())
|
||||
continue; // Instruction already done.
|
||||
|
@ -143,13 +143,13 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
|||
InstOpsUsed.push_back(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For each entry of UniqueOperandCommands, there is a set of instructions
|
||||
// that uses it. If the next command of all instructions in the set are
|
||||
// identical, fold it into the command.
|
||||
for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size();
|
||||
CommandIdx != e; ++CommandIdx) {
|
||||
|
||||
|
||||
for (unsigned Op = 1; ; ++Op) {
|
||||
// Scan for the first instruction in the set.
|
||||
std::vector<unsigned>::iterator NIT =
|
||||
|
@ -158,7 +158,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
|||
|
||||
// If this instruction has no more operands, we isn't anything to merge
|
||||
// into this command.
|
||||
const AsmWriterInst *FirstInst =
|
||||
const AsmWriterInst *FirstInst =
|
||||
getAsmWriterInstByID(NIT-InstIdxs.begin());
|
||||
if (!FirstInst || FirstInst->Operands.size() == Op)
|
||||
break;
|
||||
|
@ -175,7 +175,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
|||
NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) {
|
||||
// Okay, found another instruction in this command set. If the operand
|
||||
// matches, we're ok, otherwise bail out.
|
||||
const AsmWriterInst *OtherInst =
|
||||
const AsmWriterInst *OtherInst =
|
||||
getAsmWriterInstByID(NIT-InstIdxs.begin());
|
||||
|
||||
if (OtherInst &&
|
||||
|
@ -189,16 +189,16 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
|||
}
|
||||
}
|
||||
if (!AllSame) break;
|
||||
|
||||
|
||||
// Okay, everything in this command set has the same next operand. Add it
|
||||
// to UniqueOperandCommands and remember that it was consumed.
|
||||
std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n";
|
||||
|
||||
|
||||
UniqueOperandCommands[CommandIdx] += Command;
|
||||
InstOpsUsed[CommandIdx]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Prepend some of the instructions each case is used for onto the case val.
|
||||
for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
|
||||
std::string Instrs = InstrsForCase[i];
|
||||
|
@ -206,9 +206,9 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
|
|||
Instrs.erase(Instrs.begin()+70, Instrs.end());
|
||||
Instrs += "...";
|
||||
}
|
||||
|
||||
|
||||
if (!Instrs.empty())
|
||||
UniqueOperandCommands[i] = " // " + Instrs + "\n" +
|
||||
UniqueOperandCommands[i] = " // " + Instrs + "\n" +
|
||||
UniqueOperandCommands[i];
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
CodeGenTarget Target;
|
||||
Record *AsmWriter = Target.getAsmWriter();
|
||||
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||||
|
||||
|
||||
O <<
|
||||
"/// printInstruction - This method is automatically generated by tablegen\n"
|
||||
"/// from the instruction set description.\n"
|
||||
|
@ -257,14 +257,14 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
if (!(*I)->AsmString.empty() &&
|
||||
(*I)->TheDef->getName() != "PHI")
|
||||
Instructions.push_back(
|
||||
AsmWriterInst(**I,
|
||||
AsmWriterInst(**I,
|
||||
AsmWriter->getValueAsInt("Variant"),
|
||||
AsmWriter->getValueAsInt("FirstOperandColumn"),
|
||||
AsmWriter->getValueAsInt("OperandSpacing")));
|
||||
|
||||
// Get the instruction numbering.
|
||||
NumberedInstructions = Target.getInstructionsByEnumValue();
|
||||
|
||||
|
||||
// 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.
|
||||
|
@ -273,11 +273,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
|
||||
// Build an aggregate string, and build a table of offsets into it.
|
||||
StringToOffsetTable StringTable;
|
||||
|
||||
|
||||
/// OpcodeInfo - This encodes the index of the string to use for the first
|
||||
/// chunk of the output as well as indices used for operand printing.
|
||||
std::vector<unsigned> OpcodeInfo;
|
||||
|
||||
|
||||
unsigned MaxStringIdx = 0;
|
||||
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
|
||||
AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
|
||||
|
@ -285,7 +285,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
if (AWI == 0) {
|
||||
// Something not handled by the asmwriter printer.
|
||||
Idx = ~0U;
|
||||
} else if (AWI->Operands[0].OperandType !=
|
||||
} else if (AWI->Operands[0].OperandType !=
|
||||
AsmWriterOperand::isLiteralTextOperand ||
|
||||
AWI->Operands[0].Str.empty()) {
|
||||
// Something handled by the asmwriter printer, but with no leading string.
|
||||
|
@ -295,51 +295,51 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
UnescapeString(Str);
|
||||
Idx = StringTable.GetOrAddStringOffset(Str);
|
||||
MaxStringIdx = std::max(MaxStringIdx, Idx);
|
||||
|
||||
|
||||
// Nuke the string from the operand list. It is now handled!
|
||||
AWI->Operands.erase(AWI->Operands.begin());
|
||||
}
|
||||
|
||||
|
||||
// Bias offset by one since we want 0 as a sentinel.
|
||||
OpcodeInfo.push_back(Idx+1);
|
||||
}
|
||||
|
||||
|
||||
// Figure out how many bits we used for the string index.
|
||||
unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
|
||||
|
||||
|
||||
// To reduce code size, we compactify common instructions into a few bits
|
||||
// in the opcode-indexed table.
|
||||
unsigned BitsLeft = 32-AsmStrBits;
|
||||
|
||||
std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
|
||||
|
||||
|
||||
while (1) {
|
||||
std::vector<std::string> UniqueOperandCommands;
|
||||
std::vector<unsigned> InstIdxs;
|
||||
std::vector<unsigned> NumInstOpsHandled;
|
||||
FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
|
||||
NumInstOpsHandled);
|
||||
|
||||
|
||||
// If we ran out of operands to print, we're done.
|
||||
if (UniqueOperandCommands.empty()) break;
|
||||
|
||||
|
||||
// Compute the number of bits we need to represent these cases, this is
|
||||
// ceil(log2(numentries)).
|
||||
unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
|
||||
|
||||
|
||||
// If we don't have enough bits for this operand, don't include it.
|
||||
if (NumBits > BitsLeft) {
|
||||
DEBUG(errs() << "Not enough bits to densely encode " << NumBits
|
||||
<< " more bits\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, we can include this in the initial lookup table. Add it in.
|
||||
BitsLeft -= NumBits;
|
||||
for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i)
|
||||
if (InstIdxs[i] != ~0U)
|
||||
OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits);
|
||||
|
||||
|
||||
// Remove the info about this operand.
|
||||
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
|
||||
if (AsmWriterInst *Inst = getAsmWriterInstByID(i))
|
||||
|
@ -351,13 +351,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
Inst->Operands.begin()+NumOps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remember the handlers for this set of operands.
|
||||
TableDrivenOperandPrinters.push_back(UniqueOperandCommands);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
O<<" static const unsigned OpInfo[] = {\n";
|
||||
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
|
||||
O << " " << OpcodeInfo[i] << "U,\t// "
|
||||
|
@ -366,7 +366,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
// Add a dummy entry so the array init doesn't end with a comma.
|
||||
O << " 0U\n";
|
||||
O << " };\n\n";
|
||||
|
||||
|
||||
// Emit the string itself.
|
||||
O << " const char *AsmStrs = \n";
|
||||
StringTable.EmitString(O);
|
||||
|
@ -388,13 +388,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
// ceil(log2(numentries)).
|
||||
unsigned NumBits = Log2_32_Ceil(Commands.size());
|
||||
assert(NumBits <= BitsLeft && "consistency error");
|
||||
|
||||
|
||||
// Emit code to extract this field from Bits.
|
||||
BitsLeft -= NumBits;
|
||||
|
||||
|
||||
O << "\n // Fragment " << i << " encoded into " << NumBits
|
||||
<< " bits for " << Commands.size() << " unique commands.\n";
|
||||
|
||||
|
||||
if (Commands.size() == 2) {
|
||||
// Emit two possibilitys with if/else.
|
||||
O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
|
||||
|
@ -410,7 +410,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
|
||||
<< ((1 << NumBits)-1) << ") {\n"
|
||||
<< " default: // unreachable.\n";
|
||||
|
||||
|
||||
// Print out all the cases.
|
||||
for (unsigned i = 0, e = Commands.size(); i != e; ++i) {
|
||||
O << " case " << i << ":\n";
|
||||
|
@ -420,7 +420,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
O << " }\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Okay, delete instructions with no operand info left.
|
||||
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
|
||||
// Entire instruction has been emitted?
|
||||
|
@ -431,12 +431,12 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Because this is a vector, we want to emit from the end. Reverse all of the
|
||||
// elements in the vector.
|
||||
std::reverse(Instructions.begin(), Instructions.end());
|
||||
|
||||
|
||||
|
||||
|
||||
// Now that we've emitted all of the operand info that fit into 32 bits, emit
|
||||
// information for those instructions that are left. This is a less dense
|
||||
// encoding, but we expect the main 32-bit table to handle the majority of
|
||||
|
@ -460,7 +460,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
|||
Record *AsmWriter = Target.getAsmWriter();
|
||||
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||||
const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
|
||||
|
||||
|
||||
StringToOffsetTable StringTable;
|
||||
O <<
|
||||
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
||||
|
@ -478,21 +478,21 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
|||
std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
|
||||
if (AsmName.empty())
|
||||
AsmName = Reg.getName();
|
||||
|
||||
|
||||
|
||||
|
||||
if ((i % 14) == 0)
|
||||
O << "\n ";
|
||||
|
||||
|
||||
O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
|
||||
}
|
||||
O << "0\n"
|
||||
<< " };\n"
|
||||
<< "\n";
|
||||
|
||||
|
||||
O << " const char *AsmStrs =\n";
|
||||
StringTable.EmitString(O);
|
||||
O << ";\n";
|
||||
|
||||
|
||||
O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
|
||||
<< "}\n";
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
|
|||
|
||||
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
|
||||
Target.getInstructionsByEnumValue();
|
||||
|
||||
|
||||
StringToOffsetTable StringTable;
|
||||
O <<
|
||||
"\n\n#ifdef GET_INSTRUCTION_NAME\n"
|
||||
|
@ -520,21 +520,21 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
|
|||
<< " static const unsigned InstAsmOffset[] = {";
|
||||
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
|
||||
const CodeGenInstruction &Inst = *NumberedInstructions[i];
|
||||
|
||||
|
||||
std::string AsmName = Inst.TheDef->getName();
|
||||
if ((i % 14) == 0)
|
||||
O << "\n ";
|
||||
|
||||
|
||||
O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
|
||||
}
|
||||
O << "0\n"
|
||||
<< " };\n"
|
||||
<< "\n";
|
||||
|
||||
|
||||
O << " const char *Strs =\n";
|
||||
StringTable.EmitString(O);
|
||||
O << ";\n";
|
||||
|
||||
|
||||
O << " return Strs+InstAsmOffset[Opcode];\n"
|
||||
<< "}\n\n#endif\n";
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
|
|||
|
||||
void AsmWriterEmitter::run(raw_ostream &O) {
|
||||
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
|
||||
|
||||
|
||||
EmitPrintInstruction(O);
|
||||
EmitGetRegisterName(O);
|
||||
EmitGetInstructionName(O);
|
||||
|
|
Loading…
Reference in New Issue