std::vector<unsigned> &InstIdxs,
std::vector<unsigned> &InstOpsUsed) const {
InstIdxs.assign(NumberedInstructions.size(), ~0U);
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);
// 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.
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
const AsmWriterInst *Inst = getAsmWriterInstByID(i);
if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc.
// 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 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 =
for (unsigned Op = 1; ; ++Op) {
// Scan for the first instruction in the set.
std::vector<unsigned>::iterator NIT =
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.
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.
// 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";
// 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";
// 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];
// 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];
CodeGenTarget Target;
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
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"
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
"/// from the instruction set description.\n"
AsmWriter->getValueAsInt("Variant"),
AsmWriter->getValueAsInt("FirstOperandColumn"),
AsmWriter->getValueAsInt("OperandSpacing")));
// Get the instruction numbering.
NumberedInstructions = Target.getInstructionsByEnumValue();
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.
// 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.
// Build an aggregate string, and build a table of offsets into it.
StringToOffsetTable StringTable;
// 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;
/// 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]];
unsigned MaxStringIdx = 0;
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
AsmWriterOperand::isLiteralTextOperand ||
AWI->Operands[0].Str.empty()) {
// Something handled by the asmwriter printer, but with no leading string.
AsmWriterOperand::isLiteralTextOperand ||
AWI->Operands[0].Str.empty()) {
// Something handled by the asmwriter printer, but with no leading string.
UnescapeString(Str);
Idx = StringTable.GetOrAddStringOffset(Str);
MaxStringIdx = std::max(MaxStringIdx, Idx);
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());
}
// Nuke the string from the operand list. It is now handled!
AWI->Operands.erase(AWI->Operands.begin());
}
// Figure out how many bits we used for the string index.
unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
// 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;
// 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);
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;
// 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());
// 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;
}
// 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);
// 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))
// Remove the info about this operand.
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
if (AsmWriterInst *Inst = getAsmWriterInstByID(i))
// Remember the handlers for this set of operands.
TableDrivenOperandPrinters.push_back(UniqueOperandCommands);
}
// 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// "
O<<" static const unsigned OpInfo[] = {\n";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
O << " " << OpcodeInfo[i] << "U,\t// "
// Emit the string itself.
O << " const char *AsmStrs = \n";
StringTable.EmitString(O);
// Emit the string itself.
O << " const char *AsmStrs = \n";
StringTable.EmitString(O);
// ceil(log2(numentries)).
unsigned NumBits = Log2_32_Ceil(Commands.size());
assert(NumBits <= BitsLeft && "consistency error");
// ceil(log2(numentries)).
unsigned NumBits = Log2_32_Ceil(Commands.size());
assert(NumBits <= BitsLeft && "consistency error");
O << "\n // Fragment " << i << " encoded into " << NumBits
<< " bits for " << Commands.size() << " unique commands.\n";
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) << ") & "
if (Commands.size() == 2) {
// Emit two possibilitys with if/else.
O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
<< " default: // unreachable.\n";
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";
// Print out all the cases.
for (unsigned i = 0, e = Commands.size(); i != e; ++i) {
O << " case " << i << ":\n";
// Okay, delete instructions with no operand info left.
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
// Entire instruction has been emitted?
// Okay, delete instructions with no operand info left.
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
// Entire instruction has been emitted?
// 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());
// 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
// 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
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
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"
StringToOffsetTable StringTable;
O <<
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
<< " static const unsigned InstAsmOffset[] = {";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
const CodeGenInstruction &Inst = *NumberedInstructions[i];
<< " static const unsigned InstAsmOffset[] = {";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
const CodeGenInstruction &Inst = *NumberedInstructions[i];
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);