/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit /// encodings, reverse the bit order of all instructions. void CodeGenTarget::reverseBitsForLittleEndianEncoding() { if (!isLittleEndianEncoding()) return; std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); for (Record *R : Insts) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); unsigned numBits = BI->getNumBits(); SmallVector<Init *, 16> NewBits(numBits); for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { unsigned bitSwapIdx = numBits - bit - 1; Init *OrigBit = BI->getBit(bit); Init *BitSwap = BI->getBit(bitSwapIdx); NewBits[bit] = BitSwap; NewBits[bitSwapIdx] = OrigBit; } if (numBits % 2) { unsigned middle = (numBits + 1) / 2; NewBits[middle] = BI->getBit(middle); } BitsInit *NewBI = BitsInit::get(NewBits); // Update the bits in reversed order so that emitInstrOpBits will get the // correct endianness. R->getValue("Inst")->setValue(NewBI); } }
static bit_value_t bitFromBits(BitsInit &bits, unsigned index) { if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index))) return bit->getValue() ? BIT_TRUE : BIT_FALSE; // The bit is uninitialized. return BIT_UNSET; }
void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { Record *R = *I; 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" || R->getName() == "DBG_VALUE") continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); unsigned numBits = BI->getNumBits(); BitsInit *NewBI = new BitsInit(numBits); for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { unsigned bitSwapIdx = numBits - bit - 1; Init *OrigBit = BI->getBit(bit); Init *BitSwap = BI->getBit(bitSwapIdx); NewBI->setBit(bit, BitSwap); NewBI->setBit(bitSwapIdx, OrigBit); } if (numBits % 2) { unsigned middle = (numBits + 1) / 2; NewBI->setBit(middle, BI->getBit(middle)); } // Update the bits in reversed order so that emitInstrOpBits will get the // correct endianness. R->getValue("Inst")->setValue(NewBI); } }
// Prints the bit value for each position. static void dumpBits(raw_ostream &o, BitsInit &bits) { unsigned index; for (index = bits.getNumBits(); index > 0; index--) { switch (bitFromBits(bits, index - 1)) { case BIT_TRUE: o << "1"; break; case BIT_FALSE: o << "0"; break; case BIT_UNSET: o << "_"; break; default: assert(0 && "unexpected return value from bitFromBits"); } } }
// // runMCDesc - Print out MC register descriptions. // void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank) { EmitSourceFileHeader("MC Register Information", OS); OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); // The lists of sub-registers, super-registers, and overlaps all go in the // same array. That allows us to share suffixes. typedef std::vector<const CodeGenRegister*> RegVec; SmallVector<RegVec, 4> SubRegLists(Regs.size()); SmallVector<RegVec, 4> OverlapLists(Regs.size()); SequenceToOffsetTable<RegVec, CodeGenRegister::Less> RegSeqs; // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; // Compute the ordered sub-register list. SetVector<const CodeGenRegister*> SR; Reg->addSubRegsPreOrder(SR, RegBank); RegVec &SubRegList = SubRegLists[i]; SubRegList.assign(SR.begin(), SR.end()); RegSeqs.add(SubRegList); // Super-registers are already computed. const RegVec &SuperRegList = Reg->getSuperRegs(); RegSeqs.add(SuperRegList); // The list of overlaps doesn't need to have any particular order, except // Reg itself must be the first element. Pick an ordering that has one of // the other lists as a suffix. RegVec &OverlapList = OverlapLists[i]; const RegVec &Suffix = SubRegList.size() > SuperRegList.size() ? SubRegList : SuperRegList; CodeGenRegister::Set Omit(Suffix.begin(), Suffix.end()); // First element is Reg itself. OverlapList.push_back(Reg); Omit.insert(Reg); // Any elements not in Suffix. CodeGenRegister::Set OSet; Reg->computeOverlaps(OSet, RegBank); std::set_difference(OSet.begin(), OSet.end(), Omit.begin(), Omit.end(), std::back_inserter(OverlapList), CodeGenRegister::Less()); // Finally, Suffix itself. OverlapList.insert(OverlapList.end(), Suffix.begin(), Suffix.end()); RegSeqs.add(OverlapList); } // Compute the final layout of the sequence table. RegSeqs.layout(); OS << "namespace llvm {\n\n"; const std::string &TargetName = Target.getName(); // Emit the shared table of register lists. OS << "extern const uint16_t " << TargetName << "RegLists[] = {\n"; RegSeqs.emit(OS, printRegister); OS << "};\n\n"; OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { \"NOREG\", 0, 0, 0 },\n"; // Emit the register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; OS << " { \"" << Reg->getName() << "\", " << RegSeqs.get(OverlapLists[i]) << ", " << RegSeqs.get(SubRegLists[i]) << ", " << RegSeqs.get(Reg->getSuperRegs()) << " },\n"; } OS << "};\n\n"; // End of register descriptors... ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const uint16_t " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; } OS << "\n };\n\n"; OS << " // " << Name << " Bit set.\n" << " const uint8_t " << Name << "Bits[] = {\n "; BitVectorEmitter BVE; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); } BVE.print(OS); OS << "\n };\n\n"; } OS << "}\n\n"; OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); OS << " { " << '\"' << RC.getName() << "\", " << RC.getName() << ", " << RC.getName() << "Bits, " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " << RC.Allocatable << " },\n"; } OS << "};\n\n"; // Emit the data table for getSubReg(). ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); if (SubRegIndices.size()) { OS << "const uint16_t " << TargetName << "SubRegTable[][" << SubRegIndices.size() << "] = {\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); OS << " /* " << Regs[i]->TheDef->getName() << " */\n"; if (SRM.empty()) { OS << " {0},\n"; continue; } OS << " {"; for (unsigned j = 0, je = SubRegIndices.size(); j != je; ++j) { // FIXME: We really should keep this to 80 columns... CodeGenRegister::SubRegMap::const_iterator SubReg = SRM.find(SubRegIndices[j]); if (SubReg != SRM.end()) OS << getQualifiedName(SubReg->second->TheDef); else OS << "0"; if (j != je - 1) OS << ", "; } OS << "}" << (i != e ? "," : "") << "\n"; } OS << "};\n\n"; OS << "const uint16_t *get" << TargetName << "SubRegTable() {\n return (const uint16_t *)" << TargetName << "SubRegTable;\n}\n\n"; } EmitRegMappingTables(OS, Regs, false); // Emit Reg encoding table OS << "extern const uint16_t " << TargetName; OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record *Reg = Regs[i]->TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(b))) Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } OS << "};\n"; // End of HW encoding table // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n"; OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegLists, "; if (SubRegIndices.size() != 0) OS << "(uint16_t*)" << TargetName << "SubRegTable, " << SubRegIndices.size() << ",\n"; else OS << "NULL, 0,\n"; OS << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; }
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EmittedLists, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; if (!Inst.Operands.empty()) // Each logical operand can be multiple MI operands. MinOperands = Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t" << SchedModels.getSchedClassIdx(Inst) << ",\t0"; // Emit all of the target independent flags... if (Inst.isPseudo) OS << "|(1ULL<<MCID::Pseudo)"; if (Inst.isReturn) OS << "|(1ULL<<MCID::Return)"; if (Inst.isBranch) OS << "|(1ULL<<MCID::Branch)"; if (Inst.isIndirectBranch) OS << "|(1ULL<<MCID::IndirectBranch)"; if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)"; if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)"; if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)"; if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)"; if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)"; if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)"; if (Inst.isCall) OS << "|(1ULL<<MCID::Call)"; if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)"; if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)"; if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)"; if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)"; if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)"; if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)"; if (Inst.isTerminator) OS << "|(1ULL<<MCID::Terminator)"; if (Inst.isReMaterializable) OS << "|(1ULL<<MCID::Rematerializable)"; if (Inst.isNotDuplicable) OS << "|(1ULL<<MCID::NotDuplicable)"; if (Inst.Operands.hasOptionalDef) OS << "|(1ULL<<MCID::HasOptionalDef)"; if (Inst.usesCustomInserter) OS << "|(1ULL<<MCID::UsesCustomInserter)"; if (Inst.hasPostISelHook) OS << "|(1ULL<<MCID::HasPostISelHook)"; if (Inst.Operands.isVariadic)OS << "|(1ULL<<MCID::Variadic)"; if (Inst.hasSideEffects) OS << "|(1ULL<<MCID::UnmodeledSideEffects)"; if (Inst.isAsCheapAsAMove) OS << "|(1ULL<<MCID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)"; if (Inst.isRegSequence) OS << "|(1ULL<<MCID::RegSequence)"; if (Inst.isExtractSubreg) OS << "|(1ULL<<MCID::ExtractSubreg)"; if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)"; if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); if (!TSF) PrintFatalError("no TSFlags?"); uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i))) Value |= uint64_t(Bit->getValue()) << i; else PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); } OS << ", 0x"; OS.write_hex(Value); OS << "ULL, "; // Emit the implicit uses and defs lists... std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); if (UseList.empty()) OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[UseList] << ", "; std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); if (DefList.empty()) OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) OS << "nullptr"; else OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; CodeGenTarget &Target = CDP.getTargetInfo(); if (Inst.HasComplexDeprecationPredicate) // Emit a function pointer to the complex predicate method. OS << ", -1 " << ",&get" << Inst.DeprecatedReason << "DeprecationInfo"; else if (!Inst.DeprecatedReason.empty()) // Emit the Subtarget feature. OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason << " ,nullptr"; else // Instruction isn't deprecated. OS << ", -1 ,nullptr"; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; }
// // runMCDesc - Print out MC register descriptions. // void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank) { emitSourceFileHeader("MC Register Information", OS); OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); // The lists of sub-registers, super-registers, and overlaps all go in the // same array. That allows us to share suffixes. typedef std::vector<const CodeGenRegister*> RegVec; // Differentially encoded lists. SequenceToOffsetTable<DiffVec> DiffSeqs; SmallVector<DiffVec, 4> SubRegLists(Regs.size()); SmallVector<DiffVec, 4> SuperRegLists(Regs.size()); SmallVector<DiffVec, 4> OverlapLists(Regs.size()); SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); SmallVector<unsigned, 4> RegUnitInitScale(Regs.size()); // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec; SequenceToOffsetTable<SubRegIdxVec> SubRegIdxSeqs; SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); SequenceToOffsetTable<std::string> RegStrings; // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; RegStrings.add(Reg->getName()); // Compute the ordered sub-register list. SetVector<const CodeGenRegister*> SR; Reg->addSubRegsPreOrder(SR, RegBank); diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) SRIs.push_back(Reg->getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. const RegVec &SuperRegList = Reg->getSuperRegs(); diffEncode(SuperRegLists[i], Reg->EnumValue, SuperRegList.begin(), SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); // The list of overlaps doesn't need to have any particular order, and Reg // itself must be omitted. DiffVec &OverlapList = OverlapLists[i]; CodeGenRegister::Set OSet; Reg->computeOverlaps(OSet, RegBank); OSet.erase(Reg); diffEncode(OverlapList, Reg->EnumValue, OSet.begin(), OSet.end()); DiffSeqs.add(OverlapList); // Differentially encode the register unit list, seeded by register number. // First compute a scale factor that allows more diff-lists to be reused: // // D0 -> (S0, S1) // D1 -> (S2, S3) // // A scale factor of 2 allows D0 and D1 to share a diff-list. The initial // value for the differential decoder is the register number multiplied by // the scale. // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; ArrayRef<unsigned> RUs = Reg->getNativeRegUnits(); if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); if (i+1 != Regs.size() && Regs[i+1]->getNativeRegUnits().size() == RUs.size()) ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); } // Compute the final layout of the sequence table. DiffSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; const std::string &TargetName = Target.getName(); // Emit the shared table of differential lists. OS << "extern const uint16_t " << TargetName << "RegDiffLists[] = {\n"; DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; // Emit the string table. RegStrings.layout(); OS << "extern const char " << TargetName << "RegStrings[] = {\n"; RegStrings.emit(OS, printChar); OS << "};\n\n"; OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; // Emit the register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; OS << " { " << RegStrings.get(Reg->getName()) << ", " << DiffSeqs.get(OverlapLists[i]) << ", " << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; } OS << "};\n\n"; // End of register descriptors... // Emit the table of register unit roots. Each regunit has one or two root // registers. OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); assert(Roots.size() <= 2 && "More than two roots not supported yet."); OS << " { " << getQualifiedName(Roots.front()->TheDef); for (unsigned r = 1; r != Roots.size(); ++r) OS << ", " << getQualifiedName(Roots[r]->TheDef); OS << " },\n"; } OS << "};\n\n"; ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const uint16_t " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; } OS << "\n };\n\n"; OS << " // " << Name << " Bit set.\n" << " const uint8_t " << Name << "Bits[] = {\n "; BitVectorEmitter BVE; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); } BVE.print(OS); OS << "\n };\n\n"; } OS << "}\n\n"; OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); OS << " { " << '\"' << RC.getName() << "\", " << RC.getName() << ", " << RC.getName() << "Bits, " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " << RC.Allocatable << " },\n"; } OS << "};\n\n"; ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); EmitRegMappingTables(OS, Regs, false); // Emit Reg encoding table OS << "extern const uint16_t " << TargetName; OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record *Reg = Regs[i]->TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(b))) Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } OS << "};\n"; // End of HW encoding table // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " << TargetName << "SubRegIdxLists, " << SubRegIndices.size() << ",\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; }
/// SetValue - /// Return true on error, false on success. bool TGParser::SetValue(Record *CurRec, TGLoc Loc, const std::string &ValName, const std::vector<unsigned> &BitList, Init *V) { if (!V) return false; if (CurRec == 0) CurRec = &CurMultiClass->Rec; RecordVal *RV = CurRec->getValue(ValName); if (RV == 0) return Error(Loc, "Value '" + ValName + "' unknown!"); // Do not allow assignments like 'X = X'. This will just cause infinite loops // in the resolution machinery. if (BitList.empty()) if (VarInit *VI = dynamic_cast<VarInit*>(V)) if (VI->getName() == ValName) return false; // If we are assigning to a subset of the bits in the value... then we must be // assigning to a field of BitsRecTy, which must have a BitsInit // initializer. // if (!BitList.empty()) { BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue()); if (CurVal == 0) return Error(Loc, "Value '" + ValName + "' is not a bits type"); // Convert the incoming value to a bits type of the appropriate size... Init *BI = V->convertInitializerTo(new BitsRecTy(BitList.size())); if (BI == 0) { V->convertInitializerTo(new BitsRecTy(BitList.size())); return Error(Loc, "Initializer is not compatible with bit range"); } // We should have a BitsInit type now. BitsInit *BInit = dynamic_cast<BitsInit*>(BI); assert(BInit != 0); BitsInit *NewVal = new BitsInit(CurVal->getNumBits()); // Loop over bits, assigning values as appropriate. for (unsigned i = 0, e = BitList.size(); i != e; ++i) { unsigned Bit = BitList[i]; if (NewVal->getBit(Bit)) return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + ValName + "' more than once"); NewVal->setBit(Bit, BInit->getBit(i)); } for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) if (NewVal->getBit(i) == 0) NewVal->setBit(i, CurVal->getBit(i)); V = NewVal; } if (RV->setValue(V)) return Error(Loc, "Value '" + ValName + "' of type '" + RV->getType()->getAsString() + "' is incompatible with initializer '" + V->getAsString() +"'"); return false; }
/// ParseSimpleValue - Parse a tblgen value. This returns null on error. /// /// SimpleValue ::= IDValue /// SimpleValue ::= INTVAL /// SimpleValue ::= STRVAL+ /// SimpleValue ::= CODEFRAGMENT /// SimpleValue ::= '?' /// SimpleValue ::= '{' ValueList '}' /// SimpleValue ::= ID '<' ValueListNE '>' /// SimpleValue ::= '[' ValueList ']' /// SimpleValue ::= '(' IDValue DagArgList ')' /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= SHLTOK '(' Value ',' Value ')' /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// Init *TGParser::ParseSimpleValue(Record *CurRec) { Init *R = 0; switch (Lex.getCode()) { default: TokError("Unknown token when parsing a value"); break; case tgtok::IntVal: R = new IntInit(Lex.getCurIntVal()); Lex.Lex(); break; case tgtok::StrVal: { std::string Val = Lex.getCurStrVal(); Lex.Lex(); // Handle multiple consecutive concatenated strings. while (Lex.getCode() == tgtok::StrVal) { Val += Lex.getCurStrVal(); Lex.Lex(); } R = new StringInit(Val); break; } case tgtok::CodeFragment: R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: R = new UnsetInit(); Lex.Lex(); break; case tgtok::Id: { TGLoc NameLoc = Lex.getLoc(); std::string Name = Lex.getCurStrVal(); if (Lex.Lex() != tgtok::less) // consume the Id. return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue // Value ::= ID '<' ValueListNE '>' if (Lex.Lex() == tgtok::greater) { TokError("expected non-empty value list"); return 0; } std::vector<Init*> ValueList = ParseValueList(CurRec); if (ValueList.empty()) return 0; if (Lex.getCode() != tgtok::greater) { TokError("expected '>' at end of value list"); return 0; } Lex.Lex(); // eat the '>' // This is a CLASS<initvalslist> expression. This is supposed to synthesize // a new anonymous definition, deriving from CLASS<initvalslist> with no // body. Record *Class = Records.getClass(Name); if (!Class) { Error(NameLoc, "Expected a class name, got '" + Name + "'"); return 0; } // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),NameLoc); SubClassReference SCRef; SCRef.RefLoc = NameLoc; SCRef.Rec = Class; SCRef.TemplateArgs = ValueList; // Add info about the subclass to NewRec. if (AddSubClass(NewRec, SCRef)) return 0; NewRec->resolveReferences(); Records.addDef(NewRec); // The result of the expression is a reference to the new record. return new DefInit(NewRec); } case tgtok::l_brace: { // Value ::= '{' ValueList '}' TGLoc BraceLoc = Lex.getLoc(); Lex.Lex(); // eat the '{' std::vector<Init*> Vals; if (Lex.getCode() != tgtok::r_brace) { Vals = ParseValueList(CurRec); if (Vals.empty()) return 0; } if (Lex.getCode() != tgtok::r_brace) { TokError("expected '}' at end of bit list value"); return 0; } Lex.Lex(); // eat the '}' BitsInit *Result = new BitsInit(Vals.size()); for (unsigned i = 0, e = Vals.size(); i != e; ++i) { Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy()); if (Bit == 0) { Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ ") is not convertable to a bit"); return 0; } Result->setBit(Vals.size()-i-1, Bit); } return Result; } case tgtok::l_square: { // Value ::= '[' ValueList ']' Lex.Lex(); // eat the '[' std::vector<Init*> Vals; if (Lex.getCode() != tgtok::r_square) { Vals = ParseValueList(CurRec); if (Vals.empty()) return 0; } if (Lex.getCode() != tgtok::r_square) { TokError("expected ']' at end of list value"); return 0; } Lex.Lex(); // eat the ']' return new ListInit(Vals); } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' if (Lex.getCode() != tgtok::Id) { TokError("expected identifier in dag init"); return 0; } Init *Operator = ParseIDValue(CurRec); if (Operator == 0) return 0; // If the operator name is present, parse it. std::string OperatorName; if (Lex.getCode() == tgtok::colon) { if (Lex.Lex() != tgtok::VarName) { // eat the ':' TokError("expected variable name in dag operator"); return 0; } OperatorName = Lex.getCurStrVal(); Lex.Lex(); // eat the VarName. } std::vector<std::pair<llvm::Init*, std::string> > DagArgs; if (Lex.getCode() != tgtok::r_paren) { DagArgs = ParseDagArgList(CurRec); if (DagArgs.empty()) return 0; } if (Lex.getCode() != tgtok::r_paren) { TokError("expected ')' in dag init"); return 0; } Lex.Lex(); // eat the ')' return new DagInit(Operator, OperatorName, DagArgs); } case tgtok::XConcat: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' BinOpInit::BinaryOp Code; switch (Lex.getCode()) { default: assert(0 && "Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT; break; case tgtok::XSRA: Code = BinOpInit::SRA; break; case tgtok::XSRL: Code = BinOpInit::SRL; break; case tgtok::XSHL: Code = BinOpInit::SHL; break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; } Lex.Lex(); // eat the operation if (Lex.getCode() != tgtok::l_paren) { TokError("expected '(' after binary operator"); return 0; } Lex.Lex(); // eat the '(' Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; if (Lex.getCode() != tgtok::comma) { TokError("expected ',' in binary operator"); return 0; } Lex.Lex(); // eat the ',' Init *RHS = ParseValue(CurRec); if (RHS == 0) return 0; if (Lex.getCode() != tgtok::r_paren) { TokError("expected ')' in binary operator"); return 0; } Lex.Lex(); // eat the ')' return (new BinOpInit(Code, LHS, RHS))->Fold(); } } return R; }
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EmittedLists, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; if (!Inst.Operands.size() == 0) // Each logical operand can be multiple MI operands. MinOperands = Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t0"; // Emit all of the target indepedent flags... if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)"; if (Inst.isReturn) OS << "|(1<<MCID::Return)"; if (Inst.isBranch) OS << "|(1<<MCID::Branch)"; if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)"; if (Inst.isCompare) OS << "|(1<<MCID::Compare)"; if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)"; if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)"; if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)"; if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)"; if (Inst.isCall) OS << "|(1<<MCID::Call)"; if (Inst.canFoldAsLoad) OS << "|(1<<MCID::FoldableAsLoad)"; if (Inst.mayLoad) OS << "|(1<<MCID::MayLoad)"; if (Inst.mayStore) OS << "|(1<<MCID::MayStore)"; if (Inst.isPredicable) OS << "|(1<<MCID::Predicable)"; if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)"; if (Inst.isCommutable) OS << "|(1<<MCID::Commutable)"; if (Inst.isTerminator) OS << "|(1<<MCID::Terminator)"; if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)"; if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)"; if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)"; if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)"; if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)"; if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)"; if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)"; if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); if (!TSF) throw "no TSFlags?"; uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i))) Value |= uint64_t(Bit->getValue()) << i; else throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); } OS << ", 0x"; OS.write_hex(Value); OS << "ULL, "; // Emit the implicit uses and defs lists... std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); if (UseList.empty()) OS << "NULL, "; else OS << "ImplicitList" << EmittedLists[UseList] << ", "; std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); if (DefList.empty()) OS << "NULL, "; else OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) OS << "0"; else OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; }
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 CodeEmitterGen::run(std::ostream &o) { std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); EmitSourceFileHeader("Machine Code Emitter", o); std::string Namespace = "V9::"; std::string ClassName = "SparcV9CodeEmitter::"; //const std::string &Namespace = Inst->getValue("Namespace")->getName(); o << "unsigned " << ClassName << "getBinaryCodeForInstr(MachineInstr &MI) {\n" << " unsigned Value = 0;\n" << " DEBUG(std::cerr << MI);\n" << " switch (MI.getOpcode()) {\n"; for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { Record *R = *I; o << " case " << Namespace << R->getName() << ": {\n" << " DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n"; BitsInit *BI = R->getValueAsBitsInit("Inst"); unsigned Value = 0; const std::vector<RecordVal> &Vals = R->getValues(); DEBUG(o << " // prefilling: "); // Start by filling in fixed values... 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); DEBUG(o << B->getValue()); } else { DEBUG(o << "0"); } } DEBUG(o << "\n"); DEBUG(o << " // " << *R->getValue("Inst") << "\n"); o << " Value = " << Value << "U;\n\n"; // Loop over all of the fields in the instruction determining which are the // operands to the instruction. // unsigned op = 0; std::map<std::string, unsigned> OpOrder; std::map<std::string, bool> OpContinuous; 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 BitsInit *InstInit = BI; int beginBitInVar = -1, endBitInVar = -1; int beginBitInInst = -1, endBitInInst = -1; bool continuous = true; for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) { if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { // only process the current variable if (VI->getName() != Vals[i].getName()) continue; if (beginBitInVar == -1) beginBitInVar = VBI->getBitNum(); if (endBitInVar == -1) endBitInVar = VBI->getBitNum(); else { if (endBitInVar == (int)VBI->getBitNum() + 1) endBitInVar = VBI->getBitNum(); else { continuous = false; break; } } if (beginBitInInst == -1) beginBitInInst = bit; if (endBitInInst == -1) endBitInInst = bit; else { if (endBitInInst == bit + 1) endBitInInst = bit; else { continuous = false; break; } } // maintain same distance between bits in field and bits in // instruction. if the relative distances stay the same // throughout, if (beginBitInVar - (int)VBI->getBitNum() != beginBitInInst - bit) { continuous = false; break; } } } } // If we have found no bit in "Inst" which comes from this field, then // this is not an operand!! if (beginBitInInst != -1) { o << " // op" << op << ": " << Vals[i].getName() << "\n" << " int64_t op" << op <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n"; //<< " MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n"; OpOrder[Vals[i].getName()] = op++; DEBUG(o << " // Var: begin = " << beginBitInVar << ", end = " << endBitInVar << "; Inst: begin = " << beginBitInInst << ", end = " << endBitInInst << "\n"); if (continuous) { DEBUG(o << " // continuous: op" << OpOrder[Vals[i].getName()] << "\n"); // Mask off the right bits // Low mask (ie. shift, if necessary) assert(endBitInVar >= 0 && "Negative shift amount in masking!"); if (endBitInVar != 0) { o << " op" << OpOrder[Vals[i].getName()] << " >>= " << endBitInVar << ";\n"; beginBitInVar -= endBitInVar; endBitInVar = 0; } // High mask o << " op" << OpOrder[Vals[i].getName()] << " &= (1<<" << beginBitInVar+1 << ") - 1;\n"; // Shift the value to the correct place (according to place in inst) assert(endBitInInst >= 0 && "Negative shift amount!"); if (endBitInInst != 0) o << " op" << OpOrder[Vals[i].getName()] << " <<= " << endBitInInst << ";\n"; // Just OR in the result o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n"; } // otherwise, will be taken care of in the loop below using this // value: OpContinuous[Vals[i].getName()] = continuous; } } } for (unsigned f = 0, e = Vals.size(); f != e; ++f) { if (Vals[f].getPrefix()) { BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue(); // Scan through the field looking for bit initializers of the current // variable... for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { if (BitInit *BI = dynamic_cast<BitInit*>(FieldInitializer->getBit(i))) { DEBUG(o << " // bit init: f: " << f << ", i: " << i << "\n"); } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) { DEBUG(o << " // unset init: f: " << f << ", i: " << i << "\n"); } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { // If the bits of the field are laid out consecutively in the // instruction, then instead of separately ORing in bits, just // mask and shift the entire field for efficiency. if (OpContinuous[VI->getName()]) { // already taken care of in the loop above, thus there is no // need to individually OR in the bits // for debugging, output the regular version anyway, commented DEBUG(o << " // Value |= getValueBit(op" << OpOrder[VI->getName()] << ", " << VBI->getBitNum() << ")" << " << " << i << ";\n"); } else { o << " Value |= getValueBit(op" << OpOrder[VI->getName()] << ", " << VBI->getBitNum() << ")" << " << " << i << ";\n"; } } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) { // FIXME: implement this! o << "FIELD INIT not implemented yet!\n"; } else { o << "Error: UNIMPLEMENTED\n"; } } } } } o << " break;\n" << " }\n"; } o << " default:\n" << " std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n" << " abort();\n" << " }\n" << " return Value;\n" << "}\n"; EmitSourceFileTail(o); }