Skip to content

Commit

Permalink
[clang-format] Add Options to break inside the TableGen DAGArg. (#83149)
Browse files Browse the repository at this point in the history
Add two options to control the line break inside TableGen DAGArg.
- TableGenBreakInsideDAGArg
- TableGenBreakingDAGArgOperators
  • Loading branch information
hnakamura5 committed Mar 18, 2024
1 parent 73381a8 commit 0c423af
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 6 deletions.
64 changes: 64 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6158,6 +6158,70 @@ the configuration (without a prefix: ``Auto``).
**TabWidth** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`<TabWidth>`
The number of columns used for tab stops.

.. _TableGenBreakInsideDAGArg:

**TableGenBreakInsideDAGArg** (``DAGArgStyle``) :versionbadge:`clang-format 19` :ref:`<TableGenBreakInsideDAGArg>`
The styles of the line break inside the DAGArg in TableGen.

Possible values:

* ``DAS_DontBreak`` (in configuration: ``DontBreak``)
Never break inside DAGArg.

.. code-block:: c++

let DAGArgIns = (ins i32:$src1, i32:$src2);

* ``DAS_BreakElements`` (in configuration: ``BreakElements``)
Break inside DAGArg after each list element but for the last.
This aligns to the first element.

.. code-block:: c++

let DAGArgIns = (ins i32:$src1,
i32:$src2);

* ``DAS_BreakAll`` (in configuration: ``BreakAll``)
Break inside DAGArg after the operator and the all elements.

.. code-block:: c++

let DAGArgIns = (ins
i32:$src1,
i32:$src2
);



.. _TableGenBreakingDAGArgOperators:

**TableGenBreakingDAGArgOperators** (``List of Strings``) :versionbadge:`clang-format 19` :ref:`<TableGenBreakingDAGArgOperators>`
Works only when TableGenBreakInsideDAGArg is not DontBreak.
The string list needs to consist of identifiers in TableGen.
If any identifier is specified, this limits the line breaks by
TableGenBreakInsideDAGArg option only on DAGArg values beginning with
the specified identifiers.

For example the configuration,

.. code-block:: c++

TableGenBreakInsideDAGArg: BreakAll
TableGenBreakingDAGArgOperators: ['ins', 'outs']

makes the line break only occurs inside DAGArgs beginning with the
specified identifiers 'ins' and 'outs'.


.. code-block:: c++

let DAGArgIns = (ins
i32:$src1,
i32:$src2
);
let DAGArgOtherID = (other i32:$other1, i32:$other2);
let DAGArgBang = (!cast<SomeType>("Some") i32:$src1, i32:$src2)

.. _TypeNames:

**TypeNames** (``List of Strings``) :versionbadge:`clang-format 17` :ref:`<TypeNames>`
Expand Down
63 changes: 60 additions & 3 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -4728,6 +4728,60 @@ struct FormatStyle {
/// \version 8
std::vector<std::string> StatementMacros;

/// Works only when TableGenBreakInsideDAGArg is not DontBreak.
/// The string list needs to consist of identifiers in TableGen.
/// If any identifier is specified, this limits the line breaks by
/// TableGenBreakInsideDAGArg option only on DAGArg values beginning with
/// the specified identifiers.
///
/// For example the configuration,
/// \code
/// TableGenBreakInsideDAGArg: BreakAll
/// TableGenBreakingDAGArgOperators: ['ins', 'outs']
/// \endcode
///
/// makes the line break only occurs inside DAGArgs beginning with the
/// specified identifiers 'ins' and 'outs'.
///
/// \code
/// let DAGArgIns = (ins
/// i32:$src1,
/// i32:$src2
/// );
/// let DAGArgOtherID = (other i32:$other1, i32:$other2);
/// let DAGArgBang = (!cast<SomeType>("Some") i32:$src1, i32:$src2)
/// \endcode
/// \version 19
std::vector<std::string> TableGenBreakingDAGArgOperators;

/// Different ways to control the format inside TableGen DAGArg.
enum DAGArgStyle : int8_t {
/// Never break inside DAGArg.
/// \code
/// let DAGArgIns = (ins i32:$src1, i32:$src2);
/// \endcode
DAS_DontBreak,
/// Break inside DAGArg after each list element but for the last.
/// This aligns to the first element.
/// \code
/// let DAGArgIns = (ins i32:$src1,
/// i32:$src2);
/// \endcode
DAS_BreakElements,
/// Break inside DAGArg after the operator and the all elements.
/// \code
/// let DAGArgIns = (ins
/// i32:$src1,
/// i32:$src2
/// );
/// \endcode
DAS_BreakAll,
};

/// The styles of the line break inside the DAGArg in TableGen.
/// \version 19
DAGArgStyle TableGenBreakInsideDAGArg;

/// The number of columns used for tab stops.
/// \version 3.7
unsigned TabWidth;
Expand Down Expand Up @@ -4980,9 +5034,12 @@ struct FormatStyle {
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
Standard == R.Standard &&
StatementAttributeLikeMacros == R.StatementAttributeLikeMacros &&
StatementMacros == R.StatementMacros && TabWidth == R.TabWidth &&
TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros &&
UseTab == R.UseTab &&
StatementMacros == R.StatementMacros &&
TableGenBreakingDAGArgOperators ==
R.TableGenBreakingDAGArgOperators &&
TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg &&
TabWidth == R.TabWidth && TypeNames == R.TypeNames &&
TypenameMacros == R.TypenameMacros && UseTab == R.UseTab &&
VerilogBreakBetweenInstancePorts ==
R.VerilogBreakBetweenInstancePorts &&
WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros;
Expand Down
19 changes: 17 additions & 2 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
!CurrentState.IsCSharpGenericTypeConstraint && Previous.opensScope() &&
Previous.isNot(TT_ObjCMethodExpr) && Previous.isNot(TT_RequiresClause) &&
Previous.isNot(TT_TableGenDAGArgOpener) &&
Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
!(Current.MacroParent && Previous.MacroParent) &&
(Current.isNot(TT_LineComment) ||
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) {
Expand Down Expand Up @@ -1437,7 +1438,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) {
return CurrentState.Indent;
}
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
if (Previous.is(tok::r_paren) &&
Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
!Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment)) {
return ContinuationIndent;
}
Expand Down Expand Up @@ -1698,7 +1701,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign ||
PrecedenceLevel != prec::Comma || Current.NestingLevel == 0) &&
(!Style.isTableGen() ||
(Previous && Previous->is(TT_TableGenDAGArgListComma)))) {
(Previous && Previous->isOneOf(TT_TableGenDAGArgListComma,
TT_TableGenDAGArgListCommaToBreak)))) {
NewParenState.Indent = std::max(
std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
}
Expand Down Expand Up @@ -1835,6 +1839,17 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Style.ContinuationIndentWidth +
std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);

