aboutsummaryrefslogtreecommitdiffstats
path: root/utils/TableGen/Record.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/Record.cpp')
-rw-r--r--utils/TableGen/Record.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index fa10799..2f500ae 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -18,6 +18,7 @@
#include <ios>
#include <sys/types.h>
#include <regex.h>
+#include <sstream>
using namespace llvm;
@@ -1034,6 +1035,69 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
}
break;
}
+
+ case PATSUBST: {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *MHSs = dynamic_cast<StringInit*>(MHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ if (LHSs && MHSs && RHSs) {
+ regex_t compiled;
+ int err = regcomp (&compiled, LHSs->getValue().c_str(), REG_EXTENDED);
+ if (err != 0) {
+ size_t length = regerror (err, &compiled, NULL, 0);
+ char *buffer = new char[length];
+ (void) regerror (err, &compiled, buffer, length);
+ std::string errmsg = buffer;
+ delete[] buffer;
+ regfree(&compiled);
+ throw errmsg;
+ }
+ regmatch_t matches[10];
+ int result = regexec(&compiled, RHSs->getValue().c_str(), 10, matches, 0);
+ if (result == REG_ESPACE) {
+ size_t length = regerror (err, &compiled, NULL, 0);
+ char *buffer = new char[length];
+ (void) regerror (err, &compiled, buffer, length);
+ std::string errmsg = buffer;
+ delete[] buffer;
+ regfree(&compiled);
+ throw errmsg;
+ }
+ regfree(&compiled);
+ if (result == 0) {
+ // Parse the substitution string looking for $1, $2, etc. and
+ // substitute strings. If there are no $1, etc. just replace
+ // the whole string.
+ std::string replacement = MHSs->getValue();
+ size_t pos = replacement.find("$");
+ while (pos != std::string::npos && pos+1 < replacement.size()) {
+ if (std::isdigit(replacement[pos+1])) {
+ std::string sidx(&replacement[pos+1], 1);
+ std::istringstream str(sidx);
+ int idx;
+ if (str >> idx) {
+ replacement.replace(pos, 2, RHSs->getValue(), matches[idx].rm_so,
+ matches[idx].rm_eo - matches[idx].rm_so);
+ }
+ else {
+ throw "unexpected failure in patsubst index calculation";
+ }
+ }
+ else if (replacement[pos+1] == '$') {
+ replacement.replace(pos, 2, "$");
+ }
+ pos = replacement.find("$", pos+1);
+ }
+ return new StringInit(replacement);
+ }
+ else {
+ // No match, just pass the string through
+ return RHSs;
+ }
+ }
+ break;
+ }
}
return this;
@@ -1069,6 +1133,7 @@ std::string TernOpInit::getAsString() const {
std::string Result;
switch (Opc) {
case SUBST: Result = "!subst"; break;
+ case PATSUBST: Result = "!patsubst"; break;
case FOREACH: Result = "!foreach"; break;
case IF: Result = "!if"; break;
}