llvm.org GIT mirror llvm / 0d97399
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 David Greene 10 years ago
8 changed file(s) with 97 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
416416
!subst(a, b, c)
417417
If 'a' and 'b' are of string type or are symbol references, substitute
418418 'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.
419
!patsubst(a, b, c)
420
patch regular expression 'a' against string 'c' and substitute string 'b' on
421 a match. 'b' may contain placeholders of the form $<digit>, where
422 <digit> is a number 1-9.
419423
!regmatch(a, b)
420424
An integer {0,1} indicating whether string 'b' matched regular expression
421425 'a.'
0 // RUN: tblgen %s | grep {Match1 = "v4f32"} | count 1
1 // RUN: tblgen %s | grep {Match2 = "v2f64"} | count 1
2 // RUN: tblgen %s | grep {Match3 = "v4f32 add"} | count 1
3 // RUN: tblgen %s | grep {Match4 = "v2f64 add"} | count 1
4
5 class Foo {
6 string Value = v;
7 string Match1 = !patsubst(".*ps$", "v4f32", v);
8 string Match2 = !patsubst(".*pd$", "v2f64", v);
9 string Match3 = !patsubst("(.*)ps$", "v4f32 $1", v);
10 string Match4 = !patsubst("(.*)pd$", "v2f64 $1", v);
11 }
12
13 def Bar : Foo<"addps">;
14 def Baz : Foo<"addpd">;
20242024 }
20252025 }
20262026 else {
2027 ListTy - TArg->getType();
2027 ListTy = TArg->getType();
20282028 }
20292029 }
20302030 ListInit *LI = new ListInit(Values, new ListRecTy(ListTy));
1717 #include
1818 #include
1919 #include
20 #include
2021
2122 using namespace llvm;
2223
10331034 }
10341035 break;
10351036 }
1037
1038 case PATSUBST: {
1039 StringInit *LHSs = dynamic_cast(LHS);
1040 StringInit *MHSs = dynamic_cast(MHS);
1041 StringInit *RHSs = dynamic_cast(RHS);
1042
1043 if (LHSs && MHSs && RHSs) {
1044 regex_t compiled;
1045 int err = regcomp (&compiled, LHSs->getValue().c_str(), REG_EXTENDED);
1046 if (err != 0) {
1047 size_t length = regerror (err, &compiled, NULL, 0);
1048 char *buffer = new char[length];
1049 (void) regerror (err, &compiled, buffer, length);
1050 std::string errmsg = buffer;
1051 delete[] buffer;
1052 regfree(&compiled);
1053 throw errmsg;
1054 }
1055 regmatch_t matches[10];
1056 int result = regexec(&compiled, RHSs->getValue().c_str(), 10, matches, 0);
1057 if (result == REG_ESPACE) {
1058 size_t length = regerror (err, &compiled, NULL, 0);
1059 char *buffer = new char[length];
1060 (void) regerror (err, &compiled, buffer, length);
1061 std::string errmsg = buffer;
1062 delete[] buffer;
1063 regfree(&compiled);
1064 throw errmsg;
1065 }
1066 regfree(&compiled);
1067 if (result == 0) {
1068 // Parse the substitution string looking for $1, $2, etc. and
1069 // substitute strings. If there are no $1, etc. just replace
1070 // the whole string.
1071 std::string replacement = MHSs->getValue();
1072 size_t pos = replacement.find("$");
1073 while (pos != std::string::npos && pos+1 < replacement.size()) {
1074 if (std::isdigit(replacement[pos+1])) {
1075 std::string sidx(&replacement[pos+1], 1);
1076 std::istringstream str(sidx);
1077 int idx;
1078 if (str >> idx) {
1079 replacement.replace(pos, 2, RHSs->getValue(), matches[idx].rm_so,
1080 matches[idx].rm_eo - matches[idx].rm_so);
1081 }
1082 else {
1083 throw "unexpected failure in patsubst index calculation";
1084 }
1085 }
1086 else if (replacement[pos+1] == '$') {
1087 replacement.replace(pos, 2, "$");
1088 }
1089 pos = replacement.find("$", pos+1);
1090 }
1091 return new StringInit(replacement);
1092 }
1093 else {
1094 // No match, just pass the string through
1095 return RHSs;
1096 }
1097 }
1098 break;
1099 }
10361100 }
10371101
10381102 return this;
10681132 std::string Result;
10691133 switch (Opc) {
10701134 case SUBST: Result = "!subst"; break;
1135 case PATSUBST: Result = "!patsubst"; break;
10711136 case FOREACH: Result = "!foreach"; break;
10721137 case IF: Result = "!if"; break;
10731138 }
884884 ///
885885 class TernOpInit : public OpInit {
886886 public:
887 enum TernaryOp { SUBST, FOREACH, IF };
887 enum TernaryOp { SUBST, FOREACH, IF, PATSUBST };
888888 private:
889889 TernaryOp Opc;
890890 Init *LHS, *MHS, *RHS;
448448 if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
449449 if (Len == 8 && !memcmp(Start, "regmatch", 8)) return tgtok::XRegMatch;
450450 if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
451 if (Len == 8 && !memcmp(Start, "patsubst", 8)) return tgtok::XPatSubst;
451452 if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
452453 if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
453454 if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
4545
4646 // !keywords.
4747 XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
48 XForEach, XCar, XCdr, XNull, XIf, XRegMatch,
48 XForEach, XCar, XCdr, XNull, XIf, XRegMatch, XPatSubst,
4949
5050 // Integer value.
5151 IntVal,
877877
878878 case tgtok::XIf:
879879 case tgtok::XForEach:
880 case tgtok::XPatSubst:
880881 case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
881882 TernOpInit::TernaryOp Code;
882883 RecTy *Type = 0;
894895 break;
895896 case tgtok::XSubst:
896897 Code = TernOpInit::SUBST;
898 break;
899 case tgtok::XPatSubst:
900 Code = TernOpInit::PATSUBST;
897901 break;
898902 }
899903 if (Lex.getCode() != tgtok::l_paren) {
968972 Type = RHSt->getType();
969973 break;
970974 }
975 case tgtok::XPatSubst: {
976 Type = new StringRecTy;
977 break;
978 }
971979 }
972980 return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec, CurMultiClass);
973981 }
12761284 case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
12771285 case tgtok::XIf:
12781286 case tgtok::XForEach:
1287 case tgtok::XPatSubst:
12791288 case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
12801289 return ParseOperation(CurRec);
12811290 break;