summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-08-01 06:27:59 +0000
committerChris Lattner <sabre@nondot.org>2003-08-01 06:27:59 +0000
commitc7d58024f8bed33e0b3e795e51a62ec30248aff3 (patch)
treef8aedb5f9f052481cbe68d91ab8ba62bff00c1d5 /utils
parent58c5de16927ea5ba1b454a69ce7ee4fdc371b9f7 (diff)
downloadllvm-c7d58024f8bed33e0b3e795e51a62ec30248aff3.tar.gz
llvm-c7d58024f8bed33e0b3e795e51a62ec30248aff3.tar.bz2
llvm-c7d58024f8bed33e0b3e795e51a62ec30248aff3.tar.xz
add support for emitting register classes
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7473 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/Record.cpp12
-rw-r--r--utils/TableGen/Record.h7
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp45
3 files changed, 63 insertions, 1 deletions
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index 8649b5fe4c..7f81a382bb 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -460,6 +460,18 @@ std::ostream &operator<<(std::ostream &OS, const Record &R) {
return OS << "}\n";
}
+/// getValueInit - Return the initializer for a value with the specified name,
+/// or throw an exception if the field does not exist.
+///
+Init *Record::getValueInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + R->getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+ return R->getValue();
+}
+
+
/// getValueAsString - This method looks up the specified field and returns its
/// value as a string, throwing an exception if the field does not exist or if
/// the value is not a string.
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 0eaf16ff0e..1729b02866 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -335,6 +335,8 @@ class CodeInit : public Init {
public:
CodeInit(const std::string &V) : Value(V) {}
+ const std::string getValue() const { return Value; }
+
virtual Init *convertInitializerTo(RecTy *Ty) {
return Ty->convertValue(this);
}
@@ -601,6 +603,11 @@ public:
// High-level methods useful to tablegen back-ends
//
+ /// getValueInit - Return the initializer for a value with the specified name,
+ /// or throw an exception if the field does not exist.
+ ///
+ Init *getValueInit(const std::string &FieldName) const;
+
/// getValueAsString - This method looks up the specified field and returns
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 66e7b1250f..af04f791d5 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -8,6 +8,7 @@
#include "RegisterInfoEmitter.h"
#include "Record.h"
+#include "Support/StringExtras.h"
#include <set>
static void EmitSourceHeader(const std::string &Desc, std::ostream &o) {
@@ -59,6 +60,12 @@ void RegisterInfoEmitter::runHeader(std::ostream &OS) {
<< "};\n\n";
}
+static std::string getQualifiedRecordName(Record *R) {
+ std::string Namespace = R->getValueAsString("Namespace");
+ if (Namespace.empty()) return R->getName();
+ return Namespace + "::" + R->getName();
+}
+
// RegisterInfoEmitter::run - Main register file description emitter.
//
void RegisterInfoEmitter::run(std::ostream &OS) {
@@ -71,6 +78,9 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
std::vector<Record*> RegisterClasses =
Records.getAllDerivedDefinitions("RegisterClass");
+ std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register");
+ Record *RegisterClass = Records.getClass("Register");
+
std::set<Record*> RegistersFound;
// Loop over all of the register classes... emitting each one.
@@ -79,7 +89,40 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
Record *RC = RegisterClasses[rc];
std::string Name = RC->getName();
- //if (Name[
+ if (Name[9] == '.') {
+ static unsigned AnonCounter = 0;
+ Name = "AnonRegClass_"+utostr(AnonCounter++);
+ }
+
+ // Emit the register list now...
+ OS << " // " << Name << " Register Class...\n const unsigned " << Name
+ << "[] = {\n ";
+ ListInit *RegList = RC->getValueAsListInit("MemberList");
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ Record *Reg = RegList->getElement(i);
+ if (!Reg->isSubClassOf(RegisterClass))
+ throw "Register Class member '" + Reg->getName() +
+ " does not derive from the Register class!";
+ if (RegistersFound.count(Reg))
+ throw "Register '" + Reg->getName() +
+ "' included in multiple register classes!";
+ OS << getQualifiedRecordName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
+ << " " << Name << "Class() : TargetRegisterClass("
+ << RC->getValueAsInt("Size")/8 << ", " << RC->getValueAsInt("Alignment")
+ << ", " << Name << ", " << Name << " + " << RegList->getSize()
+ << ") {}\n";
+
+ if (CodeInit *CI = dynamic_cast<CodeInit*>(RC->getValueInit("Methods")))
+ OS << CI->getValue();
+ else
+ throw "Expected 'code' fragment for 'Methods' value in register class '"+
+ RC->getName() + "'!";
+
+ OS << " } " << Name << "Instance;\n\n";
}