| //===--------------------- 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 |