Index: docs/TableGen/LangIntro.rst =================================================================== --- docs/TableGen/LangIntro.rst +++ docs/TableGen/LangIntro.rst @@ -174,7 +174,8 @@ ``!strconcat(a, b, ...)`` A string value that is the result of concatenating the 'a' and 'b' strings. More than two arguments are accepted with the result being the concatenation - of all the strings given. + of all the strings given. If all arguments are code fragments, then so is + the return value. ``str1#str2`` "#" (paste) is a shorthand for !strconcat. It may concatenate things that Index: lib/TableGen/Record.cpp =================================================================== --- lib/TableGen/Record.cpp +++ lib/TableGen/Record.cpp @@ -763,11 +763,10 @@ ProfileBinOpInit(ID, getOpcode(), getLHS(), getRHS(), getType()); } -static StringInit *ConcatStringInits(const StringInit *I0, - const StringInit *I1) { +template static T *ConcatStringLikeInits(const T *I0, const T *I1) { SmallString<80> Concat(I0->getValue()); Concat.append(I1->getValue()); - return StringInit::get(Concat); + return T::get(Concat); } Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { @@ -807,10 +806,14 @@ break; } case STRCONCAT: { + CodeInit *LHSc = dyn_cast(LHS); + CodeInit *RHSc = dyn_cast(RHS); + if (LHSc && RHSc) + return ConcatStringLikeInits(LHSc, RHSc); StringInit *LHSs = dyn_cast(LHS); StringInit *RHSs = dyn_cast(RHS); if (LHSs && RHSs) - return ConcatStringInits(LHSs, RHSs); + return ConcatStringLikeInits(LHSs, RHSs); break; } case EQ: { @@ -1896,7 +1899,7 @@ // Shortcut for the common case of concatenating two strings. if (const StringInit *I0s = dyn_cast(I0)) if (const StringInit *I1s = dyn_cast(I1)) - return ConcatStringInits(I0s, I1s); + return ConcatStringLikeInits(I0s, I1s); return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1, StringRecTy::get()); } Index: test/TableGen/strconcat.td =================================================================== --- test/TableGen/strconcat.td +++ test/TableGen/strconcat.td @@ -1,24 +1,28 @@ // RUN: llvm-tblgen %s | FileCheck %s -// CHECK: class Y { +// CHECK: class Y { // CHECK: string T = !strconcat(Y:S, "foo"); // CHECK: string T2 = !strconcat(Y:S, !strconcat("foo", !strconcat(Y:S, "bar"))); // CHECK: string S = "foobar"; +// CHECK: code T3 = !strconcat(Y:C, [{ ; }]); // CHECK: } // CHECK: def Z { // CHECK: string T = "fufoo"; // CHECK: string T2 = "fufoofubar"; // CHECK: string S = "foobar"; +// CHECK: code T3 = [{ 1 ; }]; // CHECK: } -class Y { +class Y { string T = !strconcat(S, "foo"); // More than two arguments is equivalent to nested calls string T2 = !strconcat(S, "foo", S, "bar"); // String values concatenate lexically, as in C. string S = "foo" "bar"; + + code T3 = !strconcat(C, [{ ; }]); } -def Z : Y<"fu">; +def Z : Y<"fu", [{ 1 }]>;