1 //===- unittest/Format/FormatTestTableGen.cpp -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "FormatTestUtils.h" 10 #include "clang/Format/Format.h" 11 #include "llvm/Support/Debug.h" 12 #include "gtest/gtest.h" 13 14 #define DEBUG_TYPE "format-test" 15 16 namespace clang { 17 namespace format { 18 19 class FormatTestTableGen : public testing::Test { 20 protected: 21 static std::string format(StringRef Code, unsigned Offset, unsigned Length, 22 const FormatStyle &Style) { 23 LLVM_DEBUG(llvm::errs() << "---\n"); 24 LLVM_DEBUG(llvm::errs() << Code << "\n\n"); 25 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); 26 tooling::Replacements Replaces = reformat(Style, Code, Ranges); 27 auto Result = applyAllReplacements(Code, Replaces); 28 EXPECT_TRUE(static_cast<bool>(Result)); 29 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); 30 return *Result; 31 } 32 33 static std::string format(StringRef Code) { 34 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 35 Style.ColumnLimit = 60; // To make writing tests easier. 36 return format(Code, 0, Code.size(), Style); 37 } 38 39 static void verifyFormat(StringRef Code) { 40 EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable"; 41 EXPECT_EQ(Code.str(), format(test::messUp(Code))); 42 } 43 44 static void verifyFormat(StringRef Result, StringRef MessedUp) { 45 EXPECT_EQ(Result, format(MessedUp)); 46 } 47 48 static void verifyFormat(StringRef Code, const FormatStyle &Style) { 49 EXPECT_EQ(Code.str(), format(Code, 0, Code.size(), Style)) 50 << "Expected code is not stable"; 51 auto MessUp = test::messUp(Code); 52 EXPECT_EQ(Code.str(), format(MessUp, 0, MessUp.size(), Style)); 53 } 54 }; 55 56 TEST_F(FormatTestTableGen, FormatStringBreak) { 57 verifyFormat("include \"OptParser.td\"\n" 58 "def flag : Flag<\"--foo\">,\n" 59 " HelpText<\n" 60 " \"This is a very, very, very, very, \"\n" 61 " \"very, very, very, very, very, very, \"\n" 62 " \"very long help string\">;"); 63 } 64 65 TEST_F(FormatTestTableGen, NoSpacesInSquareBracketLists) { 66 verifyFormat("def flag : Flag<[\"-\", \"--\"], \"foo\">;"); 67 } 68 69 TEST_F(FormatTestTableGen, LiteralsAndIdentifiers) { 70 verifyFormat("def LiteralAndIdentifiers {\n" 71 " let someInteger = -42;\n" 72 " let 0startID = $TokVarName;\n" 73 " let 0xstartInteger = 0x42;\n" 74 " let someIdentifier = $TokVarName;\n" 75 "}"); 76 } 77 78 TEST_F(FormatTestTableGen, BangOperators) { 79 verifyFormat("def BangOperators {\n" 80 " let IfOpe = !if(\n" 81 " !not(!and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x))),\n" 82 " !foldl(0, !listconcat(!range(5, 6), !range(7, 8)),\n" 83 " total, rec, !add(total, rec.Number)),\n" 84 " !tail(!range(9, 10)));\n" 85 " let ForeachOpe = !foreach(\n" 86 " arg, arglist,\n" 87 " !if(!isa<SomeType>(arg.Type),\n" 88 " !add(!cast<SomeOtherType>(arg).Number, x), arg));\n" 89 " let CondOpe1 = !cond(!eq(size, 1): 1,\n" 90 " !eq(size, 2): 1,\n" 91 " !eq(size, 4): 1,\n" 92 " !eq(size, 8): 1,\n" 93 " !eq(size, 16): 1,\n" 94 " true: 0);\n" 95 " let CondOpe2 = !cond(!lt(x, 0): \"negativenegative\",\n" 96 " !eq(x, 0): \"zerozero\",\n" 97 " true: \"positivepositive\");\n" 98 " let CondOpe2WithComment = !cond(!lt(x, 0): // negative\n" 99 " \"negativenegative\",\n" 100 " !eq(x, 0): // zero\n" 101 " \"zerozero\",\n" 102 " true: // default\n" 103 " \"positivepositive\");\n" 104 " let CondOpe3WithCommentAfterLParen = !cond(\n" 105 " // comment\n" 106 " !eq(/* comment */ x, 0): \"zero\");\n" 107 "}"); 108 } 109 110 TEST_F(FormatTestTableGen, Include) { 111 verifyFormat("include \"test/IncludeFile.h\""); 112 } 113 114 TEST_F(FormatTestTableGen, Types) { 115 verifyFormat("def Types : list<int>, bits<3>, list<list<string>> {}"); 116 } 117 118 TEST_F(FormatTestTableGen, SimpleValue1_SingleLiterals) { 119 verifyFormat("def SimpleValue {\n" 120 " let Integer = 42;\n" 121 " let String = \"some string\";\n" 122 "}"); 123 } 124 125 TEST_F(FormatTestTableGen, SimpleValue1_MultilineString) { 126 // test::messUp does not understand multiline TableGen code-literals. 127 // We have to give the result and the strings to format manually. 128 StringRef DefWithCode = 129 "def SimpleValueCode {\n" 130 " let Code =\n" 131 " [{ A TokCode is nothing more than a multi-line string literal " 132 "delimited by \\[{ and }\\]. It can break across lines and the line " 133 "breaks are retained in the string. \n" 134 "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n" 135 "}"; 136 StringRef DefWithCodeMessedUp = 137 "def SimpleValueCode { let \n" 138 "Code= \n" 139 " [{ A TokCode is nothing more than a multi-line string " 140 "literal " 141 "delimited by \\[{ and }\\]. It can break across lines and the line " 142 "breaks are retained in the string. \n" 143 "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}] \n" 144 " ; \n" 145 " } "; 146 verifyFormat(DefWithCode, DefWithCodeMessedUp); 147 } 148 149 TEST_F(FormatTestTableGen, SimpleValue2) { 150 verifyFormat("def SimpleValue2 {\n" 151 " let True = true;\n" 152 " let False = false;\n" 153 "}"); 154 } 155 156 TEST_F(FormatTestTableGen, SimpleValue3) { 157 verifyFormat("class SimpleValue3<int x> { int Question = ?; }"); 158 } 159 160 TEST_F(FormatTestTableGen, SimpleValue4) { 161 verifyFormat("def SimpleValue4 { let ValueList = {1, 2, 3}; }"); 162 } 163 164 TEST_F(FormatTestTableGen, SimpleValue5) { 165 verifyFormat("def SimpleValue5 {\n" 166 " let SquareList = [1, 4, 9];\n" 167 " let SquareListWithType = [\"a\", \"b\", \"c\"]<string>;\n" 168 " let SquareListListWithType = [[1, 2], [3, 4, 5], [7]]<\n" 169 " list<int>>;\n" 170 " let SquareBitsListWithType = [ {1, 2},\n" 171 " {3, 4} ]<list<bits<8>>>;\n" 172 "}"); 173 } 174 175 TEST_F(FormatTestTableGen, SimpleValue6) { 176 verifyFormat("def SimpleValue6 {\n" 177 " let DAGArgIns = (ins i32:$src1, i32:$src2);\n" 178 " let DAGArgOuts = (outs i32:$dst1, i32:$dst2, i32:$dst3,\n" 179 " i32:$dst4, i32:$dst5, i32:$dst6, i32:$dst7);\n" 180 " let DAGArgOutsWithComment = (outs i32:$dst1, // dst1\n" 181 " i32:$dst2, // dst2\n" 182 " i32:$dst3, // dst3\n" 183 " i32:$dst4, // dst4\n" 184 " i32:$dst5, // dst5\n" 185 " i32:$dst6, // dst6\n" 186 " i32:$dst7 // dst7\n" 187 " );\n" 188 " let DAGArgBang = (!cast<SomeType>(\"Some\") i32:$src1,\n" 189 " i32:$src2);\n" 190 "}"); 191 } 192 193 TEST_F(FormatTestTableGen, SimpleValue7) { 194 verifyFormat("def SimpleValue7 { let Identifier = SimpleValue; }"); 195 } 196 197 TEST_F(FormatTestTableGen, SimpleValue8) { 198 verifyFormat("def SimpleValue8 { let Class = SimpleValue3<3>; }"); 199 } 200 201 TEST_F(FormatTestTableGen, ValueSuffix) { 202 verifyFormat("def SuffixedValues {\n" 203 " let Bit = value{17};\n" 204 " let Bits = value{8...15};\n" 205 " let List = value[1];\n" 206 " let Slice1 = value[1, ];\n" 207 " let Slice2 = value[4...7, 17, 2...3, 4];\n" 208 " let Field = value.field;\n" 209 "}"); 210 } 211 212 TEST_F(FormatTestTableGen, PasteOperator) { 213 verifyFormat("def Paste#\"Operator\" { string Paste = \"Paste\"#operator; }"); 214 215 verifyFormat("def [\"Traring\", \"Paste\"]# {\n" 216 " string X = Traring#;\n" 217 " string Y = List<\"Operator\">#;\n" 218 " string Z = [\"Traring\", \"Paste\", \"Traring\", \"Paste\",\n" 219 " \"Traring\", \"Paste\"]#;\n" 220 "}"); 221 } 222 223 TEST_F(FormatTestTableGen, ClassDefinition) { 224 verifyFormat("class Class<int x, int y = 1, string z = \"z\", int w = -1>\n" 225 " : Parent1, Parent2<x, y> {\n" 226 " int Item1 = 1;\n" 227 " int Item2;\n" 228 " code Item3 = [{ Item3 }];\n" 229 " let Item4 = 4;\n" 230 " let Item5{1, 2} = 5;\n" 231 " defvar Item6 = 6;\n" 232 " let Item7 = ?;\n" 233 " assert !ge(x, 0), \"Assert7\";\n" 234 "}"); 235 236 verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }"); 237 } 238 239 TEST_F(FormatTestTableGen, Def) { 240 verifyFormat("def Def : Parent1<Def>, Parent2(defs Def) {\n" 241 " code Item1 = [{ Item1 }];\n" 242 " let Item2{1, 3...4} = {1, 2};\n" 243 " defvar Item3 = (ops nodty:$node1, nodty:$node2);\n" 244 " assert !le(Item2, 0), \"Assert4\";\n" 245 "}"); 246 247 verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }"); 248 249 verifyFormat("def NotFP : FPFormat<0>;"); 250 } 251 252 TEST_F(FormatTestTableGen, Let) { 253 verifyFormat("let x = 1, y = value<type>,\n" 254 " z = !and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x)) in {\n" 255 " class Class1 : Parent<x, y> { let Item1 = z; }\n" 256 "}"); 257 } 258 259 TEST_F(FormatTestTableGen, MultiClass) { 260 verifyFormat("multiclass Multiclass<int x> {\n" 261 " def : Def1<(item type:$src1),\n" 262 " (!if(!ge(x, 0), !mul(!add(x, 1), !sub(x, 2)),\n" 263 " !sub(x, 2)))>;\n" 264 " def Def2 : value<type>;\n" 265 " def Def3 : type { let value = 1; }\n" 266 " defm : SomeMultiClass<Def1, Def2>;\n" 267 " defvar DefVar = 6;\n" 268 " foreach i = [1, 2, 3] in {\n" 269 " def : Foreach#i<(item type:$src1),\n" 270 " (!if(!gt(x, i),\n" 271 " !mul(!add(x, i), !sub(x, i)),\n" 272 " !sub(x, !add(i, 1))))>;\n" 273 " }\n" 274 " if !gt(x, 0) then {\n" 275 " def : IfThen<x>;\n" 276 " } else {\n" 277 " def : IfElse<x>;\n" 278 " }\n" 279 " if (dagid x, 0) then {\n" 280 " def : If2<1>;\n" 281 " }\n" 282 " let y = 1, z = 2 in {\n" 283 " multiclass Multiclass2<int x> {\n" 284 " foreach i = [1, 2, 3] in {\n" 285 " def : Foreach#i<(item type:$src1),\n" 286 " (!if(!gt(z, i),\n" 287 " !mul(!add(y, i), !sub(x, i)),\n" 288 " !sub(z, !add(i, 1))))>;\n" 289 " }\n" 290 " }\n" 291 " }\n" 292 "}"); 293 } 294 295 TEST_F(FormatTestTableGen, MultiClassesWithPasteOperator) { 296 // This is a sensitive example for the handling of the paste operators in 297 // brace type calculation. 298 verifyFormat("multiclass MultiClass1<int i> {\n" 299 " def : Def#x<i>;\n" 300 " def : Def#y<i>;\n" 301 "}\n" 302 "multiclass MultiClass2<int i> { def : Def#x<i>; }"); 303 } 304 305 TEST_F(FormatTestTableGen, Defm) { 306 verifyFormat("defm : Multiclass<0>;"); 307 308 verifyFormat("defm Defm1 : Multiclass<1>;"); 309 } 310 311 TEST_F(FormatTestTableGen, Defset) { 312 verifyFormat("defset list<Class> DefSet1 = {\n" 313 " def Def1 : Class<1>;\n" 314 " def Def2 : Class<2>;\n" 315 "}"); 316 } 317 318 TEST_F(FormatTestTableGen, Defvar) { 319 verifyFormat("defvar DefVar1 = !cond(!ge(!size(PaseOperator.Paste), 1): 1,\n" 320 " true: 0);"); 321 } 322 323 TEST_F(FormatTestTableGen, ForEach) { 324 verifyFormat( 325 "foreach i = [1, 2, 3] in {\n" 326 " def : Foreach#i<(item type:$src1),\n" 327 " (!if(!lt(x, i),\n" 328 " !shl(!mul(x, i), !size(\"string\")),\n" 329 " !size(!strconcat(\"a\", \"b\", \"c\"))))>;\n" 330 "}"); 331 } 332 333 TEST_F(FormatTestTableGen, Dump) { verifyFormat("dump \"Dump\";"); } 334 335 TEST_F(FormatTestTableGen, If) { 336 verifyFormat("if !gt(x, 0) then {\n" 337 " def : IfThen<x>;\n" 338 "} else {\n" 339 " def : IfElse<x>;\n" 340 "}"); 341 } 342 343 TEST_F(FormatTestTableGen, Assert) { 344 verifyFormat("assert !le(DefVar1, 0), \"Assert1\";"); 345 } 346 347 TEST_F(FormatTestTableGen, DAGArgBreakElements) { 348 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 349 Style.ColumnLimit = 60; 350 // By default, the DAGArg does not have a break inside. 351 ASSERT_EQ(Style.TableGenBreakInsideDAGArg, FormatStyle::DAS_DontBreak); 352 verifyFormat("def Def : Parent {\n" 353 " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n" 354 "}", 355 Style); 356 // This option forces to break inside the DAGArg. 357 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakElements; 358 verifyFormat("def Def : Parent {\n" 359 " let dagarg = (ins a:$src1,\n" 360 " aa:$src2,\n" 361 " aaa:$src3);\n" 362 "}", 363 Style); 364 verifyFormat("def Def : Parent {\n" 365 " let dagarg = (other a:$src1,\n" 366 " aa:$src2,\n" 367 " aaa:$src3);\n" 368 "}", 369 Style); 370 // Then, limit the DAGArg operator only to "ins". 371 Style.TableGenBreakingDAGArgOperators = {"ins"}; 372 verifyFormat("def Def : Parent {\n" 373 " let dagarg = (ins a:$src1,\n" 374 " aa:$src2,\n" 375 " aaa:$src3);\n" 376 "}", 377 Style); 378 verifyFormat("def Def : Parent {\n" 379 " let dagarg = (other a:$src1, aa:$src2, aaa:$src3)\n" 380 "}", 381 Style); 382 } 383 384 TEST_F(FormatTestTableGen, DAGArgBreakAll) { 385 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 386 Style.ColumnLimit = 60; 387 // By default, the DAGArg does not have a break inside. 388 verifyFormat("def Def : Parent {\n" 389 " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n" 390 "}", 391 Style); 392 // This option forces to break inside the DAGArg. 393 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; 394 verifyFormat("def Def : Parent {\n" 395 " let dagarg = (ins\n" 396 " a:$src1,\n" 397 " aa:$src2,\n" 398 " aaa:$src3\n" 399 " );\n" 400 "}", 401 Style); 402 verifyFormat("def Def : Parent {\n" 403 " let dagarg = (other\n" 404 " a:$src1,\n" 405 " aa:$src2,\n" 406 " aaa:$src3\n" 407 " );\n" 408 "}", 409 Style); 410 // Then, limit the DAGArg operator only to "ins". 411 Style.TableGenBreakingDAGArgOperators = {"ins"}; 412 verifyFormat("def Def : Parent {\n" 413 " let dagarg = (ins\n" 414 " a:$src1,\n" 415 " aa:$src2,\n" 416 " aaa:$src3\n" 417 " );\n" 418 "}", 419 Style); 420 verifyFormat("def Def : Parent {\n" 421 " let dagarg = (other a:$src1, aa:$src2, aaa:$src3);\n" 422 "}", 423 Style); 424 } 425 426 TEST_F(FormatTestTableGen, DAGArgAlignment) { 427 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 428 Style.ColumnLimit = 60; 429 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; 430 Style.TableGenBreakingDAGArgOperators = {"ins", "outs"}; 431 verifyFormat("def Def : Parent {\n" 432 " let dagarg = (ins\n" 433 " a:$src1,\n" 434 " aa:$src2,\n" 435 " aaa:$src3\n" 436 " )\n" 437 "}", 438 Style); 439 verifyFormat("def Def : Parent {\n" 440 " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" 441 "}", 442 Style); 443 Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true; 444 verifyFormat("def Def : Parent {\n" 445 " let dagarg = (ins\n" 446 " a :$src1,\n" 447 " aa :$src2,\n" 448 " aaa:$src3\n" 449 " )\n" 450 "}", 451 Style); 452 verifyFormat("def Def : Parent {\n" 453 " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" 454 "}", 455 Style); 456 } 457 458 TEST_F(FormatTestTableGen, CondOperatorAlignment) { 459 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 460 Style.ColumnLimit = 60; 461 verifyFormat("let CondOpe1 = !cond(!eq(size, 1): 1,\n" 462 " !eq(size, 16): 1,\n" 463 " true: 0);", 464 Style); 465 Style.AlignConsecutiveTableGenCondOperatorColons.Enabled = true; 466 verifyFormat("let CondOpe1 = !cond(!eq(size, 1) : 1,\n" 467 " !eq(size, 16): 1,\n" 468 " true : 0);", 469 Style); 470 } 471 472 TEST_F(FormatTestTableGen, DefAlignment) { 473 FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); 474 Style.ColumnLimit = 60; 475 verifyFormat("def Def : Parent {}\n" 476 "def DefDef : Parent {}\n" 477 "def DefDefDef : Parent {}", 478 Style); 479 Style.AlignConsecutiveTableGenDefinitionColons.Enabled = true; 480 verifyFormat("def Def : Parent {}\n" 481 "def DefDef : Parent {}\n" 482 "def DefDefDef : Parent {}", 483 Style); 484 } 485 486 } // namespace format 487 } // end namespace clang 488