brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.8 KiB · df20cc2 Raw
502 lines · cpp
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-exception6//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 16namespace clang {17namespace format {18 19class FormatTestTableGen : public testing::Test {20protected: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 56TEST_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 65TEST_F(FormatTestTableGen, NoSpacesInSquareBracketLists) {66  verifyFormat("def flag : Flag<[\"-\", \"--\"], \"foo\">;");67}68 69TEST_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 78TEST_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 110TEST_F(FormatTestTableGen, Include) {111  verifyFormat("include \"test/IncludeFile.h\"");112}113 114TEST_F(FormatTestTableGen, Types) {115  verifyFormat("def Types : list<int>, bits<3>, list<list<string>> {}");116}117 118TEST_F(FormatTestTableGen, SimpleValue1_SingleLiterals) {119  verifyFormat("def SimpleValue {\n"120               "  let Integer = 42;\n"121               "  let String = \"some string\";\n"122               "}");123}124 125TEST_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 149TEST_F(FormatTestTableGen, SimpleValue2) {150  verifyFormat("def SimpleValue2 {\n"151               "  let True = true;\n"152               "  let False = false;\n"153               "}");154}155 156TEST_F(FormatTestTableGen, SimpleValue3) {157  verifyFormat("class SimpleValue3<int x> { int Question = ?; }");158}159 160TEST_F(FormatTestTableGen, SimpleValue4) {161  verifyFormat("def SimpleValue4 { let ValueList = {1, 2, 3}; }");162}163 164TEST_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 175TEST_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               "  let NestedDAGArg = ((DAGArg1 (v111 v112, v113), v12) v2,\n"191               "      (DAGArg3 (v31 v32)));\n"192               "}");193}194 195TEST_F(FormatTestTableGen, SimpleValue6_NestedInPat) {196  verifyFormat("def : Pat<(vec.vt (avg (vec.vt V128:$l), (vec.vt V128:$r))),\n"197               "          (inst $l, $r)>;");198}199 200TEST_F(FormatTestTableGen, SimpleValue7) {201  verifyFormat("def SimpleValue7 { let Identifier = SimpleValue; }");202}203 204TEST_F(FormatTestTableGen, SimpleValue8) {205  verifyFormat("def SimpleValue8 { let Class = SimpleValue3<3>; }");206}207 208TEST_F(FormatTestTableGen, ValueSuffix) {209  verifyFormat("def SuffixedValues {\n"210               "  let Bit = value{17};\n"211               "  let Bits = value{8...15};\n"212               "  let List = value[1];\n"213               "  let Slice1 = value[1, ];\n"214               "  let Slice2 = value[4...7, 17, 2...3, 4];\n"215               "  let Field = value.field;\n"216               "}");217}218 219TEST_F(FormatTestTableGen, PasteOperator) {220  verifyFormat("def Paste#\"Operator\" { string Paste = \"Paste\"#operator; }");221 222  verifyFormat("def [\"Traring\", \"Paste\"]# {\n"223               "  string X = Traring#;\n"224               "  string Y = List<\"Operator\">#;\n"225               "  string Z = [\"Traring\", \"Paste\", \"Traring\", \"Paste\",\n"226               "              \"Traring\", \"Paste\"]#;\n"227               "}");228 229  verifyFormat("def x#x {}", "def x\n"230                             "#x {}");231  verifyFormat("def x#x {}", "def x\n"232                             "#\n"233                             "x {}");234  verifyFormat("def x#x");235}236 237TEST_F(FormatTestTableGen, ClassDefinition) {238  verifyFormat("class Class<int x, int y = 1, string z = \"z\", int w = -1>\n"239               "    : Parent1, Parent2<x, y> {\n"240               "  int Item1 = 1;\n"241               "  int Item2;\n"242               "  code Item3 = [{ Item3 }];\n"243               "  let Item4 = 4;\n"244               "  let Item5{1, 2} = 5;\n"245               "  defvar Item6 = 6;\n"246               "  let Item7 = ?;\n"247               "  assert !ge(x, 0), \"Assert7\";\n"248               "}");249 250  verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }");251}252 253TEST_F(FormatTestTableGen, Def) {254  verifyFormat("def Def : Parent1<Def>, Parent2(defs Def) {\n"255               "  code Item1 = [{ Item1 }];\n"256               "  let Item2{1, 3...4} = {1, 2};\n"257               "  defvar Item3 = (ops nodty:$node1, nodty:$node2);\n"258               "  assert !le(Item2, 0), \"Assert4\";\n"259               "}");260 261  verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }");262 263  verifyFormat("def NotFP : FPFormat<0>;");264}265 266TEST_F(FormatTestTableGen, Let) {267  verifyFormat("let x = 1, y = value<type>,\n"268               "    z = !and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x)) in {\n"269               "  class Class1 : Parent<x, y> { let Item1 = z; }\n"270               "}");271}272 273TEST_F(FormatTestTableGen, MultiClass) {274  verifyFormat("multiclass Multiclass<int x> {\n"275               "  def : Def1<(item type:$src1),\n"276               "             (!if(!ge(x, 0), !mul(!add(x, 1), !sub(x, 2)),\n"277               "                  !sub(x, 2)))>;\n"278               "  def Def2 : value<type>;\n"279               "  def Def3 : type { let value = 1; }\n"280               "  defm : SomeMultiClass<Def1, Def2>;\n"281               "  defvar DefVar = 6;\n"282               "  foreach i = [1, 2, 3] in {\n"283               "    def : Foreach#i<(item type:$src1),\n"284               "                    (!if(!gt(x, i),\n"285               "                         !mul(!add(x, i), !sub(x, i)),\n"286               "                         !sub(x, !add(i, 1))))>;\n"287               "  }\n"288               "  if !gt(x, 0) then {\n"289               "    def : IfThen<x>;\n"290               "  } else {\n"291               "    def : IfElse<x>;\n"292               "  }\n"293               "  if (dagid x, 0) then {\n"294               "    def : If2<1>;\n"295               "  }\n"296               "  let y = 1, z = 2 in {\n"297               "    multiclass Multiclass2<int x> {\n"298               "      foreach i = [1, 2, 3] in {\n"299               "        def : Foreach#i<(item type:$src1),\n"300               "                        (!if(!gt(z, i),\n"301               "                             !mul(!add(y, i), !sub(x, i)),\n"302               "                             !sub(z, !add(i, 1))))>;\n"303               "      }\n"304               "    }\n"305               "  }\n"306               "}");307}308 309TEST_F(FormatTestTableGen, MultiClassesWithPasteOperator) {310  // This is a sensitive example for the handling of the paste operators in311  // brace type calculation.312  verifyFormat("multiclass MultiClass1<int i> {\n"313               "  def : Def#x<i>;\n"314               "  def : Def#y<i>;\n"315               "}\n"316               "multiclass MultiClass2<int i> { def : Def#x<i>; }");317}318 319TEST_F(FormatTestTableGen, Defm) {320  verifyFormat("defm : Multiclass<0>;");321 322  verifyFormat("defm Defm1 : Multiclass<1>;");323}324 325TEST_F(FormatTestTableGen, Defset) {326  verifyFormat("defset list<Class> DefSet1 = {\n"327               "  def Def1 : Class<1>;\n"328               "  def Def2 : Class<2>;\n"329               "}");330}331 332TEST_F(FormatTestTableGen, Defvar) {333  verifyFormat("defvar DefVar1 = !cond(!ge(!size(PaseOperator.Paste), 1): 1,\n"334               "                       true: 0);");335}336 337TEST_F(FormatTestTableGen, ForEach) {338  verifyFormat(339      "foreach i = [1, 2, 3] in {\n"340      "  def : Foreach#i<(item type:$src1),\n"341      "                  (!if(!lt(x, i),\n"342      "                       !shl(!mul(x, i), !size(\"string\")),\n"343      "                       !size(!strconcat(\"a\", \"b\", \"c\"))))>;\n"344      "}");345}346 347TEST_F(FormatTestTableGen, Dump) { verifyFormat("dump \"Dump\";"); }348 349TEST_F(FormatTestTableGen, If) {350  verifyFormat("if !gt(x, 0) then {\n"351               "  def : IfThen<x>;\n"352               "} else {\n"353               "  def : IfElse<x>;\n"354               "}");355}356 357TEST_F(FormatTestTableGen, Assert) {358  verifyFormat("assert !le(DefVar1, 0), \"Assert1\";");359}360 361TEST_F(FormatTestTableGen, DAGArgBreakElements) {362  FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);363  Style.ColumnLimit = 60;364  // By default, the DAGArg does not have a break inside.365  ASSERT_EQ(Style.TableGenBreakInsideDAGArg, FormatStyle::DAS_DontBreak);366  verifyFormat("def Def : Parent {\n"367               "  let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n"368               "}",369               Style);370  // This option forces to break inside the DAGArg.371  Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakElements;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,\n"380               "                      aa:$src2,\n"381               "                      aaa:$src3);\n"382               "}",383               Style);384  // Then, limit the DAGArg operator only to "ins".385  Style.TableGenBreakingDAGArgOperators = {"ins"};386  verifyFormat("def Def : Parent {\n"387               "  let dagarg = (ins a:$src1,\n"388               "                    aa:$src2,\n"389               "                    aaa:$src3);\n"390               "}",391               Style);392  verifyFormat("def Def : Parent {\n"393               "  let dagarg = (other a:$src1, aa:$src2, aaa:$src3)\n"394               "}",395               Style);396}397 398TEST_F(FormatTestTableGen, DAGArgBreakAll) {399  FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);400  Style.ColumnLimit = 60;401  // By default, the DAGArg does not have a break inside.402  verifyFormat("def Def : Parent {\n"403               "  let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n"404               "}",405               Style);406  // This option forces to break inside the DAGArg.407  Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll;408  verifyFormat("def Def : Parent {\n"409               "  let dagarg = (ins\n"410               "      a:$src1,\n"411               "      aa:$src2,\n"412               "      aaa:$src3\n"413               "  );\n"414               "}",415               Style);416  verifyFormat("def Def : Parent {\n"417               "  let dagarg = (other\n"418               "      a:$src1,\n"419               "      aa:$src2,\n"420               "      aaa:$src3\n"421               "  );\n"422               "}",423               Style);424  // Then, limit the DAGArg operator only to "ins".425  Style.TableGenBreakingDAGArgOperators = {"ins"};426  verifyFormat("def Def : Parent {\n"427               "  let dagarg = (ins\n"428               "      a:$src1,\n"429               "      aa:$src2,\n"430               "      aaa:$src3\n"431               "  );\n"432               "}",433               Style);434  verifyFormat("def Def : Parent {\n"435               "  let dagarg = (other a:$src1, aa:$src2, aaa:$src3);\n"436               "}",437               Style);438}439 440TEST_F(FormatTestTableGen, DAGArgAlignment) {441  FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);442  Style.ColumnLimit = 60;443  Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll;444  Style.TableGenBreakingDAGArgOperators = {"ins", "outs"};445  verifyFormat("def Def : Parent {\n"446               "  let dagarg = (ins\n"447               "      a:$src1,\n"448               "      aa:$src2,\n"449               "      aaa:$src3\n"450               "  )\n"451               "}",452               Style);453  verifyFormat("def Def : Parent {\n"454               "  let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n"455               "}",456               Style);457  Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true;458  verifyFormat("def Def : Parent {\n"459               "  let dagarg = (ins\n"460               "      a  :$src1,\n"461               "      aa :$src2,\n"462               "      aaa:$src3\n"463               "  )\n"464               "}",465               Style);466  verifyFormat("def Def : Parent {\n"467               "  let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n"468               "}",469               Style);470}471 472TEST_F(FormatTestTableGen, CondOperatorAlignment) {473  FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);474  Style.ColumnLimit = 60;475  verifyFormat("let CondOpe1 = !cond(!eq(size, 1): 1,\n"476               "                     !eq(size, 16): 1,\n"477               "                     true: 0);",478               Style);479  Style.AlignConsecutiveTableGenCondOperatorColons.Enabled = true;480  verifyFormat("let CondOpe1 = !cond(!eq(size, 1) : 1,\n"481               "                     !eq(size, 16): 1,\n"482               "                     true         : 0);",483               Style);484}485 486TEST_F(FormatTestTableGen, DefAlignment) {487  FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);488  Style.ColumnLimit = 60;489  verifyFormat("def Def : Parent {}\n"490               "def DefDef : Parent {}\n"491               "def DefDefDef : Parent {}",492               Style);493  Style.AlignConsecutiveTableGenDefinitionColons.Enabled = true;494  verifyFormat("def Def       : Parent {}\n"495               "def DefDef    : Parent {}\n"496               "def DefDefDef : Parent {}",497               Style);498}499 500} // namespace format501} // end namespace clang502