// runEnums - Print out enum values for all of the instructions. void InstrEnumEmitter::run(std::ostream &OS) { EmitSourceFileHeader("Target Instruction Enum Values", OS); OS << "namespace llvm {\n\n"; CodeGenTarget Target; // We must emit the PHI opcode first... std::string Namespace; for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { if (II->second.Namespace != "TargetInstrInfo") { Namespace = II->second.Namespace; break; } } if (Namespace.empty()) { fprintf(stderr, "No instructions defined!\n"); exit(1); } std::vector<const CodeGenInstruction*> NumberedInstructions; Target.getInstructionsByEnumValue(NumberedInstructions); OS << "namespace " << Namespace << " {\n"; OS << " enum {\n"; for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { OS << " " << NumberedInstructions[i]->TheDef->getName() << "\t= " << i << ",\n"; } OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; OS << " };\n}\n"; OS << "} // End llvm namespace \n"; }
void AsmWriterEmitter::run(std::ostream &O) { EmitSourceFileHeader("Assembly Writer Source Fragment", O); CodeGenTarget Target; Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); unsigned Variant = AsmWriter->getValueAsInt("Variant"); O << "/// printInstruction - This method is automatically generated by tablegen\n" "/// from the instruction set description. This method returns true if the\n" "/// machine instruction was sufficiently described to print it, otherwise\n" "/// it returns false.\n" "bool " << Target.getName() << ClassName << "::printInstruction(const MachineInstr *MI) {\n"; std::vector<AsmWriterInst> Instructions; for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) if (!I->second.AsmString.empty()) Instructions.push_back(AsmWriterInst(I->second, Variant)); // Get the instruction numbering. Target.getInstructionsByEnumValue(NumberedInstructions); // 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. 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.push_back(0); // "\0" AggregateString.push_back(0); // "\0" /// 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 Idx; if (AWI == 0) { // Something not handled by the asmwriter printer. Idx = 0; } else if (AWI->Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand || AWI->Operands[0].Str.empty()) { // Something handled by the asmwriter printer, but with no leading string. Idx = 1; } else { unsigned &Entry = StringOffset[AWI->Operands[0].Str]; if (Entry == 0) { // Add the string to the aggregate if this is the first time found. MaxStringIdx = Entry = AggregateString.size(); std::string Str = AWI->Operands[0].Str; UnescapeString(Str); AggregateString += Str; AggregateString += '\0'; } Idx = Entry; // Nuke the string from the operand list. It is now handled! AWI->Operands.erase(AWI->Operands.begin()); } OpcodeInfo.push_back(Idx); } // Figure out how many bits we used for the string index. unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+1); // 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; bool isFirst = true; while (1) { std::vector<std::string> UniqueOperandCommands; // For the first operand check, add a default value for instructions with // just opcode strings to use. if (isFirst) { UniqueOperandCommands.push_back(" return true;\n"); isFirst = false; } 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) { DOUT << "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)) if (!Inst->Operands.empty()) { unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; assert(NumOps <= Inst->Operands.size() && "Can't remove this many ops!"); Inst->Operands.erase(Inst->Operands.begin(), 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// " << NumberedInstructions[i]->TheDef->getName() << "\n"; } // 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 \""; 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 << AggregateString[++i]; ++CharsPrinted; } } } O << "\";\n\n"; O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n" << " O << \"\\t\";\n" << " printInlineAsm(MI);\n" << " return true;\n" << " } else if (MI->getOpcode() == TargetInstrInfo::LABEL) {\n" << " printLabel(MI);\n" << " return true;\n" << " } else if (MI->getOpcode() == TargetInstrInfo::DECLARE) {\n" << " printDeclare(MI);\n" << " return true;\n" << " } else if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {\n" << " printImplicitDef(MI);\n" << " return true;\n" << " }\n\n"; O << " O << \"\\t\";\n\n"; O << " // Emit the opcode for the instruction.\n" << " unsigned Bits = OpInfo[MI->getOpcode()];\n" << " if (Bits == 0) return false;\n" << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\n"; // Output the table driven operand information. BitsLeft = 32-AsmStrBits; for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) { std::vector<std::string> &Commands = TableDrivenOperandPrinters[i]; // Compute the number of bits we need to represent these cases, this is // 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) << ") & " << ((1 << NumBits)-1) << ") {\n" << Commands[1] << " } else {\n" << 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"; O << Commands[i]; O << " break;\n"; } 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? AsmWriterInst &Inst = Instructions[i]; if (Inst.Operands.empty()) { Instructions.erase(Instructions.begin()+i); --i; --e; } } // 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()); if (!Instructions.empty()) { // Find the opcode # of inline asm. O << " switch (MI->getOpcode()) {\n"; while (!Instructions.empty()) EmitInstructions(Instructions, O); O << " }\n"; O << " return true;\n"; } O << "}\n"; }