Skip to content

[TableGen] New bang operator !repr. #68716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions llvm/docs/TableGen/ProgRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,10 @@ TableGen provides "bang operators" that have a wide variety of uses:
: !getdagname !getdagop !gt !head !if
: !interleave !isa !le !listconcat !listremove
: !listsplat !logtwo !lt !mul !ne
: !not !or !range !setdagarg !setdagname
: !setdagop !shl !size !sra !srl
: !strconcat !sub !subst !substr !tail
: !tolower !toupper !xor
: !not !or !range !repr !setdagarg
: !setdagname !setdagop !shl !size !sra
: !srl !strconcat !sub !subst !substr
: !tail !tolower !toupper !xor

The ``!cond`` operator has a slightly different
syntax compared to other bang operators, so it is defined separately:
Expand Down Expand Up @@ -1850,6 +1850,10 @@ and non-0 as true.
``!range(``\ *list*\ ``)``
Equivalent to ``!range(0, !size(list))``.

``!repr(``\ *value*` ``)``
Represents *value* as a string. String format for the value is not
guaranteed to be stable. Intended for debugging purposes only.

``!setdagarg(``\ *dag*\ ``,``\ *key*\ ``,``\ *arg*\ ``)``
This operator produces a DAG node with the same operator and arguments as
*dag*, but replacing the value of the argument specified by the *key* with
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/TableGen/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,8 @@ class UnOpInit : public OpInit, public FoldingSetNode {
SIZE,
EMPTY,
GETDAGOP,
LOG2
LOG2,
REPR
};

private:
Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/TableGen/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,22 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const {
Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
RecordKeeper &RK = getRecordKeeper();
switch (getOpcode()) {
case REPR:
if (LHS->isConcrete()) {
// If it is a Record, print the full content.
if (const auto *Def = dyn_cast<DefInit>(LHS)) {
std::string S;
raw_string_ostream OS(S);
OS << *Def->getDef();
OS.flush();
return StringInit::get(RK, S);
}
// Otherwise, print the value of the variable.
else {
return StringInit::get(RK, LHS->getAsString());
}
}
break;
case TOLOWER:
if (StringInit *LHSs = dyn_cast<StringInit>(LHS))
return StringInit::get(RK, LHSs->getValue().lower());
Expand Down Expand Up @@ -957,6 +973,9 @@ std::string UnOpInit::getAsString() const {
case EMPTY: Result = "!empty"; break;
case GETDAGOP: Result = "!getdagop"; break;
case LOG2 : Result = "!logtwo"; break;
case REPR:
Result = "!repr";
break;
case TOLOWER:
Result = "!tolower";
break;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/TableGen/TGLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("exists", tgtok::XExists)
.Case("tolower", tgtok::XToLower)
.Case("toupper", tgtok::XToUpper)
.Case("repr", tgtok::XRepr)
.Default(tgtok::Error);

return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/TableGen/TGLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ enum TokKind {
XGetDagName,
XSetDagArg,
XSetDagName,
BANG_OPERATOR_LAST = XSetDagName,
XRepr,
BANG_OPERATOR_LAST = XRepr,

// String valued tokens.
STRING_VALUE_FIRST,
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/TableGen/TGParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XSize:
case tgtok::XEmpty:
case tgtok::XCast:
case tgtok::XRepr:
case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')'
UnOpInit::UnaryOp Code;
RecTy *Type = nullptr;
Expand All @@ -1185,6 +1186,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return nullptr;
}

break;
case tgtok::XRepr:
Lex.Lex(); // eat the operation
Code = UnOpInit::REPR;
Type = StringRecTy::get(Records);
break;
case tgtok::XToLower:
Lex.Lex(); // eat the operation
Expand Down
51 changes: 51 additions & 0 deletions llvm/test/TableGen/repr.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// RUN: llvm-tblgen %s | FileCheck %s

class PrintString<string s> {
string S = s;
}

def op;
def case_01 : PrintString<!repr((op op, op))>;
// CHECK-LABEL: def case_01 { // PrintString
// CHECK-NEXT: string S = "(op op, op)";
// CHECK-NEXT: }

def case_02 : PrintString<!repr(32)>;
// CHECK-LABEL: def case_02 { // PrintString
// CHECK-NEXT: string S = "32";
// CHECK-NEXT: }

multiclass Multi<int i, bits<3> b> {
defvar IncI = !repr(!add(i,1));
def _IncI : PrintString<IncI>;
def _b : PrintString<!repr(b)>;
}

defm case_03 : Multi<2, 0b111>;
// CHECK-LABEL: def case_03_IncI { // PrintString
// CHECK-NEXT: string S = "3";
// CHECK-NEXT: }
// CHECK-LABEL: def case_03_b { // PrintString
// CHECK-NEXT: string S = "{ 1, 1, 1 }";
// CHECK-NEXT: }

def case_04 : PrintString<!repr(!foreach(i, [1,2,3], !mul(i,2)))>;
// CHECK-LABEL: def case_04 { // PrintString
// CHECK-NEXT: string S = "[2, 4, 6]";
// CHECK-NEXT: }

// Show the dumping of full records...
def case_05 : PrintString<!repr(case_04)>;
// CHECK-LABEL: def case_05 { // PrintString
// CHECK-NEXT: string S = "case_04 { // PrintString
// CHECK-NEXT: string S = "[2, 4, 6]";
// CHECK-NEXT: }
// CHECK-NEXT: ";
// CHECK-NEXT: }

// ... and how !repr differs compared to !cast<string>.
def case_06 : PrintString<!cast<string>(case_04)>;
// CHECK-LABEL: def case_06 { // PrintString
// CHECK-NEXT: string S = "case_04";
// CHECK-NEXT: }