| //===----------------------------------------------------------------------===// |
| // |
| // 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].addField(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].addField(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.addField(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; |
| }); |
| } |
| } |