mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-19 02:25:01 +00:00
Continued evolution of the selector emitter: Represent instruction patterns
as first class objects git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7677 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -93,12 +93,60 @@ static MVT::ValueType getIntrinsicType(Record *R) {
|
|||||||
|
|
||||||
// Parse the specified DagInit into a TreePattern which we can use.
|
// Parse the specified DagInit into a TreePattern which we can use.
|
||||||
//
|
//
|
||||||
TreePatternNode *InstrSelectorEmitter::ParseTreePattern(DagInit *DI,
|
Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||||
const std::string &RecName) {
|
InstrSelectorEmitter &ise)
|
||||||
|
: PTy(pty), TheRecord(TheRec), ISE(ise) {
|
||||||
|
|
||||||
|
// First, parse the pattern...
|
||||||
|
Tree = ParseTreePattern(RawPat);
|
||||||
|
|
||||||
|
bool MadeChange, AnyUnset;
|
||||||
|
do {
|
||||||
|
MadeChange = false;
|
||||||
|
AnyUnset = InferTypes(Tree, MadeChange);
|
||||||
|
} while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
|
||||||
|
|
||||||
|
if (PTy == Instruction) {
|
||||||
|
// Check to make sure there is not any unset types in the tree pattern...
|
||||||
|
if (AnyUnset) {
|
||||||
|
std::cerr << "In instruction pattern: " << *Tree << "\n";
|
||||||
|
error("Could not infer all types!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if we have a top-level (set) of a register.
|
||||||
|
if (Tree->getOperator()->getName() == "set") {
|
||||||
|
assert(Tree->getChildren().size() == 2 && "Set with != 2 arguments?");
|
||||||
|
if (!Tree->getChild(0)->isLeaf())
|
||||||
|
error("Arg #0 of set should be a register or register class!");
|
||||||
|
DefInit *RegInit = dynamic_cast<DefInit*>(Tree->getChild(0)->getValue());
|
||||||
|
if (RegInit == 0)
|
||||||
|
error("LHS of 'set' expected to be a register or register class!");
|
||||||
|
|
||||||
|
Result = RegInit->getDef();
|
||||||
|
Tree = Tree->getChild(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resolved = !AnyUnset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pattern::error(const std::string &Msg) {
|
||||||
|
std::string M = "In ";
|
||||||
|
switch (PTy) {
|
||||||
|
case Nonterminal: M += "nonterminal "; break;
|
||||||
|
case Instruction: M += "instruction "; break;
|
||||||
|
case Expander : M += "expander "; break;
|
||||||
|
}
|
||||||
|
throw M + TheRecord->getName() + ": " + Msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TreePatternNode *Pattern::ParseTreePattern(DagInit *DI) {
|
||||||
Record *Operator = DI->getNodeType();
|
Record *Operator = DI->getNodeType();
|
||||||
|
|
||||||
if (!NodeTypes.count(Operator))
|
if (!ISE.getNodeTypes().count(Operator))
|
||||||
throw "Illegal node for instruction pattern: '" + Operator->getName() +"'!";
|
error("Unrecognized node '" + Operator->getName() + "'!");
|
||||||
|
|
||||||
const std::vector<Init*> &Args = DI->getArgs();
|
const std::vector<Init*> &Args = DI->getArgs();
|
||||||
std::vector<TreePatternNode*> Children;
|
std::vector<TreePatternNode*> Children;
|
||||||
@@ -106,14 +154,14 @@ TreePatternNode *InstrSelectorEmitter::ParseTreePattern(DagInit *DI,
|
|||||||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||||
Init *Arg = Args[i];
|
Init *Arg = Args[i];
|
||||||
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
||||||
Children.push_back(ParseTreePattern(DI, RecName));
|
Children.push_back(ParseTreePattern(DI));
|
||||||
} else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
} else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
||||||
Children.push_back(new TreePatternNode(DI));
|
Children.push_back(new TreePatternNode(DI));
|
||||||
// If it's a regclass or something else known, set the type.
|
// If it's a regclass or something else known, set the type.
|
||||||
Children.back()->setType(getIntrinsicType(DI->getDef()));
|
Children.back()->setType(getIntrinsicType(DI->getDef()));
|
||||||
} else {
|
} else {
|
||||||
Arg->dump();
|
Arg->dump();
|
||||||
throw "Unknown value for tree pattern in '" + RecName + "'!";
|
error("Unknown leaf value for tree pattern!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,37 +186,36 @@ static bool UpdateNodeType(TreePatternNode *N, MVT::ValueType VT,
|
|||||||
// InferTypes - Perform type inference on the tree, returning true if there
|
// InferTypes - Perform type inference on the tree, returning true if there
|
||||||
// are any remaining untyped nodes and setting MadeChange if any changes were
|
// are any remaining untyped nodes and setting MadeChange if any changes were
|
||||||
// made.
|
// made.
|
||||||
bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||||
const std::string &RecName,
|
|
||||||
bool &MadeChange) {
|
|
||||||
if (N->isLeaf()) return N->getType() == MVT::Other;
|
if (N->isLeaf()) return N->getType() == MVT::Other;
|
||||||
|
|
||||||
bool AnyUnset = false;
|
bool AnyUnset = false;
|
||||||
Record *Operator = N->getOperator();
|
Record *Operator = N->getOperator();
|
||||||
assert(NodeTypes.count(Operator) && "No node info for node!");
|
assert(ISE.getNodeTypes().count(Operator) && "No node info for node!");
|
||||||
const NodeType &NT = NodeTypes[Operator];
|
const NodeType &NT = ISE.getNodeTypes()[Operator];
|
||||||
|
|
||||||
// Check to see if we can infer anything about the argument types from the
|
// Check to see if we can infer anything about the argument types from the
|
||||||
// return types...
|
// return types...
|
||||||
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
||||||
if (Children.size() != NT.ArgTypes.size())
|
if (Children.size() != NT.ArgTypes.size())
|
||||||
throw "In record " + RecName + " incorrect number of children for " +
|
error("Incorrect number of children for " + Operator->getName() + " node!");
|
||||||
Operator->getName() + " node!";
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
||||||
AnyUnset |= InferTypes(Children[i], RecName, MadeChange);
|
AnyUnset |= InferTypes(Children[i], MadeChange);
|
||||||
|
|
||||||
|
|
||||||
switch (NT.ArgTypes[i]) {
|
switch (NT.ArgTypes[i]) {
|
||||||
case NodeType::Arg0:
|
case NodeType::Arg0:
|
||||||
MadeChange |= UpdateNodeType(Children[i], Children[0]->getType(),RecName);
|
MadeChange |= UpdateNodeType(Children[i], Children[0]->getType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Val:
|
case NodeType::Val:
|
||||||
if (Children[i]->getType() == MVT::isVoid)
|
if (Children[i]->getType() == MVT::isVoid)
|
||||||
throw "In pattern for " + RecName + " should not get a void node!";
|
error("Inferred a void node in an illegal place!");
|
||||||
break;
|
break;
|
||||||
case NodeType::Ptr:
|
case NodeType::Ptr:
|
||||||
MadeChange |= UpdateNodeType(Children[i],Target.getPointerType(),RecName);
|
MadeChange |= UpdateNodeType(Children[i],
|
||||||
|
ISE.getTarget().getPointerType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
default: assert(0 && "Invalid argument ArgType!");
|
default: assert(0 && "Invalid argument ArgType!");
|
||||||
}
|
}
|
||||||
@@ -177,18 +224,20 @@ bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
|||||||
// See if we can infer anything about the return type now...
|
// See if we can infer anything about the return type now...
|
||||||
switch (NT.ResultType) {
|
switch (NT.ResultType) {
|
||||||
case NodeType::Void:
|
case NodeType::Void:
|
||||||
MadeChange |= UpdateNodeType(N, MVT::isVoid, RecName);
|
MadeChange |= UpdateNodeType(N, MVT::isVoid, TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Arg0:
|
case NodeType::Arg0:
|
||||||
MadeChange |= UpdateNodeType(N, Children[0]->getType(), RecName);
|
MadeChange |= UpdateNodeType(N, Children[0]->getType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeType::Ptr:
|
case NodeType::Ptr:
|
||||||
MadeChange |= UpdateNodeType(N, Target.getPointerType(), RecName);
|
MadeChange |= UpdateNodeType(N, ISE.getTarget().getPointerType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Val:
|
case NodeType::Val:
|
||||||
if (N->getType() == MVT::isVoid)
|
if (N->getType() == MVT::isVoid)
|
||||||
throw "In pattern for " + RecName + " should not get a void node!";
|
error("Inferred a void node in an illegal place!");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0 && "Unhandled type constraint!");
|
assert(0 && "Unhandled type constraint!");
|
||||||
@@ -198,39 +247,36 @@ bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
|||||||
return AnyUnset | N->getType() == MVT::Other;
|
return AnyUnset | N->getType() == MVT::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
||||||
|
switch (P.getPatternType()) {
|
||||||
|
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
||||||
|
case Pattern::Instruction: OS << "Instruction pattern "; break;
|
||||||
|
case Pattern::Expander: OS << "Expander pattern "; break;
|
||||||
|
}
|
||||||
|
|
||||||
// ReadAndCheckPattern - Parse the specified DagInit into a pattern and then
|
OS << P.getRecord()->getName() << ":\t";
|
||||||
// perform full type inference.
|
|
||||||
//
|
|
||||||
TreePatternNode *InstrSelectorEmitter::ReadAndCheckPattern(DagInit *DI,
|
|
||||||
const std::string &RecName) {
|
|
||||||
// First, parse the pattern...
|
|
||||||
TreePatternNode *Pattern = ParseTreePattern(DI, RecName);
|
|
||||||
|
|
||||||
bool MadeChange, AnyUnset;
|
if (Record *Result = P.getResult())
|
||||||
do {
|
OS << Result->getName() << " = ";
|
||||||
MadeChange = false;
|
OS << *P.getTree();
|
||||||
AnyUnset = InferTypes(Pattern, RecName, MadeChange);
|
|
||||||
if (AnyUnset && !MadeChange) {
|
|
||||||
std::cerr << "In pattern: " << *Pattern << "\n";
|
|
||||||
throw "Cannot infer types for " + RecName;
|
|
||||||
}
|
|
||||||
} while (AnyUnset || MadeChange);
|
|
||||||
|
|
||||||
return Pattern;
|
if (!P.isResolved())
|
||||||
|
OS << " [not completely resolved]";
|
||||||
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
||||||
// our pattern database.
|
// our pattern database.
|
||||||
void InstrSelectorEmitter::ProcessNonTerminals() {
|
void InstrSelectorEmitter::ProcessNonterminals() {
|
||||||
std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
|
std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
|
||||||
for (unsigned i = 0, e = NTs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = NTs.size(); i != e; ++i) {
|
||||||
DagInit *DI = NTs[i]->getValueAsDag("Pattern");
|
DagInit *DI = NTs[i]->getValueAsDag("Pattern");
|
||||||
|
|
||||||
TreePatternNode *Pattern = ReadAndCheckPattern(DI, NTs[i]->getName());
|
Pattern *P = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this);
|
||||||
|
|
||||||
DEBUG(std::cerr << "Parsed nonterm pattern " << NTs[i]->getName() << "\t= "
|
|
||||||
<< *Pattern << "\n");
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,10 +289,9 @@ void InstrSelectorEmitter::ProcessInstructionPatterns() {
|
|||||||
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
|
||||||
Record *Inst = Insts[i];
|
Record *Inst = Insts[i];
|
||||||
if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
|
if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
|
||||||
TreePatternNode *Pattern = ReadAndCheckPattern(DI, Inst->getName());
|
Pattern *P = new Pattern(Pattern::Instruction, DI, Inst, *this);
|
||||||
|
|
||||||
DEBUG(std::cerr << "Parsed inst pattern " << Inst->getName() << "\t= "
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
<< *Pattern << "\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +302,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
|||||||
ProcessNodeTypes();
|
ProcessNodeTypes();
|
||||||
|
|
||||||
// Read in all of the nonterminals...
|
// Read in all of the nonterminals...
|
||||||
//ProcessNonTerminals();
|
ProcessNonterminals();
|
||||||
|
|
||||||
// Read all of the instruction patterns in...
|
// Read all of the instruction patterns in...
|
||||||
ProcessInstructionPatterns();
|
ProcessInstructionPatterns();
|
||||||
|
@@ -14,7 +14,10 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
class DagInit;
|
class DagInit;
|
||||||
class Init;
|
class Init;
|
||||||
|
class InstrSelectorEmitter;
|
||||||
|
|
||||||
|
/// NodeType - Represents Information parsed from the DagNode entries.
|
||||||
|
///
|
||||||
struct NodeType {
|
struct NodeType {
|
||||||
enum ArgResultTypes {
|
enum ArgResultTypes {
|
||||||
// Both argument and return types...
|
// Both argument and return types...
|
||||||
@@ -39,12 +42,17 @@ struct NodeType {
|
|||||||
static ArgResultTypes Translate(Record *R);
|
static ArgResultTypes Translate(Record *R);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// TreePatternNode - Represent a node of the tree patterns.
|
||||||
|
///
|
||||||
class TreePatternNode {
|
class TreePatternNode {
|
||||||
/// Operator - The operation that this node represents... this is null if this
|
/// Operator - The operation that this node represents... this is null if this
|
||||||
/// is a leaf.
|
/// is a leaf.
|
||||||
Record *Operator;
|
Record *Operator;
|
||||||
|
|
||||||
/// Type - The inferred value type...
|
/// Type - The inferred value type...
|
||||||
|
///
|
||||||
MVT::ValueType Type;
|
MVT::ValueType Type;
|
||||||
|
|
||||||
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
||||||
@@ -52,6 +60,7 @@ class TreePatternNode {
|
|||||||
std::vector<TreePatternNode*> Children;
|
std::vector<TreePatternNode*> Children;
|
||||||
|
|
||||||
/// Value - If this node is a leaf, this indicates what the thing is.
|
/// Value - If this node is a leaf, this indicates what the thing is.
|
||||||
|
///
|
||||||
Init *Value;
|
Init *Value;
|
||||||
public:
|
public:
|
||||||
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
||||||
@@ -68,6 +77,11 @@ public:
|
|||||||
assert(Operator != 0 && "This is a leaf node!");
|
assert(Operator != 0 && "This is a leaf node!");
|
||||||
return Children;
|
return Children;
|
||||||
}
|
}
|
||||||
|
TreePatternNode *getChild(unsigned c) const {
|
||||||
|
assert(c < Children.size() && "Child access out of range!");
|
||||||
|
return getChildren()[c];
|
||||||
|
}
|
||||||
|
|
||||||
Init *getValue() const {
|
Init *getValue() const {
|
||||||
assert(Operator == 0 && "This is not a leaf node!");
|
assert(Operator == 0 && "This is not a leaf node!");
|
||||||
return Value;
|
return Value;
|
||||||
@@ -80,17 +94,98 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Pattern - Represent a pattern of one form or another. Currently, three
|
||||||
|
/// types of patterns are possible: Instruction's, Nonterminals, and Expanders.
|
||||||
|
///
|
||||||
|
struct Pattern {
|
||||||
|
enum PatternType {
|
||||||
|
Nonterminal, Instruction, Expander
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/// PTy - The type of pattern this is.
|
||||||
|
///
|
||||||
|
PatternType PTy;
|
||||||
|
|
||||||
|
/// Tree - The tree pattern which corresponds to this pattern. Note that if
|
||||||
|
/// there was a (set) node on the outside level that it has been stripped off.
|
||||||
|
///
|
||||||
|
TreePatternNode *Tree;
|
||||||
|
|
||||||
|
/// Result - If this is an instruction or expander pattern, this is the
|
||||||
|
/// register result, specified with a (set) in the pattern.
|
||||||
|
///
|
||||||
|
Record *Result;
|
||||||
|
|
||||||
|
/// TheRecord - The actual TableGen record corresponding to this pattern.
|
||||||
|
///
|
||||||
|
Record *TheRecord;
|
||||||
|
|
||||||
|
/// Resolved - This is true of the pattern is useful in practice. In
|
||||||
|
/// particular, some non-terminals will have non-resolvable types. When a
|
||||||
|
/// user of the non-terminal is later found, they will have inferred a type
|
||||||
|
/// for the result of the non-terminal, which cause a clone of an unresolved
|
||||||
|
/// nonterminal to be made which is "resolved".
|
||||||
|
///
|
||||||
|
bool Resolved;
|
||||||
|
|
||||||
|
/// ISE - the instruction selector emitter coordinating this madness.
|
||||||
|
///
|
||||||
|
InstrSelectorEmitter &ISE;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Pattern constructor - Parse the specified DagInitializer into the current
|
||||||
|
/// record.
|
||||||
|
Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||||
|
InstrSelectorEmitter &ise);
|
||||||
|
|
||||||
|
/// getPatternType - Return what flavor of Record this pattern originated from
|
||||||
|
///
|
||||||
|
PatternType getPatternType() const { return PTy; }
|
||||||
|
|
||||||
|
/// getTree - Return the tree pattern which corresponds to this pattern.
|
||||||
|
///
|
||||||
|
TreePatternNode *getTree() const { return Tree; }
|
||||||
|
|
||||||
|
Record *getResult() const { return Result; }
|
||||||
|
|
||||||
|
/// getRecord - Return the actual TableGen record corresponding to this
|
||||||
|
/// pattern.
|
||||||
|
///
|
||||||
|
Record *getRecord() const { return TheRecord; }
|
||||||
|
|
||||||
|
bool isResolved() const { return Resolved; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||||
|
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||||
|
void error(const std::string &Msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// InstrSelectorEmitter - The top-level class which coordinates construction
|
||||||
|
/// and emission of the instruction selector.
|
||||||
|
///
|
||||||
class InstrSelectorEmitter : public TableGenBackend {
|
class InstrSelectorEmitter : public TableGenBackend {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
CodeGenTarget Target;
|
CodeGenTarget Target;
|
||||||
|
|
||||||
std::map<Record*, NodeType> NodeTypes;
|
std::map<Record*, NodeType> NodeTypes;
|
||||||
|
|
||||||
|
/// Patterns - a list of all of the patterns defined by the target description
|
||||||
|
///
|
||||||
|
std::map<Record*, Pattern*> Patterns;
|
||||||
public:
|
public:
|
||||||
InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
|
InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
|
||||||
|
|
||||||
// run - Output the instruction set description, returning true on failure.
|
// run - Output the instruction set description, returning true on failure.
|
||||||
void run(std::ostream &OS);
|
void run(std::ostream &OS);
|
||||||
|
|
||||||
|
const CodeGenTarget &getTarget() const { return Target; }
|
||||||
|
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ProcessNodeTypes - Process all of the node types in the current
|
// ProcessNodeTypes - Process all of the node types in the current
|
||||||
// RecordKeeper, turning them into the more accessible NodeTypes data
|
// RecordKeeper, turning them into the more accessible NodeTypes data
|
||||||
@@ -99,26 +194,11 @@ private:
|
|||||||
|
|
||||||
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
||||||
// our pattern database.
|
// our pattern database.
|
||||||
void ProcessNonTerminals();
|
void ProcessNonterminals();
|
||||||
|
|
||||||
// ProcessInstructionPatterns - Read in all subclasses of Instruction, and
|
// ProcessInstructionPatterns - Read in all subclasses of Instruction, and
|
||||||
// process those with a useful Pattern field.
|
// process those with a useful Pattern field.
|
||||||
void ProcessInstructionPatterns();
|
void ProcessInstructionPatterns();
|
||||||
|
|
||||||
// ParseTreePattern - Parse the specified DagInit into a TreePattern which we
|
|
||||||
// can use.
|
|
||||||
//
|
|
||||||
TreePatternNode *ParseTreePattern(DagInit *DI, const std::string &RecName);
|
|
||||||
|
|
||||||
// InferTypes - Perform type inference on the tree, returning true if there
|
|
||||||
// are any remaining untyped nodes and setting MadeChange if any changes were
|
|
||||||
// made.
|
|
||||||
bool InferTypes(TreePatternNode *N, const std::string &RecName,
|
|
||||||
bool &MadeChange);
|
|
||||||
|
|
||||||
// ReadAndCheckPattern - Parse the specified DagInit into a pattern and then
|
|
||||||
// perform full type inference.
|
|
||||||
TreePatternNode *ReadAndCheckPattern(DagInit *DI, const std::string &RecName);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -93,12 +93,60 @@ static MVT::ValueType getIntrinsicType(Record *R) {
|
|||||||
|
|
||||||
// Parse the specified DagInit into a TreePattern which we can use.
|
// Parse the specified DagInit into a TreePattern which we can use.
|
||||||
//
|
//
|
||||||
TreePatternNode *InstrSelectorEmitter::ParseTreePattern(DagInit *DI,
|
Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||||
const std::string &RecName) {
|
InstrSelectorEmitter &ise)
|
||||||
|
: PTy(pty), TheRecord(TheRec), ISE(ise) {
|
||||||
|
|
||||||
|
// First, parse the pattern...
|
||||||
|
Tree = ParseTreePattern(RawPat);
|
||||||
|
|
||||||
|
bool MadeChange, AnyUnset;
|
||||||
|
do {
|
||||||
|
MadeChange = false;
|
||||||
|
AnyUnset = InferTypes(Tree, MadeChange);
|
||||||
|
} while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
|
||||||
|
|
||||||
|
if (PTy == Instruction) {
|
||||||
|
// Check to make sure there is not any unset types in the tree pattern...
|
||||||
|
if (AnyUnset) {
|
||||||
|
std::cerr << "In instruction pattern: " << *Tree << "\n";
|
||||||
|
error("Could not infer all types!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if we have a top-level (set) of a register.
|
||||||
|
if (Tree->getOperator()->getName() == "set") {
|
||||||
|
assert(Tree->getChildren().size() == 2 && "Set with != 2 arguments?");
|
||||||
|
if (!Tree->getChild(0)->isLeaf())
|
||||||
|
error("Arg #0 of set should be a register or register class!");
|
||||||
|
DefInit *RegInit = dynamic_cast<DefInit*>(Tree->getChild(0)->getValue());
|
||||||
|
if (RegInit == 0)
|
||||||
|
error("LHS of 'set' expected to be a register or register class!");
|
||||||
|
|
||||||
|
Result = RegInit->getDef();
|
||||||
|
Tree = Tree->getChild(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resolved = !AnyUnset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pattern::error(const std::string &Msg) {
|
||||||
|
std::string M = "In ";
|
||||||
|
switch (PTy) {
|
||||||
|
case Nonterminal: M += "nonterminal "; break;
|
||||||
|
case Instruction: M += "instruction "; break;
|
||||||
|
case Expander : M += "expander "; break;
|
||||||
|
}
|
||||||
|
throw M + TheRecord->getName() + ": " + Msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TreePatternNode *Pattern::ParseTreePattern(DagInit *DI) {
|
||||||
Record *Operator = DI->getNodeType();
|
Record *Operator = DI->getNodeType();
|
||||||
|
|
||||||
if (!NodeTypes.count(Operator))
|
if (!ISE.getNodeTypes().count(Operator))
|
||||||
throw "Illegal node for instruction pattern: '" + Operator->getName() +"'!";
|
error("Unrecognized node '" + Operator->getName() + "'!");
|
||||||
|
|
||||||
const std::vector<Init*> &Args = DI->getArgs();
|
const std::vector<Init*> &Args = DI->getArgs();
|
||||||
std::vector<TreePatternNode*> Children;
|
std::vector<TreePatternNode*> Children;
|
||||||
@@ -106,14 +154,14 @@ TreePatternNode *InstrSelectorEmitter::ParseTreePattern(DagInit *DI,
|
|||||||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||||
Init *Arg = Args[i];
|
Init *Arg = Args[i];
|
||||||
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
||||||
Children.push_back(ParseTreePattern(DI, RecName));
|
Children.push_back(ParseTreePattern(DI));
|
||||||
} else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
} else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
||||||
Children.push_back(new TreePatternNode(DI));
|
Children.push_back(new TreePatternNode(DI));
|
||||||
// If it's a regclass or something else known, set the type.
|
// If it's a regclass or something else known, set the type.
|
||||||
Children.back()->setType(getIntrinsicType(DI->getDef()));
|
Children.back()->setType(getIntrinsicType(DI->getDef()));
|
||||||
} else {
|
} else {
|
||||||
Arg->dump();
|
Arg->dump();
|
||||||
throw "Unknown value for tree pattern in '" + RecName + "'!";
|
error("Unknown leaf value for tree pattern!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,37 +186,36 @@ static bool UpdateNodeType(TreePatternNode *N, MVT::ValueType VT,
|
|||||||
// InferTypes - Perform type inference on the tree, returning true if there
|
// InferTypes - Perform type inference on the tree, returning true if there
|
||||||
// are any remaining untyped nodes and setting MadeChange if any changes were
|
// are any remaining untyped nodes and setting MadeChange if any changes were
|
||||||
// made.
|
// made.
|
||||||
bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||||
const std::string &RecName,
|
|
||||||
bool &MadeChange) {
|
|
||||||
if (N->isLeaf()) return N->getType() == MVT::Other;
|
if (N->isLeaf()) return N->getType() == MVT::Other;
|
||||||
|
|
||||||
bool AnyUnset = false;
|
bool AnyUnset = false;
|
||||||
Record *Operator = N->getOperator();
|
Record *Operator = N->getOperator();
|
||||||
assert(NodeTypes.count(Operator) && "No node info for node!");
|
assert(ISE.getNodeTypes().count(Operator) && "No node info for node!");
|
||||||
const NodeType &NT = NodeTypes[Operator];
|
const NodeType &NT = ISE.getNodeTypes()[Operator];
|
||||||
|
|
||||||
// Check to see if we can infer anything about the argument types from the
|
// Check to see if we can infer anything about the argument types from the
|
||||||
// return types...
|
// return types...
|
||||||
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
||||||
if (Children.size() != NT.ArgTypes.size())
|
if (Children.size() != NT.ArgTypes.size())
|
||||||
throw "In record " + RecName + " incorrect number of children for " +
|
error("Incorrect number of children for " + Operator->getName() + " node!");
|
||||||
Operator->getName() + " node!";
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
||||||
AnyUnset |= InferTypes(Children[i], RecName, MadeChange);
|
AnyUnset |= InferTypes(Children[i], MadeChange);
|
||||||
|
|
||||||
|
|
||||||
switch (NT.ArgTypes[i]) {
|
switch (NT.ArgTypes[i]) {
|
||||||
case NodeType::Arg0:
|
case NodeType::Arg0:
|
||||||
MadeChange |= UpdateNodeType(Children[i], Children[0]->getType(),RecName);
|
MadeChange |= UpdateNodeType(Children[i], Children[0]->getType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Val:
|
case NodeType::Val:
|
||||||
if (Children[i]->getType() == MVT::isVoid)
|
if (Children[i]->getType() == MVT::isVoid)
|
||||||
throw "In pattern for " + RecName + " should not get a void node!";
|
error("Inferred a void node in an illegal place!");
|
||||||
break;
|
break;
|
||||||
case NodeType::Ptr:
|
case NodeType::Ptr:
|
||||||
MadeChange |= UpdateNodeType(Children[i],Target.getPointerType(),RecName);
|
MadeChange |= UpdateNodeType(Children[i],
|
||||||
|
ISE.getTarget().getPointerType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
default: assert(0 && "Invalid argument ArgType!");
|
default: assert(0 && "Invalid argument ArgType!");
|
||||||
}
|
}
|
||||||
@@ -177,18 +224,20 @@ bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
|||||||
// See if we can infer anything about the return type now...
|
// See if we can infer anything about the return type now...
|
||||||
switch (NT.ResultType) {
|
switch (NT.ResultType) {
|
||||||
case NodeType::Void:
|
case NodeType::Void:
|
||||||
MadeChange |= UpdateNodeType(N, MVT::isVoid, RecName);
|
MadeChange |= UpdateNodeType(N, MVT::isVoid, TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Arg0:
|
case NodeType::Arg0:
|
||||||
MadeChange |= UpdateNodeType(N, Children[0]->getType(), RecName);
|
MadeChange |= UpdateNodeType(N, Children[0]->getType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeType::Ptr:
|
case NodeType::Ptr:
|
||||||
MadeChange |= UpdateNodeType(N, Target.getPointerType(), RecName);
|
MadeChange |= UpdateNodeType(N, ISE.getTarget().getPointerType(),
|
||||||
|
TheRecord->getName());
|
||||||
break;
|
break;
|
||||||
case NodeType::Val:
|
case NodeType::Val:
|
||||||
if (N->getType() == MVT::isVoid)
|
if (N->getType() == MVT::isVoid)
|
||||||
throw "In pattern for " + RecName + " should not get a void node!";
|
error("Inferred a void node in an illegal place!");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0 && "Unhandled type constraint!");
|
assert(0 && "Unhandled type constraint!");
|
||||||
@@ -198,39 +247,36 @@ bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
|
|||||||
return AnyUnset | N->getType() == MVT::Other;
|
return AnyUnset | N->getType() == MVT::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
||||||
|
switch (P.getPatternType()) {
|
||||||
|
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
||||||
|
case Pattern::Instruction: OS << "Instruction pattern "; break;
|
||||||
|
case Pattern::Expander: OS << "Expander pattern "; break;
|
||||||
|
}
|
||||||
|
|
||||||
// ReadAndCheckPattern - Parse the specified DagInit into a pattern and then
|
OS << P.getRecord()->getName() << ":\t";
|
||||||
// perform full type inference.
|
|
||||||
//
|
|
||||||
TreePatternNode *InstrSelectorEmitter::ReadAndCheckPattern(DagInit *DI,
|
|
||||||
const std::string &RecName) {
|
|
||||||
// First, parse the pattern...
|
|
||||||
TreePatternNode *Pattern = ParseTreePattern(DI, RecName);
|
|
||||||
|
|
||||||
bool MadeChange, AnyUnset;
|
if (Record *Result = P.getResult())
|
||||||
do {
|
OS << Result->getName() << " = ";
|
||||||
MadeChange = false;
|
OS << *P.getTree();
|
||||||
AnyUnset = InferTypes(Pattern, RecName, MadeChange);
|
|
||||||
if (AnyUnset && !MadeChange) {
|
|
||||||
std::cerr << "In pattern: " << *Pattern << "\n";
|
|
||||||
throw "Cannot infer types for " + RecName;
|
|
||||||
}
|
|
||||||
} while (AnyUnset || MadeChange);
|
|
||||||
|
|
||||||
return Pattern;
|
if (!P.isResolved())
|
||||||
|
OS << " [not completely resolved]";
|
||||||
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
||||||
// our pattern database.
|
// our pattern database.
|
||||||
void InstrSelectorEmitter::ProcessNonTerminals() {
|
void InstrSelectorEmitter::ProcessNonterminals() {
|
||||||
std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
|
std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
|
||||||
for (unsigned i = 0, e = NTs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = NTs.size(); i != e; ++i) {
|
||||||
DagInit *DI = NTs[i]->getValueAsDag("Pattern");
|
DagInit *DI = NTs[i]->getValueAsDag("Pattern");
|
||||||
|
|
||||||
TreePatternNode *Pattern = ReadAndCheckPattern(DI, NTs[i]->getName());
|
Pattern *P = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this);
|
||||||
|
|
||||||
DEBUG(std::cerr << "Parsed nonterm pattern " << NTs[i]->getName() << "\t= "
|
|
||||||
<< *Pattern << "\n");
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,10 +289,9 @@ void InstrSelectorEmitter::ProcessInstructionPatterns() {
|
|||||||
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
|
||||||
Record *Inst = Insts[i];
|
Record *Inst = Insts[i];
|
||||||
if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
|
if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
|
||||||
TreePatternNode *Pattern = ReadAndCheckPattern(DI, Inst->getName());
|
Pattern *P = new Pattern(Pattern::Instruction, DI, Inst, *this);
|
||||||
|
|
||||||
DEBUG(std::cerr << "Parsed inst pattern " << Inst->getName() << "\t= "
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
<< *Pattern << "\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +302,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
|||||||
ProcessNodeTypes();
|
ProcessNodeTypes();
|
||||||
|
|
||||||
// Read in all of the nonterminals...
|
// Read in all of the nonterminals...
|
||||||
//ProcessNonTerminals();
|
ProcessNonterminals();
|
||||||
|
|
||||||
// Read all of the instruction patterns in...
|
// Read all of the instruction patterns in...
|
||||||
ProcessInstructionPatterns();
|
ProcessInstructionPatterns();
|
||||||
|
@@ -14,7 +14,10 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
class DagInit;
|
class DagInit;
|
||||||
class Init;
|
class Init;
|
||||||
|
class InstrSelectorEmitter;
|
||||||
|
|
||||||
|
/// NodeType - Represents Information parsed from the DagNode entries.
|
||||||
|
///
|
||||||
struct NodeType {
|
struct NodeType {
|
||||||
enum ArgResultTypes {
|
enum ArgResultTypes {
|
||||||
// Both argument and return types...
|
// Both argument and return types...
|
||||||
@@ -39,12 +42,17 @@ struct NodeType {
|
|||||||
static ArgResultTypes Translate(Record *R);
|
static ArgResultTypes Translate(Record *R);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// TreePatternNode - Represent a node of the tree patterns.
|
||||||
|
///
|
||||||
class TreePatternNode {
|
class TreePatternNode {
|
||||||
/// Operator - The operation that this node represents... this is null if this
|
/// Operator - The operation that this node represents... this is null if this
|
||||||
/// is a leaf.
|
/// is a leaf.
|
||||||
Record *Operator;
|
Record *Operator;
|
||||||
|
|
||||||
/// Type - The inferred value type...
|
/// Type - The inferred value type...
|
||||||
|
///
|
||||||
MVT::ValueType Type;
|
MVT::ValueType Type;
|
||||||
|
|
||||||
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
||||||
@@ -52,6 +60,7 @@ class TreePatternNode {
|
|||||||
std::vector<TreePatternNode*> Children;
|
std::vector<TreePatternNode*> Children;
|
||||||
|
|
||||||
/// Value - If this node is a leaf, this indicates what the thing is.
|
/// Value - If this node is a leaf, this indicates what the thing is.
|
||||||
|
///
|
||||||
Init *Value;
|
Init *Value;
|
||||||
public:
|
public:
|
||||||
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
||||||
@@ -68,6 +77,11 @@ public:
|
|||||||
assert(Operator != 0 && "This is a leaf node!");
|
assert(Operator != 0 && "This is a leaf node!");
|
||||||
return Children;
|
return Children;
|
||||||
}
|
}
|
||||||
|
TreePatternNode *getChild(unsigned c) const {
|
||||||
|
assert(c < Children.size() && "Child access out of range!");
|
||||||
|
return getChildren()[c];
|
||||||
|
}
|
||||||
|
|
||||||
Init *getValue() const {
|
Init *getValue() const {
|
||||||
assert(Operator == 0 && "This is not a leaf node!");
|
assert(Operator == 0 && "This is not a leaf node!");
|
||||||
return Value;
|
return Value;
|
||||||
@@ -80,17 +94,98 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Pattern - Represent a pattern of one form or another. Currently, three
|
||||||
|
/// types of patterns are possible: Instruction's, Nonterminals, and Expanders.
|
||||||
|
///
|
||||||
|
struct Pattern {
|
||||||
|
enum PatternType {
|
||||||
|
Nonterminal, Instruction, Expander
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/// PTy - The type of pattern this is.
|
||||||
|
///
|
||||||
|
PatternType PTy;
|
||||||
|
|
||||||
|
/// Tree - The tree pattern which corresponds to this pattern. Note that if
|
||||||
|
/// there was a (set) node on the outside level that it has been stripped off.
|
||||||
|
///
|
||||||
|
TreePatternNode *Tree;
|
||||||
|
|
||||||
|
/// Result - If this is an instruction or expander pattern, this is the
|
||||||
|
/// register result, specified with a (set) in the pattern.
|
||||||
|
///
|
||||||
|
Record *Result;
|
||||||
|
|
||||||
|
/// TheRecord - The actual TableGen record corresponding to this pattern.
|
||||||
|
///
|
||||||
|
Record *TheRecord;
|
||||||
|
|
||||||
|
/// Resolved - This is true of the pattern is useful in practice. In
|
||||||
|
/// particular, some non-terminals will have non-resolvable types. When a
|
||||||
|
/// user of the non-terminal is later found, they will have inferred a type
|
||||||
|
/// for the result of the non-terminal, which cause a clone of an unresolved
|
||||||
|
/// nonterminal to be made which is "resolved".
|
||||||
|
///
|
||||||
|
bool Resolved;
|
||||||
|
|
||||||
|
/// ISE - the instruction selector emitter coordinating this madness.
|
||||||
|
///
|
||||||
|
InstrSelectorEmitter &ISE;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Pattern constructor - Parse the specified DagInitializer into the current
|
||||||
|
/// record.
|
||||||
|
Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||||
|
InstrSelectorEmitter &ise);
|
||||||
|
|
||||||
|
/// getPatternType - Return what flavor of Record this pattern originated from
|
||||||
|
///
|
||||||
|
PatternType getPatternType() const { return PTy; }
|
||||||
|
|
||||||
|
/// getTree - Return the tree pattern which corresponds to this pattern.
|
||||||
|
///
|
||||||
|
TreePatternNode *getTree() const { return Tree; }
|
||||||
|
|
||||||
|
Record *getResult() const { return Result; }
|
||||||
|
|
||||||
|
/// getRecord - Return the actual TableGen record corresponding to this
|
||||||
|
/// pattern.
|
||||||
|
///
|
||||||
|
Record *getRecord() const { return TheRecord; }
|
||||||
|
|
||||||
|
bool isResolved() const { return Resolved; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||||
|
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||||
|
void error(const std::string &Msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// InstrSelectorEmitter - The top-level class which coordinates construction
|
||||||
|
/// and emission of the instruction selector.
|
||||||
|
///
|
||||||
class InstrSelectorEmitter : public TableGenBackend {
|
class InstrSelectorEmitter : public TableGenBackend {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
CodeGenTarget Target;
|
CodeGenTarget Target;
|
||||||
|
|
||||||
std::map<Record*, NodeType> NodeTypes;
|
std::map<Record*, NodeType> NodeTypes;
|
||||||
|
|
||||||
|
/// Patterns - a list of all of the patterns defined by the target description
|
||||||
|
///
|
||||||
|
std::map<Record*, Pattern*> Patterns;
|
||||||
public:
|
public:
|
||||||
InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
|
InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
|
||||||
|
|
||||||
// run - Output the instruction set description, returning true on failure.
|
// run - Output the instruction set description, returning true on failure.
|
||||||
void run(std::ostream &OS);
|
void run(std::ostream &OS);
|
||||||
|
|
||||||
|
const CodeGenTarget &getTarget() const { return Target; }
|
||||||
|
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ProcessNodeTypes - Process all of the node types in the current
|
// ProcessNodeTypes - Process all of the node types in the current
|
||||||
// RecordKeeper, turning them into the more accessible NodeTypes data
|
// RecordKeeper, turning them into the more accessible NodeTypes data
|
||||||
@@ -99,26 +194,11 @@ private:
|
|||||||
|
|
||||||
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
// ProcessNonTerminals - Read in all nonterminals and incorporate them into
|
||||||
// our pattern database.
|
// our pattern database.
|
||||||
void ProcessNonTerminals();
|
void ProcessNonterminals();
|
||||||
|
|
||||||
// ProcessInstructionPatterns - Read in all subclasses of Instruction, and
|
// ProcessInstructionPatterns - Read in all subclasses of Instruction, and
|
||||||
// process those with a useful Pattern field.
|
// process those with a useful Pattern field.
|
||||||
void ProcessInstructionPatterns();
|
void ProcessInstructionPatterns();
|
||||||
|
|
||||||
// ParseTreePattern - Parse the specified DagInit into a TreePattern which we
|
|
||||||
// can use.
|
|
||||||
//
|
|
||||||
TreePatternNode *ParseTreePattern(DagInit *DI, const std::string &RecName);
|
|
||||||
|
|
||||||
// InferTypes - Perform type inference on the tree, returning true if there
|
|
||||||
// are any remaining untyped nodes and setting MadeChange if any changes were
|
|
||||||
// made.
|
|
||||||
bool InferTypes(TreePatternNode *N, const std::string &RecName,
|
|
||||||
bool &MadeChange);
|
|
||||||
|
|
||||||
// ReadAndCheckPattern - Parse the specified DagInit into a pattern and then
|
|
||||||
// perform full type inference.
|
|
||||||
TreePatternNode *ReadAndCheckPattern(DagInit *DI, const std::string &RecName);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user