| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "InstructionEncoding.h" | |
| #include "CodeGenInstruction.h" | |
| #include "VarLenCodeEmitterGen.h" | |
| #include "llvm/Support/FormatVariadic.h" | |
| #include "llvm/TableGen/Error.h" | |
| using namespace llvm; | |
| std::pair<std::string, bool> | |
| InstructionEncoding::findOperandDecoderMethod(const Record *Record) { | |
| std::string Decoder; | |
| const RecordVal *DecoderString = Record->getValue("DecoderMethod"); | |
| const StringInit *String = | |
| DecoderString ? dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; | |
| if (String) { | |
| Decoder = String->getValue().str(); | |
| if (!Decoder.empty()) | |
| return {Decoder, false}; | |
| } | |
| if (Record->isSubClassOf("RegisterOperand")) | |
| // Allows use of a DecoderMethod in referenced RegisterClass if set. | |
| return findOperandDecoderMethod(Record->getValueAsDef("RegClass")); | |
| if (Record->isSubClassOf("RegisterClass")) { | |
| Decoder = "Decode" + Record->getName().str() + "RegisterClass"; | |
| } else if (Record->isSubClassOf("RegClassByHwMode")) { | |
| Decoder = "Decode" + Record->getName().str() + "RegClassByHwMode"; | |
| } | |
| return {Decoder, true}; | |
| } | |
| OperandInfo InstructionEncoding::getOpInfo(const Record *TypeRecord) { | |
| const RecordVal *HasCompleteDecoderVal = | |
| TypeRecord->getValue("hasCompleteDecoder"); | |
| const BitInit *HasCompleteDecoderBit = | |
| HasCompleteDecoderVal | |
| ? dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) | |
| : nullptr; | |
| bool HasCompleteDecoder = | |
| HasCompleteDecoderBit ? HasCompleteDecoderBit->getValue() : true; | |
| return OperandInfo(findOperandDecoderMethod(TypeRecord).first, | |
| HasCompleteDecoder); | |
| } | |
| void InstructionEncoding::parseVarLenEncoding(const VarLenInst &VLI) { | |
| InstBits = KnownBits(VLI.size()); | |
| SoftFailMask = APInt(VLI.size(), 0); | |
| // Parse Inst field. | |
| unsigned I = 0; | |
| for (const EncodingSegment &S : VLI) { | |
| if (const auto *SegmentBits = dyn_cast<BitsInit>(S.Value)) { | |
| for (const Init *V : SegmentBits->getBits()) { | |
| if (const auto *B = dyn_cast<BitInit>(V)) { | |
| if (B->getValue()) | |
| InstBits.One.setBit(I); | |
| else | |
| InstBits.Zero.setBit(I); | |
| } | |
| ++I; | |
| } | |
| } else if (const auto *B = dyn_cast<BitInit>(S.Value)) { | |
| if (B->getValue()) | |
| InstBits.One.setBit(I); | |
| else | |
| InstBits.Zero.setBit(I); | |
| ++I; | |
| } else { | |
| I += S.BitWidth; | |
| } | |
| } | |
| assert(I == VLI.size()); | |
| } | |
| void InstructionEncoding::parseFixedLenEncoding( | |
| const BitsInit &RecordInstBits) { | |
| // For fixed length instructions, sometimes the `Inst` field specifies more | |
| // bits than the actual size of the instruction, which is specified in `Size`. | |
| // In such cases, we do some basic validation and drop the upper bits. | |
| unsigned BitWidth = EncodingDef->getValueAsInt("Size") * 8; | |
| unsigned InstNumBits = RecordInstBits.getNumBits(); | |
| // Returns true if all bits in `Bits` are zero or unset. | |
| auto CheckAllZeroOrUnset = [&](ArrayRef<const Init *> Bits, | |
| const RecordVal *Field) { | |
| bool AllZeroOrUnset = llvm::all_of(Bits, [](const Init *Bit) { | |
| if (const auto *BI = dyn_cast<BitInit>(Bit)) | |
| return !BI->getValue(); | |
| return isa<UnsetInit>(Bit); | |
| }); | |
| if (AllZeroOrUnset) | |
| return; | |
| PrintNote([Field](raw_ostream &OS) { Field->print(OS); }); | |
| PrintFatalError(EncodingDef, Twine(Name) + ": Size is " + Twine(BitWidth) + | |
| " bits, but " + Field->getName() + | |
| " bits beyond that are not zero/unset"); | |
| }; | |
| if (InstNumBits < BitWidth) | |
| PrintFatalError(EncodingDef, Twine(Name) + ": Size is " + Twine(BitWidth) + | |
| " bits, but Inst specifies only " + | |
| Twine(InstNumBits) + " bits"); | |
| if (InstNumBits > BitWidth) { | |
| // Ensure that all the bits beyond 'Size' are 0 or unset (i.e., carry no | |
| // actual encoding). | |
| ArrayRef<const Init *> UpperBits = | |
| RecordInstBits.getBits().drop_front(BitWidth); | |
| const RecordVal *InstField = EncodingDef->getValue("Inst"); | |
| CheckAllZeroOrUnset(UpperBits, InstField); | |
| } | |
| ArrayRef<const Init *> ActiveInstBits = | |
| RecordInstBits.getBits().take_front(BitWidth); | |
| InstBits = KnownBits(BitWidth); | |
| SoftFailMask = APInt(BitWidth, 0); | |
| // Parse Inst field. | |
| for (auto [I, V] : enumerate(ActiveInstBits)) { | |
| if (const auto *B = dyn_cast<BitInit>(V)) { | |
| if (B->getValue()) | |
| InstBits.One.setBit(I); | |
| else | |
| InstBits.Zero.setBit(I); | |
| } | |
| } | |
| // Parse SoftFail field. | |
| const RecordVal *SoftFailField = EncodingDef->getValue("SoftFail"); | |
| if (!SoftFailField) | |
| return; | |
| const auto *SFBits = dyn_cast<BitsInit>(SoftFailField->getValue()); | |
| if (!SFBits || SFBits->getNumBits() != InstNumBits) { | |
| PrintNote(EncodingDef->getLoc(), "in record"); | |
| PrintFatalError(SoftFailField, | |
| formatv("SoftFail field, if defined, must be " | |
| "of the same type as Inst, which is bits<{}>", | |
| InstNumBits)); | |
| } | |
| if (InstNumBits > BitWidth) { | |
| // Ensure that all upper bits of `SoftFail` are 0 or unset. | |
| ArrayRef<const Init *> UpperBits = SFBits->getBits().drop_front(BitWidth); | |
| CheckAllZeroOrUnset(UpperBits, SoftFailField); | |
| } | |
| ArrayRef<const Init *> ActiveSFBits = SFBits->getBits().take_front(BitWidth); | |
| for (auto [I, V] : enumerate(ActiveSFBits)) { | |
| if (const auto *B = dyn_cast<BitInit>(V); B && B->getValue()) { | |
| if (!InstBits.Zero[I] && !InstBits.One[I]) { | |
| PrintNote(EncodingDef->getLoc(), "in record"); | |
| PrintError(SoftFailField, | |
| formatv("SoftFail{{{0}} = 1 requires Inst{{{0}} " | |
| "to be fully defined (0 or 1, not '?')", | |
| I)); | |
| } | |
| SoftFailMask.setBit(I); | |
| } | |
| } | |
| } | |
| void InstructionEncoding::parseVarLenOperands(const VarLenInst &VLI) { | |
| SmallVector<int> TiedTo; | |
| for (const auto &[Idx, Op] : enumerate(Inst->Operands)) { | |
| if (Op.MIOperandInfo && Op.MIOperandInfo->getNumArgs() > 0) | |
| for (auto *Arg : Op.MIOperandInfo->getArgs()) | |
| Operands.push_back(getOpInfo(cast<DefInit>(Arg)->getDef())); | |
| else | |
| Operands.push_back(getOpInfo(Op.Rec)); | |
| int TiedReg = Op.getTiedRegister(); | |
| TiedTo.push_back(-1); | |
| if (TiedReg != -1) { | |
| TiedTo[Idx] = TiedReg; | |
| TiedTo[TiedReg] = Idx; | |
| } | |
| } | |
| unsigned CurrBitPos = 0; | |
| for (const auto &EncodingSegment : VLI) { | |
| unsigned Offset = 0; | |
| StringRef OpName; | |
| if (const StringInit *SI = dyn_cast<StringInit>(EncodingSegment.Value)) { | |
| OpName = SI->getValue(); | |
| } else if (const DagInit *DI = dyn_cast<DagInit>(EncodingSegment.Value)) { | |
| OpName = cast<StringInit>(DI->getArg(0))->getValue(); | |
| Offset = cast<IntInit>(DI->getArg(2))->getValue(); | |
| } | |
| if (!OpName.empty()) { | |
| auto OpSubOpPair = Inst->Operands.parseOperandName(OpName); | |
| unsigned OpIdx = Inst->Operands.getFlattenedOperandNumber(OpSubOpPair); | |
| Operands[OpIdx].Fields.emplace_back(CurrBitPos, EncodingSegment.BitWidth, | |
| Offset); | |
| if (!EncodingSegment.CustomDecoder.empty()) | |
| Operands[OpIdx].Decoder = EncodingSegment.CustomDecoder.str(); | |
| int TiedReg = TiedTo[OpSubOpPair.first]; | |
| if (TiedReg != -1) { | |
| unsigned OpIdx = Inst->Operands.getFlattenedOperandNumber( | |
| {TiedReg, OpSubOpPair.second}); | |
| Operands[OpIdx].Fields.emplace_back(CurrBitPos, | |
| EncodingSegment.BitWidth, Offset); | |
| } | |
| } | |
| CurrBitPos += EncodingSegment.BitWidth; | |
| } | |
| } | |
| static void debugDumpRecord(const Record &Rec) { | |
| // Dump the record, so we can see what's going on. | |
| PrintNote([&Rec](raw_ostream &OS) { | |
| OS << "Dumping record for previous error:\n"; | |
| OS << Rec; | |
| }); | |
| } | |
| /// For an operand field named OpName: populate OpInfo.InitValue with the | |
| /// constant-valued bit values, and OpInfo.Fields with the ranges of bits to | |
| /// insert from the decoded instruction. | |
| static void addOneOperandFields(const Record *EncodingDef, | |
| const BitsInit &InstBits, | |
| std::map<StringRef, StringRef> &TiedNames, | |
| const Record *OpRec, StringRef OpName, | |
| OperandInfo &OpInfo) { | |
| OpInfo.Name = OpName; | |
| // Find a field with the operand's name. | |
| const RecordVal *OpEncodingField = EncodingDef->getValue(OpName); | |
| // If there is no such field, try tied operand's name. | |
| if (!OpEncodingField) { | |
| if (auto I = TiedNames.find(OpName); I != TiedNames.end()) | |
| OpEncodingField = EncodingDef->getValue(I->second); | |
| // If still no luck, we're done with this operand. | |
| if (!OpEncodingField) { | |
| OpInfo.HasNoEncoding = true; | |
| return; | |
| } | |
| } | |
| // Some or all bits of the operand may be required to be 0 or 1 depending | |
| // on the instruction's encoding. Collect those bits. | |
| if (const auto *OpBit = dyn_cast<BitInit>(OpEncodingField->getValue())) { | |
| OpInfo.InitValue = OpBit->getValue(); | |
| return; | |
| } | |
| if (const auto *OpBits = dyn_cast<BitsInit>(OpEncodingField->getValue())) { | |
| if (OpBits->getNumBits() == 0) { | |
| if (OpInfo.Decoder.empty()) { | |
| PrintError(EncodingDef->getLoc(), "operand '" + OpName + "' of type '" + | |
| OpRec->getName() + | |
| "' must have a decoder method"); | |
| } | |
| return; | |
| } | |
| for (unsigned I = 0; I < OpBits->getNumBits(); ++I) { | |
| if (const auto *OpBit = dyn_cast<BitInit>(OpBits->getBit(I))) | |
| OpInfo.InitValue = OpInfo.InitValue.value_or(0) | | |
| static_cast<uint64_t>(OpBit->getValue()) << I; | |
| } | |
| } | |
| // Find out where the variable bits of the operand are encoded. The bits don't | |
| // have to be consecutive or in ascending order. For example, an operand could | |
| // be encoded as follows: | |
| // | |
| // 7 6 5 4 3 2 1 0 | |
| // {1, op{5}, op{2}, op{1}, 0, op{4}, op{3}, ?} | |
| // | |
| // In this example the operand is encoded in three segments: | |
| // | |
| // Base Width Offset | |
| // op{2...1} 4 2 1 | |
| // op{4...3} 1 2 3 | |
| // op{5} 6 1 5 | |
| // | |
| for (unsigned I = 0, J = 0; I != InstBits.getNumBits(); I = J) { | |
| const VarInit *Var; | |
| unsigned Offset = 0; | |
| for (; J != InstBits.getNumBits(); ++J) { | |
| const Init *BitJ = InstBits.getBit(J); | |
| if (const auto *VBI = dyn_cast<VarBitInit>(BitJ)) { | |
| Var = dyn_cast<VarInit>(VBI->getBitVar()); | |
| if (I == J) | |
| Offset = VBI->getBitNum(); | |
| else if (VBI->getBitNum() != Offset + J - I) | |
| break; | |
| } else { | |
| Var = dyn_cast<VarInit>(BitJ); | |
| } | |
| if (!Var || | |
| (Var->getName() != OpName && Var->getName() != TiedNames[OpName])) | |
| break; | |
| } | |
| if (I == J) | |
| ++J; | |
| else | |
| OpInfo.Fields.emplace_back(I, J - I, Offset); | |
| } | |
| if (!OpInfo.InitValue && OpInfo.Fields.empty()) { | |
| // We found a field in InstructionEncoding record that corresponds to the | |
| // named operand, but that field has no constant bits and doesn't contribute | |
| // to the Inst field. For now, treat that field as if it didn't exist. | |
| // TODO: Remove along with IgnoreNonDecodableOperands. | |
| OpInfo.HasNoEncoding = true; | |
| } | |
| } | |
| void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) { | |
| // Search for tied operands, so that we can correctly instantiate | |
| // operands that are not explicitly represented in the encoding. | |
| std::map<StringRef, StringRef> TiedNames; | |
| for (const auto &Op : Inst->Operands) { | |
| for (const auto &[J, CI] : enumerate(Op.Constraints)) { | |
| if (!CI.isTied()) | |
| continue; | |
| std::pair<unsigned, unsigned> SO = | |
| Inst->Operands.getSubOperandNumber(CI.getTiedOperand()); | |
| StringRef TiedName = Inst->Operands[SO.first].SubOpNames[SO.second]; | |
| if (TiedName.empty()) | |
| TiedName = Inst->Operands[SO.first].Name; | |
| StringRef MyName = Op.SubOpNames[J]; | |
| if (MyName.empty()) | |
| MyName = Op.Name; | |
| TiedNames[MyName] = TiedName; | |
| TiedNames[TiedName] = MyName; | |
| } | |
| } | |
| // For each operand, see if we can figure out where it is encoded. | |
| for (const CGIOperandList::OperandInfo &Op : Inst->Operands) { | |
| // Lookup the decoder method and construct a new OperandInfo to hold our | |
| // result. | |
| OperandInfo OpInfo = getOpInfo(Op.Rec); | |
| // If we have named sub-operands... | |
| if (Op.MIOperandInfo && !Op.SubOpNames[0].empty()) { | |
| // Then there should not be a custom decoder specified on the top-level | |
| // type. | |
| if (!OpInfo.Decoder.empty()) { | |
| PrintError(EncodingDef, | |
| "DecoderEmitter: operand \"" + Op.Name + "\" has type \"" + | |
| Op.Rec->getName() + | |
| "\" with a custom DecoderMethod, but also named " | |
| "sub-operands."); | |
| continue; | |
| } | |
| // Decode each of the sub-ops separately. | |
| for (auto [SubOpName, SubOp] : | |
| zip_equal(Op.SubOpNames, Op.MIOperandInfo->getArgs())) { | |
| const Record *SubOpRec = cast<DefInit>(SubOp)->getDef(); | |
| OperandInfo SubOpInfo = getOpInfo(SubOpRec); | |
| addOneOperandFields(EncodingDef, Bits, TiedNames, SubOpRec, SubOpName, | |
| SubOpInfo); | |
| Operands.push_back(std::move(SubOpInfo)); | |
| } | |
| continue; | |
| } | |
| // Otherwise, if we have an operand with sub-operands, but they aren't | |
| // named... | |
| if (Op.MIOperandInfo && OpInfo.Decoder.empty()) { | |
| // If we have sub-ops, we'd better have a custom decoder. | |
| // (Otherwise we don't know how to populate them properly...) | |
| if (Op.MIOperandInfo->getNumArgs()) { | |
| PrintError(EncodingDef, | |
| "DecoderEmitter: operand \"" + Op.Name + | |
| "\" has non-empty MIOperandInfo, but doesn't " | |
| "have a custom decoder!"); | |
| debugDumpRecord(*EncodingDef); | |
| continue; | |
| } | |
| } | |
| addOneOperandFields(EncodingDef, Bits, TiedNames, Op.Rec, Op.Name, OpInfo); | |
| Operands.push_back(std::move(OpInfo)); | |
| } | |
| } | |
| InstructionEncoding::InstructionEncoding(const Record *EncodingDef, | |
| const CodeGenInstruction *Inst) | |
| : EncodingDef(EncodingDef), Inst(Inst) { | |
| const Record *InstDef = Inst->TheDef; | |
| // Give this encoding a name. | |
| if (EncodingDef != InstDef) | |
| Name = (EncodingDef->getName() + Twine(':')).str(); | |
| Name.append(InstDef->getName()); | |
| DecoderNamespace = EncodingDef->getValueAsString("DecoderNamespace"); | |
| DecoderMethod = EncodingDef->getValueAsString("DecoderMethod"); | |
| if (!DecoderMethod.empty()) | |
| HasCompleteDecoder = EncodingDef->getValueAsBit("hasCompleteDecoder"); | |
| const RecordVal *InstField = EncodingDef->getValue("Inst"); | |
| if (const auto *DI = dyn_cast<DagInit>(InstField->getValue())) { | |
| VarLenInst VLI(DI, InstField); | |
| parseVarLenEncoding(VLI); | |
| // If the encoding has a custom decoder, don't bother parsing the operands. | |
| if (DecoderMethod.empty()) | |
| parseVarLenOperands(VLI); | |
| } else { | |
| const auto *BI = cast<BitsInit>(InstField->getValue()); | |
| parseFixedLenEncoding(*BI); | |
| // If the encoding has a custom decoder, don't bother parsing the operands. | |
| if (DecoderMethod.empty()) | |
| parseFixedLenOperands(*BI); | |
| } | |
| if (DecoderMethod.empty()) { | |
| // A generated decoder is always successful if none of the operand | |
| // decoders can fail (all are always successful). | |
| HasCompleteDecoder = all_of(Operands, [](const OperandInfo &Op) { | |
| // By default, a generated operand decoder is assumed to always succeed. | |
| // This can be overridden by the user. | |
| return Op.Decoder.empty() || Op.HasCompleteDecoder; | |
| }); | |
| } | |
| } |