diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/utils/TableGen/CodeEmitterGen.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) | |
download | src-e3b557809604d036af6e00c60f012c2025b59a5e.tar.gz src-e3b557809604d036af6e00c60f012c2025b59a5e.zip |
Vendor import of llvm-project main llvmorg-16-init-18548-gb0daacf58f41,vendor/llvm-project/llvmorg-16-init-18548-gb0daacf58f41
the last commit before the upstream release/17.x branch was created.
Diffstat (limited to 'llvm/utils/TableGen/CodeEmitterGen.cpp')
-rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 126 |
1 files changed, 82 insertions, 44 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 1d00c3cfd069..dc4fd589eaa8 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -25,7 +25,6 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include <cassert> #include <cstdint> #include <map> #include <set> @@ -50,9 +49,8 @@ private: std::string getInstructionCase(Record *R, CodeGenTarget &Target); std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef, CodeGenTarget &Target); - void AddCodeToMergeInOperand(Record *R, BitsInit *BI, - const std::string &VarName, - unsigned &NumberedOp, + bool addCodeToMergeInOperand(Record *R, BitsInit *BI, + const std::string &VarName, unsigned &NumberedOp, std::set<unsigned> &NamedOpIndices, std::string &Case, CodeGenTarget &Target); @@ -79,11 +77,13 @@ int CodeEmitterGen::getVariableBit(const std::string &VarName, return -1; } -void CodeEmitterGen:: -AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, - unsigned &NumberedOp, - std::set<unsigned> &NamedOpIndices, - std::string &Case, CodeGenTarget &Target) { +// Returns true if it succeeds, false if an error. +bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI, + const std::string &VarName, + unsigned &NumberedOp, + std::set<unsigned> &NamedOpIndices, + std::string &Case, + CodeGenTarget &Target) { CodeGenInstruction &CGI = Target.getInstruction(R); // Determine if VarName actually contributes to the Inst encoding. @@ -99,18 +99,27 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, // If we found no bits, ignore this value, otherwise emit the call to get the // operand encoding. - if (bit < 0) return; - + if (bit < 0) + return true; + // If the operand matches by name, reference according to that // operand number. Non-matching operands are assumed to be in // order. unsigned OpIdx; - if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) { + std::pair<unsigned, unsigned> SubOp; + if (CGI.Operands.hasSubOperandAlias(VarName, SubOp)) { + OpIdx = CGI.Operands[SubOp.first].MIOperandNo + SubOp.second; + } else if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) { // Get the machine operand number for the indicated operand. OpIdx = CGI.Operands[OpIdx].MIOperandNo; - assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) && - "Explicitly used operand also marked as not emitted!"); } else { + // Fall back to positional lookup. By default, we now disable positional + // lookup (and print an error, below), but even so, we'll do the lookup to + // help print a helpful diagnostic message. + // + // TODO: When we remove useDeprecatedPositionallyEncodedOperands, delete all + // this code, just leaving a "no operand named X in record Y" error. + unsigned NumberOps = CGI.Operands.size(); /// If this operand is not supposed to be emitted by the /// generated emitter, skip it. @@ -123,41 +132,59 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, if (NumberedOp >= CGI.Operands.back().MIOperandNo + CGI.Operands.back().MINumOperands) { - std::string E; - raw_string_ostream S(E); - S << "Too few operands in record " << R->getName() - << " (no match for variable " << VarName << "):\n"; - S << *R; - PrintFatalError(R, E); + if (!Target.getInstructionSet()->getValueAsBit( + "useDeprecatedPositionallyEncodedOperands")) { + PrintError(R, Twine("No operand named ") + VarName + " in record " + + R->getName() + + " (would've given 'too few operands' error with " + "useDeprecatedPositionallyEncodedOperands=true)"); + } else { + PrintError(R, "Too few operands in record " + R->getName() + + " (no match for variable " + VarName + ")"); + } + return false; } OpIdx = NumberedOp++; + + if (!Target.getInstructionSet()->getValueAsBit( + "useDeprecatedPositionallyEncodedOperands")) { + std::pair<unsigned, unsigned> SO = + CGI.Operands.getSubOperandNumber(OpIdx); + std::string OpName = CGI.Operands[SO.first].Name; + PrintError(R, Twine("No operand named ") + VarName + " in record " + + R->getName() + " (would've used positional operand #" + + Twine(SO.first) + " ('" + OpName + "') sub-op #" + + Twine(SO.second) + + " with useDeprecatedPositionallyEncodedOperands=true)"); + return false; + } } - + + if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) { + PrintError(R, "Operand " + VarName + " used but also marked as not emitted!"); + return false; + } + std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx); - std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName; + std::string &EncoderMethodName = + CGI.Operands[SO.first].EncoderMethodNames[SO.second]; if (UseAPInt) Case += " op.clearAllBits();\n"; - // If the source operand has a custom encoder, use it. This will - // get the encoding for all of the suboperands. + Case += " // op: " + VarName + "\n"; + + // If the source operand has a custom encoder, use it. if (!EncoderMethodName.empty()) { - // A custom encoder has all of the information for the - // sub-operands, if there are more than one, so only - // query the encoder once per source operand. - if (SO.second == 0) { - Case += " // op: " + VarName + "\n"; - if (UseAPInt) { - Case += " " + EncoderMethodName + "(MI, " + utostr(OpIdx); - Case += ", op"; - } else { - Case += " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); - } - Case += ", Fixups, STI);\n"; + if (UseAPInt) { + Case += " " + EncoderMethodName + "(MI, " + utostr(OpIdx); + Case += ", op"; + } else { + Case += " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); } + Case += ", Fixups, STI);\n"; } else { - Case += " // op: " + VarName + "\n"; if (UseAPInt) { Case += " getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; Case += ", op, Fixups, STI"; @@ -263,6 +290,7 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, } } } + return true; } std::string CodeEmitterGen::getInstructionCase(Record *R, @@ -310,14 +338,25 @@ std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *Enc // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. + bool Success = true; for (const RecordVal &RV : EncodingDef->getValues()) { // Ignore fixed fields in the record, we're looking for values like: // bits<5> RST = { ?, ?, ?, ?, ? }; if (RV.isNonconcreteOK() || RV.getValue()->isComplete()) continue; - AddCodeToMergeInOperand(R, BI, std::string(RV.getName()), NumberedOp, - NamedOpIndices, Case, Target); + Success &= + addCodeToMergeInOperand(R, BI, std::string(RV.getName()), NumberedOp, + NamedOpIndices, Case, Target); + } + + if (!Success) { + // Dump the record, so we can see what's going on... + std::string E; + raw_string_ostream S(E); + S << "Dumping record for previous error:\n"; + S << *R; + PrintNote(E); } StringRef PostEmitter = R->getValueAsString("PostEncoderMethod"); @@ -370,8 +409,8 @@ void CodeEmitterGen::emitInstructionBaseValues( // Start by filling in fixed values. APInt Value(BitWidth, 0); for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { - if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e - i - 1))) - Value |= APInt(BitWidth, (uint64_t)B->getValue()) << (e - i - 1); + if (auto *B = dyn_cast<BitInit>(BI->getBit(i)); B && B->getValue()) + Value.setBit(i); } o << " "; emitInstBits(o, Value); @@ -478,9 +517,8 @@ void CodeEmitterGen::run(raw_ostream &o) { o << " const unsigned opcode = MI.getOpcode();\n" << " if (Scratch.getBitWidth() != " << BitWidth << ")\n" << " Scratch = Scratch.zext(" << BitWidth << ");\n" - << " Inst = APInt(" << BitWidth - << ", makeArrayRef(InstBits + opcode * " << NumWords << ", " << NumWords - << "));\n" + << " Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + opcode * " + << NumWords << ", " << NumWords << "));\n" << " APInt &Value = Inst;\n" << " APInt &op = Scratch;\n" << " switch (opcode) {\n"; |