mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 12:50:00 +00:00
Add a !patsubst operator. Use on string types.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73099 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e7ccfce98
commit
0d973999f3
@ -417,6 +417,10 @@ aborts with an error. </dd>
|
||||
<dt><tt>!subst(a, b, c)</tt></dt>
|
||||
<dd>If 'a' and 'b' are of string type or are symbol references, substitute
|
||||
'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.</dd>
|
||||
<dt><tt>!patsubst(a, b, c)</tt></dt>
|
||||
<dd>patch regular expression 'a' against string 'c' and substitute string 'b' on
|
||||
a match. 'b' may contain placeholders of the form $<digit>, where
|
||||
<digit> is a number 1-9.</dd>
|
||||
<dt><tt>!regmatch(a, b)</tt></dt>
|
||||
<dd>An integer {0,1} indicating whether string 'b' matched regular expression
|
||||
'a.'</dd>
|
||||
|
15
test/TableGen/patsubst.td
Normal file
15
test/TableGen/patsubst.td
Normal file
@ -0,0 +1,15 @@
|
||||
// RUN: tblgen %s | grep {Match1 = "v4f32"} | count 1
|
||||
// RUN: tblgen %s | grep {Match2 = "v2f64"} | count 1
|
||||
// RUN: tblgen %s | grep {Match3 = "v4f32 add"} | count 1
|
||||
// RUN: tblgen %s | grep {Match4 = "v2f64 add"} | count 1
|
||||
|
||||
class Foo<string v> {
|
||||
string Value = v;
|
||||
string Match1 = !patsubst(".*ps$", "v4f32", v);
|
||||
string Match2 = !patsubst(".*pd$", "v2f64", v);
|
||||
string Match3 = !patsubst("(.*)ps$", "v4f32 $1", v);
|
||||
string Match4 = !patsubst("(.*)pd$", "v2f64 $1", v);
|
||||
}
|
||||
|
||||
def Bar : Foo<"addps">;
|
||||
def Baz : Foo<"addpd">;
|
@ -2025,7 +2025,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
ListTy - TArg->getType();
|
||||
ListTy = TArg->getType();
|
||||
}
|
||||
}
|
||||
ListInit *LI = new ListInit(Values, new ListRecTy(ListTy));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -885,7 +885,7 @@ public:
|
||||
///
|
||||
class TernOpInit : public OpInit {
|
||||
public:
|
||||
enum TernaryOp { SUBST, FOREACH, IF };
|
||||
enum TernaryOp { SUBST, FOREACH, IF, PATSUBST };
|
||||
private:
|
||||
TernaryOp Opc;
|
||||
Init *LHS, *MHS, *RHS;
|
||||
|
@ -449,6 +449,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
|
||||
if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
|
||||
if (Len == 8 && !memcmp(Start, "regmatch", 8)) return tgtok::XRegMatch;
|
||||
if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
|
||||
if (Len == 8 && !memcmp(Start, "patsubst", 8)) return tgtok::XPatSubst;
|
||||
if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
|
||||
if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
|
||||
if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
|
||||
|
@ -46,7 +46,7 @@ namespace tgtok {
|
||||
|
||||
// !keywords.
|
||||
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
|
||||
XForEach, XCar, XCdr, XNull, XIf, XRegMatch,
|
||||
XForEach, XCar, XCdr, XNull, XIf, XRegMatch, XPatSubst,
|
||||
|
||||
// Integer value.
|
||||
IntVal,
|
||||
|
@ -878,6 +878,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
|
||||
case tgtok::XIf:
|
||||
case tgtok::XForEach:
|
||||
case tgtok::XPatSubst:
|
||||
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
||||
TernOpInit::TernaryOp Code;
|
||||
RecTy *Type = 0;
|
||||
@ -896,6 +897,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
case tgtok::XSubst:
|
||||
Code = TernOpInit::SUBST;
|
||||
break;
|
||||
case tgtok::XPatSubst:
|
||||
Code = TernOpInit::PATSUBST;
|
||||
break;
|
||||
}
|
||||
if (Lex.getCode() != tgtok::l_paren) {
|
||||
TokError("expected '(' after ternary operator");
|
||||
@ -969,6 +973,10 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
Type = RHSt->getType();
|
||||
break;
|
||||
}
|
||||
case tgtok::XPatSubst: {
|
||||
Type = new StringRecTy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec, CurMultiClass);
|
||||
}
|
||||
@ -1277,6 +1285,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) {
|
||||
case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
|
||||
case tgtok::XIf:
|
||||
case tgtok::XForEach:
|
||||
case tgtok::XPatSubst:
|
||||
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
||||
return ParseOperation(CurRec);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user