mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-04 02:24:29 +00:00
Implement type-inference/checking for non-terminal references
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7686 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -99,7 +99,7 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
|||||||
Resolved = !AnyUnset;
|
Resolved = !AnyUnset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pattern::error(const std::string &Msg) {
|
void Pattern::error(const std::string &Msg) const {
|
||||||
std::string M = "In ";
|
std::string M = "In ";
|
||||||
switch (PTy) {
|
switch (PTy) {
|
||||||
case Nonterminal: M += "nonterminal "; break;
|
case Nonterminal: M += "nonterminal "; break;
|
||||||
@ -109,17 +109,19 @@ void Pattern::error(const std::string &Msg) {
|
|||||||
throw M + TheRecord->getName() + ": " + Msg;
|
throw M + TheRecord->getName() + ": " + Msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MVT::ValueType getIntrinsicType(Record *R) {
|
/// getIntrinsicType - Check to see if the specified record has an intrinsic
|
||||||
|
/// type which should be applied to it. This infer the type of register
|
||||||
|
/// references from the register file information, for example.
|
||||||
|
///
|
||||||
|
MVT::ValueType Pattern::getIntrinsicType(Record *R) const {
|
||||||
// Check to see if this is a register or a register class...
|
// Check to see if this is a register or a register class...
|
||||||
if (R->isSubClassOf("RegisterClass")) {
|
if (R->isSubClassOf("RegisterClass"))
|
||||||
return getValueType(R->getValueAsDef("RegType"));
|
return getValueType(R->getValueAsDef("RegType"));
|
||||||
} else if (R->isSubClassOf("Register")) {
|
else if (R->isSubClassOf("Nonterminal"))
|
||||||
|
return ISE.ReadNonterminal(R)->getTree()->getType();
|
||||||
|
else if (R->isSubClassOf("Register")) {
|
||||||
std::cerr << "WARNING: Explicit registers not handled yet!\n";
|
std::cerr << "WARNING: Explicit registers not handled yet!\n";
|
||||||
return MVT::Other;
|
return MVT::Other;
|
||||||
} else if (R->isSubClassOf("Nonterminal")) {
|
|
||||||
//std::cerr << "Warning nonterminal type not handled yet:" << R->getName()
|
|
||||||
// << "\n";
|
|
||||||
return MVT::Other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw "Error: Unknown value used: " + R->getName();
|
throw "Error: Unknown value used: " + R->getName();
|
||||||
@ -238,6 +240,15 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
|||||||
return AnyUnset | N->getType() == MVT::Other;
|
return AnyUnset | N->getType() == MVT::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// InstantiateNonterminalsReferenced - If this pattern refers to any
|
||||||
|
/// nonterminals which are not themselves completely resolved, clone the
|
||||||
|
/// nonterminal and resolve it with the using context we provide.
|
||||||
|
///
|
||||||
|
void Pattern::InstantiateNonterminalsReferenced() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
||||||
switch (P.getPatternType()) {
|
switch (P.getPatternType()) {
|
||||||
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
||||||
@ -300,16 +311,23 @@ void InstrSelectorEmitter::ReadNodeTypes() {
|
|||||||
DEBUG(std::cerr << "DONE!\n");
|
DEBUG(std::cerr << "DONE!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) {
|
||||||
|
Pattern *&P = Patterns[R];
|
||||||
|
if (P) return P; // Don't reread it!
|
||||||
|
|
||||||
|
DagInit *DI = R->getValueAsDag("Pattern");
|
||||||
|
P = new Pattern(Pattern::Nonterminal, DI, R, *this);
|
||||||
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ReadNonTerminals - Read in all nonterminals and incorporate them into our
|
// ReadNonTerminals - Read in all nonterminals and incorporate them into our
|
||||||
// pattern database.
|
// pattern database.
|
||||||
void InstrSelectorEmitter::ReadNonterminals() {
|
void InstrSelectorEmitter::ReadNonterminals() {
|
||||||
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");
|
ReadNonterminal(NTs[i]);
|
||||||
|
|
||||||
Patterns[NTs[i]] = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this);
|
|
||||||
DEBUG(std::cerr << "Parsed " << *Patterns[NTs[i]] << "\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -342,11 +360,12 @@ void InstrSelectorEmitter::ReadExpanderPatterns() {
|
|||||||
|
|
||||||
// InstantiateNonterminals - Instantiate any unresolved nonterminals with
|
// InstantiateNonterminals - Instantiate any unresolved nonterminals with
|
||||||
// information from the context that they are used in.
|
// information from the context that they are used in.
|
||||||
|
//
|
||||||
void InstrSelectorEmitter::InstantiateNonterminals() {
|
void InstrSelectorEmitter::InstantiateNonterminals() {
|
||||||
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
|
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
|
||||||
E = Patterns.end(); I != E; ++I) {
|
E = Patterns.end(); I != E; ++I)
|
||||||
|
if (I->second->isResolved())
|
||||||
}
|
I->second->InstantiateNonterminalsReferenced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,10 +162,15 @@ public:
|
|||||||
|
|
||||||
bool isResolved() const { return Resolved; }
|
bool isResolved() const { return Resolved; }
|
||||||
|
|
||||||
|
/// InstantiateNonterminalsReferenced - If this pattern refers to any
|
||||||
|
/// nonterminals which are not themselves completely resolved, clone the
|
||||||
|
/// nonterminal and resolve it with the using context we provide.
|
||||||
|
void InstantiateNonterminalsReferenced();
|
||||||
private:
|
private:
|
||||||
|
MVT::ValueType getIntrinsicType(Record *R) const;
|
||||||
TreePatternNode *ParseTreePattern(DagInit *DI);
|
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||||
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||||
void error(const std::string &Msg);
|
void error(const std::string &Msg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
||||||
@ -193,6 +198,17 @@ public:
|
|||||||
const CodeGenTarget &getTarget() const { return Target; }
|
const CodeGenTarget &getTarget() const { return Target; }
|
||||||
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
||||||
|
|
||||||
|
/// getPattern - return the pattern corresponding to the specified record, or
|
||||||
|
/// null if there is none.
|
||||||
|
Pattern *getPattern(Record *R) const {
|
||||||
|
std::map<Record*, Pattern*>::const_iterator I = Patterns.find(R);
|
||||||
|
return I != Patterns.end() ? I->second : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ReadNonterminal - This method parses the specified record as a
|
||||||
|
/// nonterminal, but only if it hasn't been read in already.
|
||||||
|
Pattern *ReadNonterminal(Record *R);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
|
// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
|
||||||
// turning them into the more accessible NodeTypes data structure.
|
// turning them into the more accessible NodeTypes data structure.
|
||||||
|
@ -99,7 +99,7 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
|||||||
Resolved = !AnyUnset;
|
Resolved = !AnyUnset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pattern::error(const std::string &Msg) {
|
void Pattern::error(const std::string &Msg) const {
|
||||||
std::string M = "In ";
|
std::string M = "In ";
|
||||||
switch (PTy) {
|
switch (PTy) {
|
||||||
case Nonterminal: M += "nonterminal "; break;
|
case Nonterminal: M += "nonterminal "; break;
|
||||||
@ -109,17 +109,19 @@ void Pattern::error(const std::string &Msg) {
|
|||||||
throw M + TheRecord->getName() + ": " + Msg;
|
throw M + TheRecord->getName() + ": " + Msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MVT::ValueType getIntrinsicType(Record *R) {
|
/// getIntrinsicType - Check to see if the specified record has an intrinsic
|
||||||
|
/// type which should be applied to it. This infer the type of register
|
||||||
|
/// references from the register file information, for example.
|
||||||
|
///
|
||||||
|
MVT::ValueType Pattern::getIntrinsicType(Record *R) const {
|
||||||
// Check to see if this is a register or a register class...
|
// Check to see if this is a register or a register class...
|
||||||
if (R->isSubClassOf("RegisterClass")) {
|
if (R->isSubClassOf("RegisterClass"))
|
||||||
return getValueType(R->getValueAsDef("RegType"));
|
return getValueType(R->getValueAsDef("RegType"));
|
||||||
} else if (R->isSubClassOf("Register")) {
|
else if (R->isSubClassOf("Nonterminal"))
|
||||||
|
return ISE.ReadNonterminal(R)->getTree()->getType();
|
||||||
|
else if (R->isSubClassOf("Register")) {
|
||||||
std::cerr << "WARNING: Explicit registers not handled yet!\n";
|
std::cerr << "WARNING: Explicit registers not handled yet!\n";
|
||||||
return MVT::Other;
|
return MVT::Other;
|
||||||
} else if (R->isSubClassOf("Nonterminal")) {
|
|
||||||
//std::cerr << "Warning nonterminal type not handled yet:" << R->getName()
|
|
||||||
// << "\n";
|
|
||||||
return MVT::Other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw "Error: Unknown value used: " + R->getName();
|
throw "Error: Unknown value used: " + R->getName();
|
||||||
@ -238,6 +240,15 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
|||||||
return AnyUnset | N->getType() == MVT::Other;
|
return AnyUnset | N->getType() == MVT::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// InstantiateNonterminalsReferenced - If this pattern refers to any
|
||||||
|
/// nonterminals which are not themselves completely resolved, clone the
|
||||||
|
/// nonterminal and resolve it with the using context we provide.
|
||||||
|
///
|
||||||
|
void Pattern::InstantiateNonterminalsReferenced() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
|
||||||
switch (P.getPatternType()) {
|
switch (P.getPatternType()) {
|
||||||
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
|
||||||
@ -300,16 +311,23 @@ void InstrSelectorEmitter::ReadNodeTypes() {
|
|||||||
DEBUG(std::cerr << "DONE!\n");
|
DEBUG(std::cerr << "DONE!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) {
|
||||||
|
Pattern *&P = Patterns[R];
|
||||||
|
if (P) return P; // Don't reread it!
|
||||||
|
|
||||||
|
DagInit *DI = R->getValueAsDag("Pattern");
|
||||||
|
P = new Pattern(Pattern::Nonterminal, DI, R, *this);
|
||||||
|
DEBUG(std::cerr << "Parsed " << *P << "\n");
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ReadNonTerminals - Read in all nonterminals and incorporate them into our
|
// ReadNonTerminals - Read in all nonterminals and incorporate them into our
|
||||||
// pattern database.
|
// pattern database.
|
||||||
void InstrSelectorEmitter::ReadNonterminals() {
|
void InstrSelectorEmitter::ReadNonterminals() {
|
||||||
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");
|
ReadNonterminal(NTs[i]);
|
||||||
|
|
||||||
Patterns[NTs[i]] = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this);
|
|
||||||
DEBUG(std::cerr << "Parsed " << *Patterns[NTs[i]] << "\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -342,11 +360,12 @@ void InstrSelectorEmitter::ReadExpanderPatterns() {
|
|||||||
|
|
||||||
// InstantiateNonterminals - Instantiate any unresolved nonterminals with
|
// InstantiateNonterminals - Instantiate any unresolved nonterminals with
|
||||||
// information from the context that they are used in.
|
// information from the context that they are used in.
|
||||||
|
//
|
||||||
void InstrSelectorEmitter::InstantiateNonterminals() {
|
void InstrSelectorEmitter::InstantiateNonterminals() {
|
||||||
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
|
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
|
||||||
E = Patterns.end(); I != E; ++I) {
|
E = Patterns.end(); I != E; ++I)
|
||||||
|
if (I->second->isResolved())
|
||||||
}
|
I->second->InstantiateNonterminalsReferenced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,10 +162,15 @@ public:
|
|||||||
|
|
||||||
bool isResolved() const { return Resolved; }
|
bool isResolved() const { return Resolved; }
|
||||||
|
|
||||||
|
/// InstantiateNonterminalsReferenced - If this pattern refers to any
|
||||||
|
/// nonterminals which are not themselves completely resolved, clone the
|
||||||
|
/// nonterminal and resolve it with the using context we provide.
|
||||||
|
void InstantiateNonterminalsReferenced();
|
||||||
private:
|
private:
|
||||||
|
MVT::ValueType getIntrinsicType(Record *R) const;
|
||||||
TreePatternNode *ParseTreePattern(DagInit *DI);
|
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||||
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||||
void error(const std::string &Msg);
|
void error(const std::string &Msg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
|
||||||
@ -193,6 +198,17 @@ public:
|
|||||||
const CodeGenTarget &getTarget() const { return Target; }
|
const CodeGenTarget &getTarget() const { return Target; }
|
||||||
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
|
||||||
|
|
||||||
|
/// getPattern - return the pattern corresponding to the specified record, or
|
||||||
|
/// null if there is none.
|
||||||
|
Pattern *getPattern(Record *R) const {
|
||||||
|
std::map<Record*, Pattern*>::const_iterator I = Patterns.find(R);
|
||||||
|
return I != Patterns.end() ? I->second : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ReadNonterminal - This method parses the specified record as a
|
||||||
|
/// nonterminal, but only if it hasn't been read in already.
|
||||||
|
Pattern *ReadNonterminal(Record *R);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
|
// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
|
||||||
// turning them into the more accessible NodeTypes data structure.
|
// turning them into the more accessible NodeTypes data structure.
|
||||||
|
Reference in New Issue
Block a user