if (Style.isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakElements) {
// For the case the next token is a TableGen DAGArg operator identifier
// that is not marked to have a line break after it.
// In this case the option DAS_BreakElements requires to align the
// DAGArg elements to the operator.
const FormatToken *Next = Current.Next;
if (Next && Next->is(TT_TableGenDAGArgOperatorID))
NewIndent = State.Column + Next->TokenText.size() + 2;
}

// Ensure that different different brackets force relative alignment, e.g.:
// void SomeFunction(vector< // break
// int> v);
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
}
};

template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);
IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);
IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);
}
};

template <>
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
static void
Expand Down Expand Up @@ -1092,6 +1100,10 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("StatementAttributeLikeMacros",
Style.StatementAttributeLikeMacros);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TableGenBreakingDAGArgOperators",
Style.TableGenBreakingDAGArgOperators);
IO.mapOptional("TableGenBreakInsideDAGArg",
Style.TableGenBreakInsideDAGArg);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TypeNames", Style.TypeNames);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
Expand Down Expand Up @@ -1552,6 +1564,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
LLVMStyle.StatementMacros.push_back("Q_UNUSED");
LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
LLVMStyle.TableGenBreakingDAGArgOperators = {};
LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
LLVMStyle.TabWidth = 8;
LLVMStyle.UseTab = FormatStyle::UT_Never;
LLVMStyle.VerilogBreakBetweenInstancePorts = true;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ extern bool IsCpp;
TYPE(TableGenDAGArgCloser) \
TYPE(TableGenDAGArgListColon) \
TYPE(TableGenDAGArgListComma) \
TYPE(TableGenDAGArgListCommaToBreak) \
TYPE(TableGenDAGArgOpener) \
TYPE(TableGenDAGArgOpenerToBreak) \
TYPE(TableGenDAGArgOperatorID) \
TYPE(TableGenDAGArgOperatorToBreak) \
TYPE(TableGenListCloser) \
TYPE(TableGenListOpener) \
TYPE(TableGenMultiLineString) \
Expand Down
64 changes: 63 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,16 +986,59 @@ class AnnotatingParser {
return false;
}

