diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 84901e5fcb4..5aec728ae19 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -432,8 +432,8 @@ protected: /// readability for really no benefit. enum InitKind { IK_BitInit, - IK_BitsInit, IK_FirstTypedInit, + IK_BitsInit, IK_DagInit, IK_DefInit, IK_FieldInit, @@ -651,11 +651,12 @@ public: /// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. /// It contains a vector of bits, whose size is determined by the type. /// -class BitsInit : public Init, public FoldingSetNode { +class BitsInit : public TypedInit, public FoldingSetNode { std::vector Bits; BitsInit(ArrayRef Range) - : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {} + : TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())), + Bits(Range.begin(), Range.end()) {} BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION; BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION; @@ -688,6 +689,14 @@ public: } std::string getAsString() const override; + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { + llvm_unreachable("Illegal element reference off bits"); + } + Init *resolveReferences(Record &R, const RecordVal *RV) const override; Init *getBit(unsigned Bit) const override { diff --git a/test/TableGen/if.td b/test/TableGen/if.td index 1d8d62329ae..05a2d992856 100644 --- a/test/TableGen/if.td +++ b/test/TableGen/if.td @@ -3,7 +3,7 @@ // Support for an `!if' operator as part of a `let' statement. // CHECK: class C -// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, !if({ C:y{3} }, 1, !if({ C:y{2} }, { C:x{0} }, !if({ C:y{1} }, { C:x{1} }, !if({ C:y{0} }, { C:x{2} }, ?)))){0}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){1}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){0}, !if({ C:x{2} }, 2, 6){2}, !if({ C:x{2} }, 2, 6){1}, !if({ C:x{2} }, 2, 6){0}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){1}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){0}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){3}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){2}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){1}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){0} }; +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, !if({ C:y{3} }, 1, !if({ C:y{2} }, { C:x{0} }, !if({ C:y{1} }, { C:x{1} }, !if({ C:y{0} }, { C:x{2} }, ?)))){0}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){1}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){0}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){2}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){1}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){0}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){1}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){0}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){3}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){2}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){1}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){0} }; class C x, bits<4> y, bit z> { bits<16> n; diff --git a/test/TableGen/list-element-bitref.td b/test/TableGen/list-element-bitref.td index 4622f28526e..0f59b537fa6 100644 --- a/test/TableGen/list-element-bitref.td +++ b/test/TableGen/list-element-bitref.td @@ -1,7 +1,7 @@ // RUN: llvm-tblgen %s | FileCheck %s // XFAIL: vg_leak -class C> L> { +class C> L> { bits<2> V0 = L[0]{1-0}; bits<2> V1 = L[1]{3-2}; string V2 = !if(L[0]{0}, "Odd", "Even"); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 2577ad4d919..1e8daf5b09b 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -520,6 +520,21 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // Bits (also used for 0bxx literals) + if (BitsInit *BI = dyn_cast(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + if (!BI->isComplete()) + return false; + // Convert the bits init to an integer and use that for the result. + IntInit *II = + dyn_cast_or_null(BI->convertInitializerTo(IntRecTy::get())); + if (!II) + return false; + ResOp = ResultOperand(II->getValue()); + return true; + } + // If both are Operands with the same MVT, allow the conversion. It's // up to the user to make sure the values are appropriate, just like // for isel Pat's.