diff options
Diffstat (limited to 'utils/TableGen/PredicateExpander.cpp')
| -rw-r--r-- | utils/TableGen/PredicateExpander.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/utils/TableGen/PredicateExpander.cpp b/utils/TableGen/PredicateExpander.cpp new file mode 100644 index 000000000000..68eb32794a02 --- /dev/null +++ b/utils/TableGen/PredicateExpander.cpp @@ -0,0 +1,262 @@ +//===--------------------- PredicateExpander.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// Functionalities used by the Tablegen backends to expand machine predicates. +// +//===----------------------------------------------------------------------===// + +#include "PredicateExpander.h" + +namespace llvm { + +void PredicateExpander::expandTrue(formatted_raw_ostream &OS) { OS << "true"; } +void PredicateExpander::expandFalse(formatted_raw_ostream &OS) { + OS << "false"; +} + +void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS, + int OpIndex, int ImmVal) { + OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex + << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal; +} + +void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS, + int OpIndex, StringRef ImmVal) { + OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex + << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal; +} + +void PredicateExpander::expandCheckRegOperand(formatted_raw_ostream &OS, + int OpIndex, const Record *Reg) { + assert(Reg->isSubClassOf("Register") && "Expected a register Record!"); + + OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex + << ").getReg() " << (shouldNegate() ? "!= " : "== "); + const StringRef Str = Reg->getValueAsString("Namespace"); + if (!Str.empty()) + OS << Str << "::"; + OS << Reg->getName(); +} + +void PredicateExpander::expandCheckInvalidRegOperand(formatted_raw_ostream &OS, + int OpIndex) { + OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex + << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0"; +} + +void PredicateExpander::expandCheckSameRegOperand(formatted_raw_ostream &OS, + int First, int Second) { + OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First + << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI" + << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()"; +} + +void PredicateExpander::expandCheckNumOperands(formatted_raw_ostream &OS, + int NumOps) { + OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() " + << (shouldNegate() ? "!= " : "== ") << NumOps; +} + +void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS, + const Record *Inst) { + OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() " + << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace") + << "::" << Inst->getName(); +} + +void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS, + const RecVec &Opcodes) { + assert(!Opcodes.empty() && "Expected at least one opcode to check!"); + bool First = true; + + if (Opcodes.size() == 1) { + OS << "( "; + expandCheckOpcode(OS, Opcodes[0]); + OS << " )"; + return; + } + + OS << '('; + increaseIndentLevel(); + for (const Record *Rec : Opcodes) { + OS << '\n'; + OS.PadToColumn(getIndentLevel() * 2); + if (!First) + OS << (shouldNegate() ? "&& " : "|| "); + + expandCheckOpcode(OS, Rec); + First = false; + } + + OS << '\n'; + decreaseIndentLevel(); + OS.PadToColumn(getIndentLevel() * 2); + OS << ')'; +} + +void PredicateExpander::expandCheckPseudo(formatted_raw_ostream &OS, + const RecVec &Opcodes) { + if (shouldExpandForMC()) + expandFalse(OS); + else + expandCheckOpcode(OS, Opcodes); +} + +void PredicateExpander::expandPredicateSequence(formatted_raw_ostream &OS, + const RecVec &Sequence, + bool IsCheckAll) { + assert(!Sequence.empty() && "Found an invalid empty predicate set!"); + if (Sequence.size() == 1) + return expandPredicate(OS, Sequence[0]); + + // Okay, there is more than one predicate in the set. + bool First = true; + OS << (shouldNegate() ? "!(" : "("); + increaseIndentLevel(); + + bool OldValue = shouldNegate(); + setNegatePredicate(false); + for (const Record *Rec : Sequence) { + OS << '\n'; + OS.PadToColumn(getIndentLevel() * 2); + if (!First) + OS << (IsCheckAll ? "&& " : "|| "); + expandPredicate(OS, Rec); + First = false; + } + OS << '\n'; + decreaseIndentLevel(); + OS.PadToColumn(getIndentLevel() * 2); + OS << ')'; + setNegatePredicate(OldValue); +} + +void PredicateExpander::expandTIIFunctionCall(formatted_raw_ostream &OS, + StringRef TargetName, + StringRef MethodName) { + OS << (shouldNegate() ? "!" : ""); + if (shouldExpandForMC()) + OS << TargetName << "_MC::"; + else + OS << TargetName << "Gen" + << "InstrInfo::"; + OS << MethodName << (isByRef() ? "(MI)" : "(*MI)"); +} + +void PredicateExpander::expandCheckIsRegOperand(formatted_raw_ostream &OS, + int OpIndex) { + OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->") + << "getOperand(" << OpIndex << ").isReg() "; +} + +void PredicateExpander::expandCheckIsImmOperand(formatted_raw_ostream &OS, + int OpIndex) { + OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->") + << "getOperand(" << OpIndex << ").isImm() "; +} + +void PredicateExpander::expandCheckFunctionPredicate(formatted_raw_ostream &OS, + StringRef MCInstFn, + StringRef MachineInstrFn) { + OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn) + << (isByRef() ? "(MI)" : "(*MI)"); +} + +void PredicateExpander::expandCheckNonPortable(formatted_raw_ostream &OS, + StringRef Code) { + if (shouldExpandForMC()) + return expandFalse(OS); + + OS << '(' << Code << ')'; +} + +void PredicateExpander::expandPredicate(formatted_raw_ostream &OS, + const Record *Rec) { + OS.flush(); + unsigned ColNum = getIndentLevel() * 2; + if (OS.getColumn() < ColNum) + OS.PadToColumn(ColNum); + + if (Rec->isSubClassOf("MCTrue")) { + if (shouldNegate()) + return expandFalse(OS); + return expandTrue(OS); + } + + if (Rec->isSubClassOf("MCFalse")) { + if (shouldNegate()) + return expandTrue(OS); + return expandFalse(OS); + } + + if (Rec->isSubClassOf("CheckNot")) { + flipNegatePredicate(); + expandPredicate(OS, Rec->getValueAsDef("Pred")); + flipNegatePredicate(); + return; + } + + if (Rec->isSubClassOf("CheckIsRegOperand")) + return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex")); + + if (Rec->isSubClassOf("CheckIsImmOperand")) + return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex")); + + if (Rec->isSubClassOf("CheckRegOperand")) + return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"), + Rec->getValueAsDef("Reg")); + + if (Rec->isSubClassOf("CheckInvalidRegOperand")) + return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex")); + + if (Rec->isSubClassOf("CheckImmOperand")) + return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"), + Rec->getValueAsInt("ImmVal")); + + if (Rec->isSubClassOf("CheckImmOperand_s")) + return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"), + Rec->getValueAsString("ImmVal")); + + if (Rec->isSubClassOf("CheckSameRegOperand")) + return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"), + Rec->getValueAsInt("SecondIndex")); + + if (Rec->isSubClassOf("CheckNumOperands")) + return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps")); + + if (Rec->isSubClassOf("CheckPseudo")) + return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes")); + + if (Rec->isSubClassOf("CheckOpcode")) + return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes")); + + if (Rec->isSubClassOf("CheckAll")) + return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"), + /* AllOf */ true); + + if (Rec->isSubClassOf("CheckAny")) + return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"), + /* AllOf */ false); + + if (Rec->isSubClassOf("CheckFunctionPredicate")) + return expandCheckFunctionPredicate( + OS, Rec->getValueAsString("MCInstFnName"), + Rec->getValueAsString("MachineInstrFnName")); + + if (Rec->isSubClassOf("CheckNonPortable")) + return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock")); + + if (Rec->isSubClassOf("TIIPredicate")) + return expandTIIFunctionCall(OS, Rec->getValueAsString("TargetName"), + Rec->getValueAsString("FunctionName")); + + llvm_unreachable("No known rules to expand this MCInstPredicate"); +} + +} // namespace llvm |
