aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/CodeEmitterGen.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/utils/TableGen/CodeEmitterGen.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
downloadsrc-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.cpp126
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";