diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
| commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
| tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /utils/TableGen/CodeGenTarget.cpp | |
| parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
Notes
Diffstat (limited to 'utils/TableGen/CodeGenTarget.cpp')
| -rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 122 | 
1 files changed, 73 insertions, 49 deletions
| diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index dd1705955824..d1b57118e0ee 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -133,7 +133,7 @@ std::string llvm::getQualifiedName(const Record *R) {  /// getTarget - Return the current instance of the Target class.  ///  CodeGenTarget::CodeGenTarget(RecordKeeper &records) -  : Records(records), RegBank(0), SchedModels(0) { +  : Records(records), RegBank(nullptr), SchedModels(nullptr) {    std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");    if (Targets.size() == 0)      PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -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];  } @@ -222,7 +226,7 @@ const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {    const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName();    StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name);    if (I == Regs.end()) -    return 0; +    return nullptr;    return I->second;  } @@ -283,48 +287,21 @@ 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!"); +  if (!Rec || I == Insts.end()) +    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",       nullptr};    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_") @@ -439,6 +459,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {    if (R->getValue("GCCBuiltinName"))  // Ignore a missing GCCBuiltinName field.      GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); +  if (R->getValue("MSBuiltinName"))   // Ignore a missing MSBuiltinName field. +    MSBuiltinName = R->getValueAsString("MSBuiltinName");    TargetPrefix = R->getValueAsString("TargetPrefix");    Name = R->getValueAsString("LLVMName"); @@ -481,14 +503,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 +537,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 +576,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")) { | 