// Judge if the token is a operator ID to insert line break in DAGArg.
// That is, TableGenBreakingDAGArgOperators is empty (by the definition of the
// option) or the token is in the list.
bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) {
auto &Opes = Style.TableGenBreakingDAGArgOperators;
// If the list is empty, all operators are breaking operators.
if (Opes.empty())
return true;
// Otherwise, the operator is limited to normal identifiers.
if (Tok.isNot(tok::identifier) ||
Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
return false;
}
// The case next is colon, it is not a operator of identifier.
if (!Tok.Next || Tok.Next->is(tok::colon))
return false;
return std::find(Opes.begin(), Opes.end(), Tok.TokenText.str()) !=
Opes.end();
}

// SimpleValue6 ::= "(" DagArg [DagArgList] ")"
// This parses SimpleValue 6's inside part of "(" ")"
bool parseTableGenDAGArgAndList(FormatToken *Opener) {
FormatToken *FirstTok = CurrentToken;
if (!parseTableGenDAGArg())
return false;
bool BreakInside = false;
if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) {
// Specialized detection for DAGArgOperator, that determines the way of
// line break for this DAGArg elements.
if (isTableGenDAGArgBreakingOperator(*FirstTok)) {
// Special case for identifier DAGArg operator.
BreakInside = true;
Opener->setType(TT_TableGenDAGArgOpenerToBreak);
if (FirstTok->isOneOf(TT_TableGenBangOperator,
TT_TableGenCondOperator)) {
// Special case for bang/cond operators. Set the whole operator as
// the DAGArg operator. Always break after it.
CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak);
} else if (FirstTok->is(tok::identifier)) {
if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll)
FirstTok->setType(TT_TableGenDAGArgOperatorToBreak);
else
FirstTok->setType(TT_TableGenDAGArgOperatorID);
}
}
}
// Parse the [DagArgList] part
bool FirstDAGArgListElm = true;
while (CurrentToken) {
if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) {
CurrentToken->setType(TT_TableGenDAGArgListComma);
CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak
: TT_TableGenDAGArgListComma);
skipToNextNonComment();
}
if (CurrentToken && CurrentToken->is(tok::r_paren)) {
Expand Down Expand Up @@ -5086,6 +5129,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
}
if (Right.is(TT_TableGenCondOperatorColon))
return false;
if (Left.isOneOf(TT_TableGenDAGArgOperatorID,
TT_TableGenDAGArgOperatorToBreak) &&
Right.isNot(TT_TableGenDAGArgCloser)) {
return true;
}
// Do not insert bang operators and consequent openers.
if (Right.isOneOf(tok::l_paren, tok::less) &&
Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
Expand Down Expand Up @@ -5462,6 +5510,18 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// case2:0);
if (Left.is(TT_TableGenCondOperatorComma))
return true;
if (Left.is(TT_TableGenDAGArgOperatorToBreak) &&
Right.isNot(TT_TableGenDAGArgCloser)) {
return true;
}
if (Left.is(TT_TableGenDAGArgListCommaToBreak))
return true;
if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen &&
Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) &&
&Left != Right.MatchingParen->Next) {
// Check to avoid empty DAGArg such as (ins).
return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll;
}
}

if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&
Expand Down Expand Up @@ -5876,6 +5936,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// Avoid to break around paste operator.
if (Left.is(tok::hash) || Right.is(tok::hash))
return false;
if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator))
return false;
}

if (Left.is(tok::at))
Expand Down

0 comments on commit 0c423af

Please sign in to comment.