X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FAsmWriterEmitter.cpp;h=6ae0b39c8ddea911e6319c9d1b5b6d3eda324e7e;hp=44622e937dadba58f75d3912ac1a3323c673d802;hb=9255b8d349768a02b2d139a43984c9b544098122;hpb=e260990fa19e3f5f2935a922868e80b83fb87524 diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 44622e937da..6ae0b39c8dd 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -101,22 +101,22 @@ static void EmitInstructions(std::vector &Insts, } void AsmWriterEmitter:: -FindUniqueOperandCommands(std::vector &UniqueOperandCommands, +FindUniqueOperandCommands(std::vector &UniqueOperandCommands, std::vector &InstIdxs, std::vector &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 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 &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::iterator NIT = @@ -158,7 +158,7 @@ FindUniqueOperandCommands(std::vector &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 &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 &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 &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 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 > TableDrivenOperandPrinters; - + while (1) { std::vector UniqueOperandCommands; std::vector InstIdxs; std::vector 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 &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 &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);