mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-09 03:01:17 +00:00

This patch introduces tablegen class MCStatement. Currently, an MCStatement can be either a return statement, or a switch statement. ``` MCStatement: MCReturnStatement MCOpcodeSwitchStatement ``` A MCReturnStatement expands to a return statement, and the boolean expression associated with the return statement is described by a MCInstPredicate. An MCOpcodeSwitchStatement is a switch statement where the condition is a check on the machine opcode. It allows the definition of multiple checks, as well as a default case. More details on the grammar implemented by these two new constructs can be found in the diff for TargetInstrPredicates.td. This patch makes it easier to read the body of auto-generated TargetInstrInfo predicates. In future, I plan to reuse/extend the MCStatement grammar to describe more complex target hooks. For now, this is just a first step (mostly a minor cosmetic change to polish the new predicates framework). Differential Revision: https://reviews.llvm.org/D50457 llvm-svn: 339352
329 lines
11 KiB
C++
329 lines
11 KiB
C++
//===--------------------- 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::expandReturnStatement(formatted_raw_ostream &OS,
|
|
const Record *Rec) {
|
|
OS << "return ";
|
|
expandPredicate(OS, Rec);
|
|
OS << ";";
|
|
}
|
|
|
|
void PredicateExpander::expandOpcodeSwitchCase(formatted_raw_ostream &OS,
|
|
const Record *Rec) {
|
|
const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
|
|
for (const Record *Opcode : Opcodes) {
|
|
OS.PadToColumn(getIndentLevel() * 2);
|
|
OS << "case " << Opcode->getValueAsString("Namespace")
|
|
<< "::" << Opcode->getName() << " :\n";
|
|
}
|
|
|
|
increaseIndentLevel();
|
|
expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
|
|
decreaseIndentLevel();
|
|
}
|
|
|
|
void PredicateExpander::expandOpcodeSwitchStatement(formatted_raw_ostream &OS,
|
|
const RecVec &Cases,
|
|
const Record *Default) {
|
|
OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
|
|
|
|
for (const Record *Rec : Cases) {
|
|
expandOpcodeSwitchCase(OS, Rec);
|
|
OS << '\n';
|
|
}
|
|
|
|
unsigned ColNum = getIndentLevel() * 2;
|
|
OS.PadToColumn(ColNum);
|
|
|
|
// Expand the default case.
|
|
OS << "default :\n";
|
|
increaseIndentLevel();
|
|
expandStatement(OS, Default);
|
|
decreaseIndentLevel();
|
|
OS << '\n';
|
|
|
|
OS.PadToColumn(ColNum);
|
|
OS << "} // end of switch-stmt";
|
|
}
|
|
|
|
void PredicateExpander::expandStatement(formatted_raw_ostream &OS,
|
|
const Record *Rec) {
|
|
OS.flush();
|
|
unsigned ColNum = getIndentLevel() * 2;
|
|
if (OS.getColumn() < ColNum)
|
|
OS.PadToColumn(ColNum);
|
|
|
|
if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
|
|
expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
|
|
Rec->getValueAsDef("DefaultCase"));
|
|
return;
|
|
}
|
|
|
|
if (Rec->isSubClassOf("MCReturnStatement")) {
|
|
expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
|
|
return;
|
|
}
|
|
|
|
llvm_unreachable("No known rules to expand this MCStatement");
|
|
}
|
|
|
|
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
|