// 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"; }
/// populateInstInfo - Fills an array of InstInfos with information about each /// instruction in a target /// /// @arg infoArray - The array of InstInfo objects to populate /// @arg target - The CodeGenTarget to use as a source of instructions static void populateInstInfo(CompoundConstantEmitter &infoArray, CodeGenTarget &target) { std::vector<const CodeGenInstruction*> numberedInstructions; target.getInstructionsByEnumValue(numberedInstructions); unsigned int index; unsigned int numInstructions = numberedInstructions.size(); for (index = 0; index < numInstructions; ++index) { const CodeGenInstruction& inst = *numberedInstructions[index]; CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); FlagsConstantEmitter *instFlags = new FlagsConstantEmitter; infoStruct->addEntry(instFlags); LiteralConstantEmitter *numOperandsEmitter = new LiteralConstantEmitter(inst.OperandList.size()); infoStruct->addEntry(numOperandsEmitter); CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; infoStruct->addEntry(operandFlagArray); FlagsConstantEmitter *operandFlags[MAX_OPERANDS]; for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) { operandFlags[operandIndex] = new FlagsConstantEmitter; operandFlagArray->addEntry(operandFlags[operandIndex]); } unsigned numSyntaxes = 0; if (target.getName() == "X86") { X86PopulateOperands(operandFlags, inst); X86ExtractSemantics(*instFlags, operandFlags, inst); numSyntaxes = 2; } CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; infoStruct->addEntry(operandOrderArray); for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) { CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter; operandOrderArray->addEntry(operandOrder); if (syntaxIndex < numSyntaxes) { populateOperandOrder(operandOrder, inst, syntaxIndex); } else { for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) { operandOrder->addEntry(new LiteralConstantEmitter("-1")); } } } } }
/// populateInstInfo - Fills an array of InstInfos with information about each /// instruction in a target /// /// \param infoArray The array of InstInfo objects to populate /// \param target The CodeGenTarget to use as a source of instructions static void populateInstInfo(CompoundConstantEmitter &infoArray, CodeGenTarget &target) { const std::vector<const CodeGenInstruction*> &numberedInstructions = target.getInstructionsByEnumValue(); unsigned int index; unsigned int numInstructions = numberedInstructions.size(); for (index = 0; index < numInstructions; ++index) { const CodeGenInstruction& inst = *numberedInstructions[index]; CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); LiteralConstantEmitter *instType = new LiteralConstantEmitter; infoStruct->addEntry(instType); LiteralConstantEmitter *numOperandsEmitter = new LiteralConstantEmitter(inst.Operands.size()); infoStruct->addEntry(numOperandsEmitter); CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; infoStruct->addEntry(operandTypeArray); LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; infoStruct->addEntry(operandFlagArray); FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; for (unsigned operandIndex = 0; operandIndex < EDIS_MAX_OPERANDS; ++operandIndex) { operandTypes[operandIndex] = new LiteralConstantEmitter; operandTypeArray->addEntry(operandTypes[operandIndex]); operandFlags[operandIndex] = new FlagsConstantEmitter; operandFlagArray->addEntry(operandFlags[operandIndex]); } unsigned numSyntaxes = 0; // We don't need to do anything for pseudo-instructions, as we'll never // see them here. We'll only see real instructions. // We still need to emit null initializers for everything. if (!inst.isPseudo) { if (target.getName() == "X86") { X86PopulateOperands(operandTypes, inst); X86ExtractSemantics(*instType, operandFlags, inst); numSyntaxes = 2; } else if (target.getName() == "ARM") { ARMPopulateOperands(operandTypes, inst); ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); numSyntaxes = 1; } } CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; infoStruct->addEntry(operandOrderArray); for (unsigned syntaxIndex = 0; syntaxIndex < EDIS_MAX_SYNTAXES; ++syntaxIndex) { CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter(EDIS_MAX_OPERANDS); operandOrderArray->addEntry(operandOrder); if (syntaxIndex < numSyntaxes) { populateOperandOrder(operandOrder, inst, syntaxIndex); } } infoStruct = NULL; } }
void CodeEmitterGen::run(raw_ostream &o) { CodeGenTarget Target; std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); // For little-endian instruction bit encodings, reverse the bit order if (Target.isLittleEndianEncoding()) reverseBits(Insts); EmitSourceFileHeader("Machine Code Emitter", o); std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::"; std::vector<const CodeGenInstruction*> NumberedInstructions; Target.getInstructionsByEnumValue(NumberedInstructions); // Emit function declaration o << "unsigned " << Target.getName() << "CodeEmitter::" << "getBinaryCodeForInstr(const MachineInstr &MI) {\n"; // Emit instruction base values o << " static const unsigned InstBits[] = {\n"; for (std::vector<const CodeGenInstruction*>::iterator IN = NumberedInstructions.begin(), EN = NumberedInstructions.end(); IN != EN; ++IN) { const CodeGenInstruction *CGI = *IN; Record *R = CGI->TheDef; if (R->getName() == "PHI" || R->getName() == "INLINEASM" || R->getName() == "DBG_LABEL" || R->getName() == "EH_LABEL" || R->getName() == "GC_LABEL" || R->getName() == "KILL" || R->getName() == "EXTRACT_SUBREG" || R->getName() == "INSERT_SUBREG" || R->getName() == "IMPLICIT_DEF" || R->getName() == "SUBREG_TO_REG" || R->getName() == "COPY_TO_REGCLASS") { o << " 0U,\n"; continue; } BitsInit *BI = R->getValueAsBitsInit("Inst"); // Start by filling in fixed values... unsigned Value = 0; for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) { Value |= B->getValue() << (e-i-1); } } o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n"; } o << " 0U\n };\n"; // Map to accumulate all the cases. std::map<std::string, std::vector<std::string> > CaseMap; // Construct all cases statement for each opcode for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); IC != EC; ++IC) { Record *R = *IC; const std::string &InstName = R->getName(); std::string Case(""); if (InstName == "PHI" || InstName == "INLINEASM" || InstName == "DBG_LABEL"|| InstName == "EH_LABEL"|| InstName == "GC_LABEL"|| InstName == "KILL"|| InstName == "EXTRACT_SUBREG" || InstName == "INSERT_SUBREG" || InstName == "IMPLICIT_DEF" || InstName == "SUBREG_TO_REG" || InstName == "COPY_TO_REGCLASS") continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); const std::vector<RecordVal> &Vals = R->getValues(); CodeGenInstruction &CGI = Target.getInstruction(InstName); // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. unsigned op = 0; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) { // Is the operand continuous? If so, we can just mask and OR it in // instead of doing it bit-by-bit, saving a lot in runtime cost. const std::string &VarName = Vals[i].getName(); bool gotOp = false; for (int bit = BI->getNumBits()-1; bit >= 0; ) { int varBit = getVariableBit(VarName, BI, bit); if (varBit == -1) { --bit; } else { int beginInstBit = bit; int beginVarBit = varBit; int N = 1; for (--bit; bit >= 0;) { varBit = getVariableBit(VarName, BI, bit); if (varBit == -1 || varBit != (beginVarBit - N)) break; ++N; --bit; } if (!gotOp) { /// If this operand is not supposed to be emitted by the generated /// emitter, skip it. while (CGI.isFlatOperandNotEmitted(op)) ++op; Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(op++) + "));\n"; gotOp = true; } unsigned opMask = ~0U >> (32-N); int opShift = beginVarBit - N + 1; opMask <<= opShift; opShift = beginInstBit - beginVarBit; if (opShift > 0) { Case += " Value |= (op & " + utostr(opMask) + "U) << " + itostr(opShift) + ";\n"; } else if (opShift < 0) { Case += " Value |= (op & " + utostr(opMask) + "U) >> " + itostr(-opShift) + ";\n"; } else { Case += " Value |= op & " + utostr(opMask) + "U;\n"; } } } } } std::vector<std::string> &InstList = CaseMap[Case]; InstList.push_back(InstName); } // Emit initial function code o << " const unsigned opcode = MI.getOpcode();\n" << " unsigned Value = InstBits[opcode];\n" << " unsigned op = 0;\n" << " op = op; // suppress warning\n" << " switch (opcode) {\n"; // Emit each case statement std::map<std::string, std::vector<std::string> >::iterator IE, EE; for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { const std::string &Case = IE->first; std::vector<std::string> &InstList = IE->second; for (int i = 0, N = InstList.size(); i < N; i++) { if (i) o << "\n"; o << " case " << Namespace << InstList[i] << ":"; } o << " {\n"; o << Case; o << " break;\n" << " }\n"; } // Default case: unhandled opcode o << " default:\n" << " std::string msg;\n" << " raw_string_ostream Msg(msg);\n" << " Msg << \"Not supported instr: \" << MI;\n" << " llvm_report_error(Msg.str());\n" << " }\n" << " return Value;\n" << "}\n\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"; }