diff options
Diffstat (limited to 'llvm/lib/TableGen/Record.cpp')
-rw-r--r-- | llvm/lib/TableGen/Record.cpp | 519 |
1 files changed, 389 insertions, 130 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index d3db004196b8..b6c6b8f031d3 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -43,15 +43,11 @@ using namespace llvm; static BumpPtrAllocator Allocator; -STATISTIC(CodeInitsConstructed, - "The total number of unique CodeInits constructed"); - //===----------------------------------------------------------------------===// // Type implementations //===----------------------------------------------------------------------===// BitRecTy BitRecTy::Shared; -CodeRecTy CodeRecTy::Shared; IntRecTy IntRecTy::Shared; StringRecTy StringRecTy::Shared; DagRecTy DagRecTy::Shared; @@ -113,27 +109,22 @@ bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const { return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind; } -bool CodeRecTy::typeIsConvertibleTo(const RecTy *RHS) const { - RecTyKind Kind = RHS->getRecTyKind(); - return Kind == CodeRecTyKind || Kind == StringRecTyKind; -} - std::string StringRecTy::getAsString() const { return "string"; } bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const { RecTyKind Kind = RHS->getRecTyKind(); - return Kind == StringRecTyKind || Kind == CodeRecTyKind; + return Kind == StringRecTyKind; } std::string ListRecTy::getAsString() const { - return "list<" + Ty->getAsString() + ">"; + return "list<" + ElementTy->getAsString() + ">"; } bool ListRecTy::typeIsConvertibleTo(const RecTy *RHS) const { if (const auto *ListTy = dyn_cast<ListRecTy>(RHS)) - return Ty->typeIsConvertibleTo(ListTy->getElementType()); + return ElementTy->typeIsConvertibleTo(ListTy->getElementType()); return false; } @@ -241,13 +232,10 @@ bool RecordRecTy::typeIsA(const RecTy *RHS) const { static RecordRecTy *resolveRecordTypes(RecordRecTy *T1, RecordRecTy *T2) { SmallVector<Record *, 4> CommonSuperClasses; - SmallVector<Record *, 4> Stack; - - Stack.insert(Stack.end(), T1->classes_begin(), T1->classes_end()); + SmallVector<Record *, 4> Stack(T1->classes_begin(), T1->classes_end()); while (!Stack.empty()) { - Record *R = Stack.back(); - Stack.pop_back(); + Record *R = Stack.pop_back_val(); if (T2->isSubClassOf(R)) { CommonSuperClasses.push_back(R); @@ -514,45 +502,26 @@ IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { return BitsInit::get(NewBits); } -CodeInit *CodeInit::get(StringRef V, const SMLoc &Loc) { - static StringSet<BumpPtrAllocator &> ThePool(Allocator); - - CodeInitsConstructed++; - - // Unlike StringMap, StringSet doesn't accept empty keys. - if (V.empty()) - return new (Allocator) CodeInit("", Loc); - - // Location tracking prevents us from de-duping CodeInits as we're never - // called with the same string and same location twice. However, we can at - // least de-dupe the strings for a modest saving. - auto &Entry = *ThePool.insert(V).first; - return new(Allocator) CodeInit(Entry.getKey(), Loc); -} - -StringInit *StringInit::get(StringRef V) { - static StringMap<StringInit*, BumpPtrAllocator &> ThePool(Allocator); +StringInit *StringInit::get(StringRef V, StringFormat Fmt) { + static StringMap<StringInit*, BumpPtrAllocator &> StringPool(Allocator); + static StringMap<StringInit*, BumpPtrAllocator &> CodePool(Allocator); - auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first; - if (!Entry.second) - Entry.second = new(Allocator) StringInit(Entry.getKey()); - return Entry.second; + if (Fmt == SF_String) { + auto &Entry = *StringPool.insert(std::make_pair(V, nullptr)).first; + if (!Entry.second) + Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt); + return Entry.second; + } else { + auto &Entry = *CodePool.insert(std::make_pair(V, nullptr)).first; + if (!Entry.second) + Entry.second = new (Allocator) StringInit(Entry.getKey(), Fmt); + return Entry.second; + } } Init *StringInit::convertInitializerTo(RecTy *Ty) const { if (isa<StringRecTy>(Ty)) return const_cast<StringInit *>(this); - if (isa<CodeRecTy>(Ty)) - return CodeInit::get(getValue(), SMLoc()); - - return nullptr; -} - -Init *CodeInit::convertInitializerTo(RecTy *Ty) const { - if (isa<CodeRecTy>(Ty)) - return const_cast<CodeInit *>(this); - if (isa<StringRecTy>(Ty)) - return StringInit::get(getValue()); return nullptr; } @@ -719,8 +688,10 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { if (DefInit *LHSd = dyn_cast<DefInit>(LHS)) return StringInit::get(LHSd->getAsString()); - if (IntInit *LHSi = dyn_cast<IntInit>(LHS)) + if (IntInit *LHSi = + dyn_cast_or_null<IntInit>(LHS->convertInitializerTo(IntRecTy::get()))) return StringInit::get(LHSi->getAsString()); + } else if (isa<RecordRecTy>(getType())) { if (StringInit *Name = dyn_cast<StringInit>(LHS)) { if (!CurRec && !IsFinal) @@ -761,6 +732,12 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { return NewInit; break; + case NOT: + if (IntInit *LHSi = + dyn_cast_or_null<IntInit>(LHS->convertInitializerTo(IntRecTy::get()))) + return IntInit::get(LHSi->getValue() ? 0 : 1); + break; + case HEAD: if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) { assert(!LHSl->empty() && "Empty list in head"); @@ -780,16 +757,22 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { case SIZE: if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) return IntInit::get(LHSl->size()); + if (DagInit *LHSd = dyn_cast<DagInit>(LHS)) + return IntInit::get(LHSd->arg_size()); + if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) + return IntInit::get(LHSs->getValue().size()); break; case EMPTY: if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) return IntInit::get(LHSl->empty()); + if (DagInit *LHSd = dyn_cast<DagInit>(LHS)) + return IntInit::get(LHSd->arg_empty()); if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) return IntInit::get(LHSs->getValue().empty()); break; - case GETOP: + case GETDAGOP: if (DagInit *Dag = dyn_cast<DagInit>(LHS)) { DefInit *DI = DefInit::get(Dag->getOperatorAsDef({})); if (!DI->getType()->typeIsA(getType())) { @@ -820,11 +803,12 @@ std::string UnOpInit::getAsString() const { std::string Result; switch (getOpcode()) { case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break; + case NOT: Result = "!not"; break; case HEAD: Result = "!head"; break; case TAIL: Result = "!tail"; break; case SIZE: Result = "!size"; break; case EMPTY: Result = "!empty"; break; - case GETOP: Result = "!getop"; break; + case GETDAGOP: Result = "!getdagop"; break; } return Result + "(" + LHS->getAsString() + ")"; } @@ -862,7 +846,53 @@ static StringInit *ConcatStringInits(const StringInit *I0, const StringInit *I1) { SmallString<80> Concat(I0->getValue()); Concat.append(I1->getValue()); - return StringInit::get(Concat); + return StringInit::get(Concat, + StringInit::determineFormat(I0->getFormat(), + I1->getFormat())); +} + +static StringInit *interleaveStringList(const ListInit *List, + const StringInit *Delim) { + if (List->size() == 0) + return StringInit::get(""); + StringInit *Element = dyn_cast<StringInit>(List->getElement(0)); + if (!Element) + return nullptr; + SmallString<80> Result(Element->getValue()); + StringInit::StringFormat Fmt = StringInit::SF_String; + + for (unsigned I = 1, E = List->size(); I < E; ++I) { + Result.append(Delim->getValue()); + StringInit *Element = dyn_cast<StringInit>(List->getElement(I)); + if (!Element) + return nullptr; + Result.append(Element->getValue()); + Fmt = StringInit::determineFormat(Fmt, Element->getFormat()); + } + return StringInit::get(Result, Fmt); +} + +static StringInit *interleaveIntList(const ListInit *List, + const StringInit *Delim) { + if (List->size() == 0) + return StringInit::get(""); + IntInit *Element = + dyn_cast_or_null<IntInit>(List->getElement(0) + ->convertInitializerTo(IntRecTy::get())); + if (!Element) + return nullptr; + SmallString<80> Result(Element->getAsString()); + + for (unsigned I = 1, E = List->size(); I < E; ++I) { + Result.append(Delim->getValue()); + IntInit *Element = + dyn_cast_or_null<IntInit>(List->getElement(I) + ->convertInitializerTo(IntRecTy::get())); + if (!Element) + return nullptr; + Result.append(Element->getAsString()); + } + return StringInit::get(Result); } Init *BinOpInit::getStrConcat(Init *I0, Init *I1) { @@ -876,8 +906,8 @@ Init *BinOpInit::getStrConcat(Init *I0, Init *I1) { static ListInit *ConcatListInits(const ListInit *LHS, const ListInit *RHS) { SmallVector<Init *, 8> Args; - Args.insert(Args.end(), LHS->begin(), LHS->end()); - Args.insert(Args.end(), RHS->begin(), RHS->end()); + llvm::append_range(Args, *LHS); + llvm::append_range(Args, *RHS); return ListInit::get(Args, LHS->getElementType()); } @@ -891,10 +921,6 @@ Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) { return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); } -Init *BinOpInit::getListSplat(TypedInit *LHS, Init *RHS) { - return BinOpInit::get(BinOpInit::LISTSPLAT, LHS, RHS, LHS->getType()); -} - Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case CONCAT: { @@ -934,8 +960,8 @@ Init *BinOpInit::Fold(Record *CurRec) const { ListInit *RHSs = dyn_cast<ListInit>(RHS); if (LHSs && RHSs) { SmallVector<Init *, 8> Args; - Args.insert(Args.end(), LHSs->begin(), LHSs->end()); - Args.insert(Args.end(), RHSs->begin(), RHSs->end()); + llvm::append_range(Args, *LHSs); + llvm::append_range(Args, *RHSs); return ListInit::get(Args, LHSs->getElementType()); } break; @@ -956,47 +982,76 @@ Init *BinOpInit::Fold(Record *CurRec) const { return ConcatStringInits(LHSs, RHSs); break; } + case INTERLEAVE: { + ListInit *List = dyn_cast<ListInit>(LHS); + StringInit *Delim = dyn_cast<StringInit>(RHS); + if (List && Delim) { + StringInit *Result; + if (isa<StringRecTy>(List->getElementType())) + Result = interleaveStringList(List, Delim); + else + Result = interleaveIntList(List, Delim); + if (Result) + return Result; + } + break; + } case EQ: case NE: case LE: case LT: case GE: case GT: { - // try to fold eq comparison for 'bit' and 'int', otherwise fallback - // to string objects. - IntInit *L = + // First see if we have two bit, bits, or int. + IntInit *LHSi = dyn_cast_or_null<IntInit>(LHS->convertInitializerTo(IntRecTy::get())); - IntInit *R = + IntInit *RHSi = dyn_cast_or_null<IntInit>(RHS->convertInitializerTo(IntRecTy::get())); - if (L && R) { + if (LHSi && RHSi) { bool Result; switch (getOpcode()) { - case EQ: Result = L->getValue() == R->getValue(); break; - case NE: Result = L->getValue() != R->getValue(); break; - case LE: Result = L->getValue() <= R->getValue(); break; - case LT: Result = L->getValue() < R->getValue(); break; - case GE: Result = L->getValue() >= R->getValue(); break; - case GT: Result = L->getValue() > R->getValue(); break; + case EQ: Result = LHSi->getValue() == RHSi->getValue(); break; + case NE: Result = LHSi->getValue() != RHSi->getValue(); break; + case LE: Result = LHSi->getValue() <= RHSi->getValue(); break; + case LT: Result = LHSi->getValue() < RHSi->getValue(); break; + case GE: Result = LHSi->getValue() >= RHSi->getValue(); break; + case GT: Result = LHSi->getValue() > RHSi->getValue(); break; default: llvm_unreachable("unhandled comparison"); } return BitInit::get(Result); } - if (getOpcode() == EQ || getOpcode() == NE) { - StringInit *LHSs = dyn_cast<StringInit>(LHS); - StringInit *RHSs = dyn_cast<StringInit>(RHS); + // Next try strings. + StringInit *LHSs = dyn_cast<StringInit>(LHS); + StringInit *RHSs = dyn_cast<StringInit>(RHS); - // Make sure we've resolved - if (LHSs && RHSs) { - bool Equal = LHSs->getValue() == RHSs->getValue(); - return BitInit::get(getOpcode() == EQ ? Equal : !Equal); + if (LHSs && RHSs) { + bool Result; + switch (getOpcode()) { + case EQ: Result = LHSs->getValue() == RHSs->getValue(); break; + case NE: Result = LHSs->getValue() != RHSs->getValue(); break; + case LE: Result = LHSs->getValue() <= RHSs->getValue(); break; + case LT: Result = LHSs->getValue() < RHSs->getValue(); break; + case GE: Result = LHSs->getValue() >= RHSs->getValue(); break; + case GT: Result = LHSs->getValue() > RHSs->getValue(); break; + default: llvm_unreachable("unhandled comparison"); } + return BitInit::get(Result); + } + + // Finally, !eq and !ne can be used with records. + if (getOpcode() == EQ || getOpcode() == NE) { + DefInit *LHSd = dyn_cast<DefInit>(LHS); + DefInit *RHSd = dyn_cast<DefInit>(RHS); + if (LHSd && RHSd) + return BitInit::get((getOpcode() == EQ) ? LHSd == RHSd + : LHSd != RHSd); } break; } - case SETOP: { + case SETDAGOP: { DagInit *Dag = dyn_cast<DagInit>(LHS); DefInit *Op = dyn_cast<DefInit>(RHS); if (Dag && Op) { @@ -1011,9 +1066,11 @@ Init *BinOpInit::Fold(Record *CurRec) const { break; } case ADD: + case SUB: case MUL: case AND: case OR: + case XOR: case SHL: case SRA: case SRL: { @@ -1026,10 +1083,12 @@ Init *BinOpInit::Fold(Record *CurRec) const { int64_t Result; switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); - case ADD: Result = LHSv + RHSv; break; - case MUL: Result = LHSv * RHSv; break; - case AND: Result = LHSv & RHSv; break; - case OR: Result = LHSv | RHSv; break; + case ADD: Result = LHSv + RHSv; break; + case SUB: Result = LHSv - RHSv; break; + case MUL: Result = LHSv * RHSv; break; + case AND: Result = LHSv & RHSv; break; + case OR: Result = LHSv | RHSv; break; + case XOR: Result = LHSv ^ RHSv; break; case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; case SRA: Result = LHSv >> RHSv; break; case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; @@ -1057,9 +1116,11 @@ std::string BinOpInit::getAsString() const { switch (getOpcode()) { case CONCAT: Result = "!con"; break; case ADD: Result = "!add"; break; + case SUB: Result = "!sub"; break; case MUL: Result = "!mul"; break; case AND: Result = "!and"; break; case OR: Result = "!or"; break; + case XOR: Result = "!xor"; break; case SHL: Result = "!shl"; break; case SRA: Result = "!sra"; break; case SRL: Result = "!srl"; break; @@ -1072,7 +1133,8 @@ std::string BinOpInit::getAsString() const { case LISTCONCAT: Result = "!listconcat"; break; case LISTSPLAT: Result = "!listsplat"; break; case STRCONCAT: Result = "!strconcat"; break; - case SETOP: Result = "!setop"; break; + case INTERLEAVE: Result = "!interleave"; break; + case SETDAGOP: Result = "!setdagop"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; } @@ -1107,7 +1169,7 @@ void TernOpInit::Profile(FoldingSetNodeID &ID) const { ProfileTernOpInit(ID, getOpcode(), getLHS(), getMHS(), getRHS(), getType()); } -static Init *ForeachApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) { +static Init *ItemApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) { MapResolver R(CurRec); R.set(LHS, MHSe); return RHS->resolveReferences(R); @@ -1116,7 +1178,7 @@ static Init *ForeachApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) { static Init *ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS, Record *CurRec) { bool Change = false; - Init *Val = ForeachApply(LHS, MHSd->getOperator(), RHS, CurRec); + Init *Val = ItemApply(LHS, MHSd->getOperator(), RHS, CurRec); if (Val != MHSd->getOperator()) Change = true; @@ -1129,7 +1191,7 @@ static Init *ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS, if (DagInit *Argd = dyn_cast<DagInit>(Arg)) NewArg = ForeachDagApply(LHS, Argd, RHS, CurRec); else - NewArg = ForeachApply(LHS, Arg, RHS, CurRec); + NewArg = ItemApply(LHS, Arg, RHS, CurRec); NewArgs.push_back(std::make_pair(NewArg, ArgName)); if (Arg != NewArg) @@ -1151,7 +1213,7 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, SmallVector<Init *, 8> NewList(MHSl->begin(), MHSl->end()); for (Init *&Item : NewList) { - Init *NewItem = ForeachApply(LHS, Item, RHS, CurRec); + Init *NewItem = ItemApply(LHS, Item, RHS, CurRec); if (NewItem != Item) Item = NewItem; } @@ -1161,6 +1223,31 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, return nullptr; } +// Evaluates RHS for all elements of MHS, using LHS as a temp variable. +// Creates a new list with the elements that evaluated to true. +static Init *FilterHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, + Record *CurRec) { + if (ListInit *MHSl = dyn_cast<ListInit>(MHS)) { + SmallVector<Init *, 8> NewList; + + for (Init *Item : MHSl->getValues()) { + Init *Include = ItemApply(LHS, Item, RHS, CurRec); + if (!Include) + return nullptr; + if (IntInit *IncludeInt = dyn_cast_or_null<IntInit>( + Include->convertInitializerTo(IntRecTy::get()))) { + if (IncludeInt->getValue()) + NewList.push_back(Item); + } else { + return nullptr; + } + } + return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType()); + } + + return nullptr; +} + Init *TernOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case SUBST: { @@ -1213,6 +1300,12 @@ Init *TernOpInit::Fold(Record *CurRec) const { break; } + case FILTER: { + if (Init *Result = FilterHelper(LHS, MHS, RHS, getType(), CurRec)) + return Result; + break; + } + case IF: { if (IntInit *LHSi = dyn_cast_or_null<IntInit>( LHS->convertInitializerTo(IntRecTy::get()))) { @@ -1246,6 +1339,27 @@ Init *TernOpInit::Fold(Record *CurRec) const { } break; } + + case SUBSTR: { + StringInit *LHSs = dyn_cast<StringInit>(LHS); + IntInit *MHSi = dyn_cast<IntInit>(MHS); + IntInit *RHSi = dyn_cast<IntInit>(RHS); + if (LHSs && MHSi && RHSi) { + int64_t StringSize = LHSs->getValue().size(); + int64_t Start = MHSi->getValue(); + int64_t Length = RHSi->getValue(); + if (Start < 0 || Start > StringSize) + PrintError(CurRec->getLoc(), + Twine("!substr start position is out of range 0...") + + std::to_string(StringSize) + ": " + + std::to_string(Start)); + if (Length < 0) + PrintError(CurRec->getLoc(), "!substr length must be nonnegative"); + return StringInit::get(LHSs->getValue().substr(Start, Length), + LHSs->getFormat()); + } + break; + } } return const_cast<TernOpInit *>(this); @@ -1267,7 +1381,7 @@ Init *TernOpInit::resolveReferences(Resolver &R) const { Init *mhs = MHS->resolveReferences(R); Init *rhs; - if (getOpcode() == FOREACH) { + if (getOpcode() == FOREACH || getOpcode() == FILTER) { ShadowResolver SR(R); SR.addShadow(lhs); rhs = RHS->resolveReferences(SR); @@ -1285,10 +1399,12 @@ std::string TernOpInit::getAsString() const { std::string Result; bool UnquotedLHS = false; switch (getOpcode()) { - case SUBST: Result = "!subst"; break; + case DAG: Result = "!dag"; break; + case FILTER: Result = "!filter"; UnquotedLHS = true; break; case FOREACH: Result = "!foreach"; UnquotedLHS = true; break; case IF: Result = "!if"; break; - case DAG: Result = "!dag"; break; + case SUBST: Result = "!subst"; break; + case SUBSTR: Result = "!substr"; break; } return (Result + "(" + (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) + @@ -2026,8 +2142,16 @@ std::string DagInit::getAsString() const { // Other implementations //===----------------------------------------------------------------------===// -RecordVal::RecordVal(Init *N, RecTy *T, bool P) - : Name(N), TyAndPrefix(T, P) { +RecordVal::RecordVal(Init *N, RecTy *T, FieldKind K) + : Name(N), TyAndKind(T, K) { + setValue(UnsetInit::get()); + assert(Value && "Cannot create unset value for current type!"); +} + +// This constructor accepts the same arguments as the above, but also +// a source location. +RecordVal::RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K) + : Name(N), Loc(Loc), TyAndKind(T, K) { setValue(UnsetInit::get()); assert(Value && "Cannot create unset value for current type!"); } @@ -2036,6 +2160,21 @@ StringRef RecordVal::getName() const { return cast<StringInit>(getNameInit())->getValue(); } +std::string RecordVal::getPrintType() const { + if (getType() == StringRecTy::get()) { + if (auto *StrInit = dyn_cast<StringInit>(Value)) { + if (StrInit->hasCodeFormat()) + return "code"; + else + return "string"; + } else { + return "string"; + } + } else { + return TyAndKind.getPointer()->getAsString(); + } +} + bool RecordVal::setValue(Init *V) { if (V) { Value = V->getCastTo(getType()); @@ -2046,8 +2185,33 @@ bool RecordVal::setValue(Init *V) { if (!isa<BitsInit>(Value)) { SmallVector<Init *, 64> Bits; Bits.reserve(BTy->getNumBits()); - for (unsigned i = 0, e = BTy->getNumBits(); i < e; ++i) - Bits.push_back(Value->getBit(i)); + for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) + Bits.push_back(Value->getBit(I)); + Value = BitsInit::get(Bits); + } + } + } + return Value == nullptr; + } + Value = nullptr; + return false; +} + +// This version of setValue takes a source location and resets the +// location in the RecordVal. +bool RecordVal::setValue(Init *V, SMLoc NewLoc) { + Loc = NewLoc; + if (V) { + Value = V->getCastTo(getType()); + if (Value) { + assert(!isa<TypedInit>(Value) || + cast<TypedInit>(Value)->getType()->typeIsA(getType())); + if (BitsRecTy *BTy = dyn_cast<BitsRecTy>(getType())) { + if (!isa<BitsInit>(Value)) { + SmallVector<Init *, 64> Bits; + Bits.reserve(BTy->getNumBits()); + for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) + Bits.push_back(Value->getBit(I)); Value = BitsInit::get(Bits); } } @@ -2058,13 +2222,14 @@ bool RecordVal::setValue(Init *V) { return false; } +#include "llvm/TableGen/Record.h" #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; } #endif void RecordVal::print(raw_ostream &OS, bool PrintSem) const { - if (getPrefix()) OS << "field "; - OS << *getType() << " " << getNameInitAsString(); + if (isNonconcreteOK()) OS << "field "; + OS << getPrintType() << " " << getNameInitAsString(); if (getValue()) OS << " = " << *getValue(); @@ -2089,9 +2254,9 @@ RecordRecTy *Record::getType() { } DefInit *Record::getDefInit() { - if (!TheInit) - TheInit = new(Allocator) DefInit(this); - return TheInit; + if (!CorrespondingDefInit) + CorrespondingDefInit = new (Allocator) DefInit(this); + return CorrespondingDefInit; } void Record::setName(Init *NewName) { @@ -2110,11 +2275,28 @@ void Record::setName(Init *NewName) { // this. See TGParser::ParseDef and TGParser::ParseDefm. } +// NOTE for the next two functions: +// Superclasses are in post-order, so the final one is a direct +// superclass. All of its transitive superclases immediately precede it, +// so we can step through the direct superclasses in reverse order. + +bool Record::hasDirectSuperClass(const Record *Superclass) const { + ArrayRef<std::pair<Record *, SMRange>> SCs = getSuperClasses(); + + for (int I = SCs.size() - 1; I >= 0; --I) { + const Record *SC = SCs[I].first; + if (SC == Superclass) + return true; + I -= SC->getSuperClasses().size(); + } + + return false; +} + void Record::getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const { ArrayRef<std::pair<Record *, SMRange>> SCs = getSuperClasses(); + while (!SCs.empty()) { - // Superclasses are in reverse preorder, so 'back' is a direct superclass, - // and its transitive superclasses are directly preceding it. Record *SC = SCs.back().first; SCs = SCs.drop_back(1 + SC->getSuperClasses().size()); Classes.push_back(SC); @@ -2187,15 +2369,23 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { OS << "\n"; for (const RecordVal &Val : R.getValues()) - if (Val.getPrefix() && !R.isTemplateArg(Val.getNameInit())) + if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit())) OS << Val; for (const RecordVal &Val : R.getValues()) - if (!Val.getPrefix() && !R.isTemplateArg(Val.getNameInit())) + if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit())) OS << Val; return OS << "}\n"; } +SMLoc Record::getFieldLoc(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (!R) + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName + "'!\n"); + return R->getLoc(); +} + Init *Record::getValueInit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (!R || !R->getValue()) @@ -2205,18 +2395,27 @@ Init *Record::getValueInit(StringRef FieldName) const { } StringRef Record::getValueAsString(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (!R || !R->getValue()) + llvm::Optional<StringRef> S = getValueAsOptionalString(FieldName); + if (!S.hasValue()) PrintFatalError(getLoc(), "Record `" + getName() + "' does not have a field named `" + FieldName + "'!\n"); + return S.getValue(); +} + +llvm::Optional<StringRef> +Record::getValueAsOptionalString(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (!R || !R->getValue()) + return llvm::Optional<StringRef>(); + if (isa<UnsetInit>(R->getValue())) + return llvm::Optional<StringRef>(); if (StringInit *SI = dyn_cast<StringInit>(R->getValue())) return SI->getValue(); - if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue())) - return CI->getValue(); - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a string initializer!"); + PrintFatalError(getLoc(), + "Record `" + getName() + "', ` field `" + FieldName + + "' exists but does not have a string initializer!"); } BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { @@ -2227,8 +2426,8 @@ BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue())) return BI; - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a BitsInit initializer!"); + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a bits value"); } ListInit *Record::getValueAsListInit(StringRef FieldName) const { @@ -2239,8 +2438,8 @@ ListInit *Record::getValueAsListInit(StringRef FieldName) const { if (ListInit *LI = dyn_cast<ListInit>(R->getValue())) return LI; - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a list initializer!"); + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a list value"); } std::vector<Record*> @@ -2267,7 +2466,7 @@ int64_t Record::getValueAsInt(StringRef FieldName) const { return II->getValue(); PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have an int initializer: " + + "' exists but does not have an int value: " + R->getValue()->getAsString()); } @@ -2281,7 +2480,7 @@ Record::getValueAsListOfInts(StringRef FieldName) const { else PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have a list of ints initializer: " + + "' exists but does not have a list of ints value: " + I->getAsString()); } return Ints; @@ -2294,12 +2493,10 @@ Record::getValueAsListOfStrings(StringRef FieldName) const { for (Init *I : List->getValues()) { if (StringInit *SI = dyn_cast<StringInit>(I)) Strings.push_back(SI->getValue()); - else if (CodeInit *CI = dyn_cast<CodeInit>(I)) - Strings.push_back(CI->getValue()); else PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have a list of strings initializer: " + + "' exists but does not have a list of strings value: " + I->getAsString()); } return Strings; @@ -2394,16 +2591,78 @@ Init *RecordKeeper::getNewAnonymousName() { return StringInit::get("anonymous_" + utostr(AnonCounter++)); } -std::vector<Record *> -RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const { - Record *Class = getClass(ClassName); - if (!Class) - PrintFatalError("ERROR: Couldn't find the `" + ClassName + "' class!\n"); +// These functions implement the phase timing facility. Starting a timer +// when one is already running stops the running one. - std::vector<Record*> Defs; - for (const auto &D : getDefs()) - if (D.second->isSubClassOf(Class)) - Defs.push_back(D.second.get()); +void RecordKeeper::startTimer(StringRef Name) { + if (TimingGroup) { + if (LastTimer && LastTimer->isRunning()) { + LastTimer->stopTimer(); + if (BackendTimer) { + LastTimer->clear(); + BackendTimer = false; + } + } + + LastTimer = new Timer("", Name, *TimingGroup); + LastTimer->startTimer(); + } +} + +void RecordKeeper::stopTimer() { + if (TimingGroup) { + assert(LastTimer && "No phase timer was started"); + LastTimer->stopTimer(); + } +} + +void RecordKeeper::startBackendTimer(StringRef Name) { + if (TimingGroup) { + startTimer(Name); + BackendTimer = true; + } +} + +void RecordKeeper::stopBackendTimer() { + if (TimingGroup) { + if (BackendTimer) { + stopTimer(); + BackendTimer = false; + } + } +} + +// We cache the record vectors for single classes. Many backends request +// the same vectors multiple times. +std::vector<Record *> RecordKeeper::getAllDerivedDefinitions( + StringRef ClassName) const { + + auto Pair = ClassRecordsMap.try_emplace(ClassName); + if (Pair.second) + Pair.first->second = getAllDerivedDefinitions(makeArrayRef(ClassName)); + + return Pair.first->second; +} + +std::vector<Record *> RecordKeeper::getAllDerivedDefinitions( + ArrayRef<StringRef> ClassNames) const { + SmallVector<Record *, 2> ClassRecs; + std::vector<Record *> Defs; + + assert(ClassNames.size() > 0 && "At least one class must be passed."); + for (const auto &ClassName : ClassNames) { + Record *Class = getClass(ClassName); + if (!Class) + PrintFatalError("The class '" + ClassName + "' is not defined\n"); + ClassRecs.push_back(Class); + } + + for (const auto &OneDef : getDefs()) { + if (all_of(ClassRecs, [&OneDef](const Record *Class) { + return OneDef.second->isSubClassOf(Class); + })) + Defs.push_back(OneDef.second.get()); + } return Defs; } |