diff options
Diffstat (limited to 'utils/TableGen/AsmWriterEmitter.cpp')
| -rw-r--r-- | utils/TableGen/AsmWriterEmitter.cpp | 122 | 
1 files changed, 64 insertions, 58 deletions
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 23f13c2ae2d49..448ebad91f091 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -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];    }  } @@ -240,15 +240,18 @@ static void UnescapeString(std::string &Str) {  /// EmitPrintInstruction - Generate the code for the "printInstruction" method  /// implementation.  void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { -  CodeGenTarget Target; +  CodeGenTarget Target(Records);    Record *AsmWriter = Target.getAsmWriter();    std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); -   +  bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); +  const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; +    O <<    "/// printInstruction - This method is automatically generated by tablegen\n"    "/// from the instruction set description.\n"      "void " << Target.getName() << ClassName -            << "::printInstruction(const MachineInstr *MI, raw_ostream &O) {\n"; +            << "::printInstruction(const " << MachineInstrClassName +            << " *MI, raw_ostream &O) {\n";    std::vector<AsmWriterInst> Instructions; @@ -257,14 +260,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 +276,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 +288,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 +298,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 +354,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 +369,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 +391,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) << ") & " @@ -403,11 +406,14 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {          << "  } else {\n"          << Commands[0]          << "  }\n\n"; +    } else if (Commands.size() == 1) { +      // Emit a single possibility. +      O << Commands[0] << "\n\n";      } else {        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"; @@ -417,7 +423,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? @@ -428,12 +434,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 @@ -453,11 +459,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {  void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { -  CodeGenTarget Target; +  CodeGenTarget Target(Records);    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" @@ -475,33 +481,33 @@ 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";  }  void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { -  CodeGenTarget Target; +  CodeGenTarget Target(Records);    Record *AsmWriter = Target.getAsmWriter();    std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");    const std::vector<const CodeGenInstruction*> &NumberedInstructions =      Target.getInstructionsByEnumValue(); -   +    StringToOffsetTable StringTable;    O <<  "\n\n#ifdef GET_INSTRUCTION_NAME\n" @@ -517,21 +523,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";  } @@ -540,7 +546,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);  | 
