aboutsummaryrefslogtreecommitdiffstats
path: root/utils/TableGen/CodeGenTarget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/CodeGenTarget.cpp')
-rw-r--r--utils/TableGen/CodeGenTarget.cpp114
1 files changed, 68 insertions, 46 deletions
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index dd17059..dd9c23c 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -143,6 +143,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
}
CodeGenTarget::~CodeGenTarget() {
+ DeleteContainerSeconds(Instructions);
delete RegBank;
delete SchedModels;
}
@@ -172,7 +173,8 @@ Record *CodeGenTarget::getInstructionSet() const {
Record *CodeGenTarget::getAsmParser() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
if (AsmParserNum >= LI.size())
- PrintFatalError("Target does not have an AsmParser #" + utostr(AsmParserNum) + "!");
+ PrintFatalError("Target does not have an AsmParser #" +
+ Twine(AsmParserNum) + "!");
return LI[AsmParserNum];
}
@@ -183,7 +185,8 @@ Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
std::vector<Record*> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
if (i >= LI.size())
- PrintFatalError("Target does not have an AsmParserVariant #" + utostr(i) + "!");
+ PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
+ "!");
return LI[i];
}
@@ -201,7 +204,8 @@ unsigned CodeGenTarget::getAsmParserVariantCount() const {
Record *CodeGenTarget::getAsmWriter() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
if (AsmWriterNum >= LI.size())
- PrintFatalError("Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!");
+ PrintFatalError("Target does not have an AsmWriter #" +
+ Twine(AsmWriterNum) + "!");
return LI[AsmWriterNum];
}
@@ -284,47 +288,20 @@ GetInstByName(const char *Name,
DenseMap<const Record*, CodeGenInstruction*>::const_iterator
I = Insts.find(Rec);
if (Rec == 0 || I == Insts.end())
- PrintFatalError(std::string("Could not find '") + Name + "' instruction!");
+ PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
return I->second;
}
-namespace {
-/// SortInstByName - Sorting predicate to sort instructions by name.
-///
-struct SortInstByName {
- bool operator()(const CodeGenInstruction *Rec1,
- const CodeGenInstruction *Rec2) const {
- return Rec1->TheDef->getName() < Rec2->TheDef->getName();
- }
-};
-}
-
-/// getInstructionsByEnumValue - Return all of the instructions defined by the
-/// target, ordered by their enum value.
+/// \brief Return all of the instructions defined by the target, ordered by
+/// their enum value.
void CodeGenTarget::ComputeInstrsByEnum() const {
// The ordering here must match the ordering in TargetOpcodes.h.
static const char *const FixedInstrs[] = {
- "PHI",
- "INLINEASM",
- "PROLOG_LABEL",
- "EH_LABEL",
- "GC_LABEL",
- "KILL",
- "EXTRACT_SUBREG",
- "INSERT_SUBREG",
- "IMPLICIT_DEF",
- "SUBREG_TO_REG",
- "COPY_TO_REGCLASS",
- "DBG_VALUE",
- "REG_SEQUENCE",
- "COPY",
- "BUNDLE",
- "LIFETIME_START",
- "LIFETIME_END",
- "STACKMAP",
- "PATCHPOINT",
- 0
- };
+ "PHI", "INLINEASM", "CFI_INSTRUCTION", "EH_LABEL",
+ "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG",
+ "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE",
+ "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START",
+ "LIFETIME_END", "STACKMAP", "PATCHPOINT", 0};
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
for (const char *const *p = FixedInstrs; *p; ++p) {
const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
@@ -345,8 +322,10 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
// All of the instructions are now in random order based on the map iteration.
// Sort them by name.
- std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(),
- SortInstByName());
+ std::sort(InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
+ [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
+ return Rec1->TheDef->getName() < Rec2->TheDef->getName();
+ });
}
@@ -357,6 +336,46 @@ bool CodeGenTarget::isLittleEndianEncoding() const {
return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
}
+/// 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 (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
+ I != E; ++I) {
+ Record *R = *I;
+ 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);
+ }
+}
+
/// guessInstructionProperties - Return true if it's OK to guess instruction
/// properties instead of raising an error.
///
@@ -430,6 +449,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isCommutative = false;
canThrow = false;
isNoReturn = false;
+ isNoDuplicate = false;
if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
@@ -481,14 +501,14 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// It only makes sense to use the extended and truncated vector element
// variants with iAny types; otherwise, if the intrinsic is not
// overloaded, all the types can be specified directly.
- assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
- !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedType")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else {
VT = getValueType(TyEl->getValueAsDef("VT"));
}
- if (EVT(VT).isOverloaded()) {
+ if (MVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
isOverloaded = true;
}
@@ -515,14 +535,14 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// It only makes sense to use the extended and truncated vector element
// variants with iAny types; otherwise, if the intrinsic is not
// overloaded, all the types can be specified directly.
- assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
- !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedType")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else
VT = getValueType(TyEl->getValueAsDef("VT"));
- if (EVT(VT).isOverloaded()) {
+ if (MVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
isOverloaded = true;
}
@@ -554,6 +574,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isCommutative = true;
else if (Property->getName() == "Throws")
canThrow = true;
+ else if (Property->getName() == "IntrNoDuplicate")
+ isNoDuplicate = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
else if (Property->isSubClassOf("NoCapture")) {