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