Skip to content
Open
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
1 change: 1 addition & 0 deletions llvm/lib/TableGen/TGLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ tgtok::TokKind TGLexer::LexIdentifier() {
StringRef Str(IdentStart, CurPtr-IdentStart);

tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
.Case("auto", tgtok::Auto)
.Case("int", tgtok::Int)
.Case("bit", tgtok::Bit)
.Case("bits", tgtok::Bits)
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/TableGen/TGLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ enum TokKind {

// Reserved keywords. ('ElseKW' is named to distinguish it from the
// existing 'Else' that means the preprocessor #else.)
Auto,
Bit,
Bits,
Code,
Expand Down
60 changes: 49 additions & 11 deletions llvm/lib/TableGen/TGParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3262,13 +3262,19 @@ bool TGParser::ParseTemplateArgValueList(
///
/// Declaration ::= FIELD? Type ID ('=' Value)?
///
Init *TGParser::ParseDeclaration(Record *CurRec,
bool ParsingTemplateArgs) {
Init *TGParser::ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs,
bool AllowAuto = false) {
// Read the field prefix if present.
bool HasField = consume(tgtok::Field);

RecTy *Type = ParseType();
if (!Type) return nullptr;
RecTy *Type;
if (AllowAuto && consume(tgtok::Auto)) {
Type = nullptr;
} else {
Type = ParseType();
if (!Type)
return nullptr;
}

if (Lex.getCode() != tgtok::Id) {
TokError("Expected identifier in declaration");
Expand All @@ -3290,6 +3296,32 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
Init *DeclName = StringInit::get(Records, Str);
Lex.Lex();

bool HasValue = consume(tgtok::equal);

// When 'auto' is used, parse the value and infer the type based on the
// value's type.
SMLoc ValLoc;
Init *Val = nullptr;
if (!Type) {
if (!HasValue) {
// auto used without a value.
TokError("auto requires assigning a value");
return nullptr;
}
ValLoc = Lex.getLoc();
// When no item type is supplied to ParseValue, it will either infer the
// type from the value, or fail to parse
Val = ParseValue(CurRec);

// Infer type from the value.
if (TypedInit *TI = dyn_cast_or_null<TypedInit>(Val)) {
Type = TI->getType();
} else {
Error(ValLoc, "unable to infer type");
return nullptr;
}
}

bool BadField;
if (!ParsingTemplateArgs) { // def, possibly in a multiclass
BadField = AddValue(CurRec, IdLoc,
Expand All @@ -3311,10 +3343,14 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
if (BadField)
return nullptr;

// If a value is present, parse it and set new field's value.
if (consume(tgtok::equal)) {
SMLoc ValLoc = Lex.getLoc();
Init *Val = ParseValue(CurRec, Type);
// For the non-auto case, if a value is present, parse it.
if (!Val && HasValue) {
ValLoc = Lex.getLoc();
Val = ParseValue(CurRec, Type);
}

// Set the new field's value.
if (HasValue) {
if (!Val ||
SetValue(CurRec, ValLoc, DeclName, {}, Val,
/*AllowSelfAssignment=*/false, /*OverrideDefLoc=*/false)) {
Expand Down Expand Up @@ -3423,7 +3459,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;

// Read the first declaration.
Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
Init *TemplArg = ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/true);
if (!TemplArg)
return true;

Expand All @@ -3432,7 +3468,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
while (consume(tgtok::comma)) {
// Read the following declarations.
SMLoc Loc = Lex.getLoc();
TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
TemplArg = ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/true);
if (!TemplArg)
return true;

Expand Down Expand Up @@ -3467,7 +3503,9 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
return ParseDump(nullptr, CurRec);

if (Lex.getCode() != tgtok::Let) {
if (!ParseDeclaration(CurRec, false))
// Allow 'auto' when parsing declarations in the body of a def or class.
if (!ParseDeclaration(CurRec, /*ParsingTemplateArgs=*/false,
/*AllowAuto=*/true))
return true;

if (!consume(tgtok::semi))
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/TableGen/TGParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ class TGParser {
bool ParseBodyItem(Record *CurRec);

bool ParseTemplateArgList(Record *CurRec);
Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs,
bool AllowAuto);
VarInit *ParseForeachDeclaration(Init *&ForeachListValue);

SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
Expand Down
44 changes: 44 additions & 0 deletions llvm/test/TableGen/auto.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: llvm-tblgen %s | FileCheck %s --check-prefix=CHECK-PASS
// RUN: not llvm-tblgen -DBAD0 %s 2>&1 | FileCheck %s --check-prefix=CHECK-BAD0 -DFILE=%s
// RUN: not llvm-tblgen -DBAD1 %s 2>&1 | FileCheck %s --check-prefix=CHECK-BAD1 -DFILE=%s

// CHECK-PASS: int Arg = A:P;
class A<int P> {
auto Arg = P;
}

def MyOp;

// CHECK-PASS-LABEL: class B
// CHECK-PASS: int A = 10;
// CHECK-PASS: string B = "x";
// CHECK-PASS: list<int> C = [10, 10];
// CHECK-PASS{LITERAL}: list<list<int>> D = [[10, 10], [11, 11]];
// CHECK-PASS: list<A> F = [anonymous_0, anonymous_1];
// CHECK-PASS: bits<4> G = { 0, 1, 0, 1 };
// CHECK-PASS: code H = [{ printf(); }];
// CHECK-PASS: bits<1> I = { 0 };
// CHECK-PASS: dag K = (MyOp 10, 100);
// CHECK-PASS: int L = 10;
class B {
auto A = 10;
auto B = "x";
auto C = [10,10];
auto D = [[10,10],[11,11]];
#ifdef BAD0
// CHECK-BAD0: [[FILE]]:[[@LINE+1]]:12: error: unable to infer type
auto E = [];
#endif
auto F = [A<10>, A<11>];
auto G = {0,1,0,1};
auto H = [{ printf(); }];
// FIXME: This becomes `bits` and not `bit`.
auto I = 0b0;
#ifdef BAD1
// CHECK-BAD1: [[FILE]]:[[@LINE+1]]:12: error: unable to infer type
auto J = ?;
#endif
auto K = (MyOp 10, 100);
auto L = A<10>.Arg;
}