diff options
Diffstat (limited to 'llvm/lib/TableGen/Record.cpp')
| -rw-r--r-- | llvm/lib/TableGen/Record.cpp | 138 |
1 files changed, 115 insertions, 23 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index b6c6b8f031d3..8663863d968f 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -502,6 +502,28 @@ IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { return BitsInit::get(NewBits); } +AnonymousNameInit *AnonymousNameInit::get(unsigned V) { + return new (Allocator) AnonymousNameInit(V); +} + +StringInit *AnonymousNameInit::getNameInit() const { + return StringInit::get(getAsString()); +} + +std::string AnonymousNameInit::getAsString() const { + return "anonymous_" + utostr(Value); +} + +Init *AnonymousNameInit::resolveReferences(Resolver &R) const { + auto *Old = const_cast<Init *>(static_cast<const Init *>(this)); + auto *New = R.resolve(Old); + New = New ? New : Old; + if (R.isFinal()) + if (auto *Anonymous = dyn_cast<AnonymousNameInit>(New)) + return Anonymous->getNameInit(); + return New; +} + StringInit *StringInit::get(StringRef V, StringFormat Fmt) { static StringMap<StringInit*, BumpPtrAllocator &> StringPool(Allocator); static StringMap<StringInit*, BumpPtrAllocator &> CodePool(Allocator); @@ -593,6 +615,12 @@ Init *ListInit::convertInitializerTo(RecTy *Ty) const { } Init *ListInit::convertInitListSlice(ArrayRef<unsigned> Elements) const { + if (Elements.size() == 1) { + if (Elements[0] >= size()) + return nullptr; + return getElement(Elements[0]); + } + SmallVector<Init*, 8> Vals; Vals.reserve(Elements.size()); for (unsigned Element : Elements) { @@ -627,6 +655,14 @@ Init *ListInit::resolveReferences(Resolver &R) const { return const_cast<ListInit *>(this); } +bool ListInit::isComplete() const { + for (Init *Element : *this) { + if (!Element->isComplete()) + return false; + } + return true; +} + bool ListInit::isConcrete() const { for (Init *Element : *this) { if (!Element->isConcrete()) @@ -701,7 +737,9 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { // Self-references are allowed, but their resolution is delayed until // the final resolve to ensure that we get the correct type for them. - if (Name == CurRec->getNameInit()) { + auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->getNameInit()); + if (Name == CurRec->getNameInit() || + (Anonymous && Name == Anonymous->getNameInit())) { if (!IsFinal) break; D = CurRec; @@ -1360,6 +1398,26 @@ Init *TernOpInit::Fold(Record *CurRec) const { } break; } + + case FIND: { + StringInit *LHSs = dyn_cast<StringInit>(LHS); + StringInit *MHSs = dyn_cast<StringInit>(MHS); + IntInit *RHSi = dyn_cast<IntInit>(RHS); + if (LHSs && MHSs && RHSi) { + int64_t SourceSize = LHSs->getValue().size(); + int64_t Start = RHSi->getValue(); + if (Start < 0 || Start > SourceSize) + PrintError(CurRec->getLoc(), + Twine("!find start position is out of range 0...") + + std::to_string(SourceSize) + ": " + + std::to_string(Start)); + auto I = LHSs->getValue().find(MHSs->getValue(), Start); + if (I == std::string::npos) + return IntInit::get(-1); + return IntInit::get(I); + } + break; + } } return const_cast<TernOpInit *>(this); @@ -1405,15 +1463,15 @@ std::string TernOpInit::getAsString() const { case IF: Result = "!if"; break; case SUBST: Result = "!subst"; break; case SUBSTR: Result = "!substr"; break; + case FIND: Result = "!find"; break; } return (Result + "(" + (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) + ", " + MHS->getAsString() + ", " + RHS->getAsString() + ")"); } -static void ProfileFoldOpInit(FoldingSetNodeID &ID, Init *A, Init *B, - Init *Start, Init *List, Init *Expr, - RecTy *Type) { +static void ProfileFoldOpInit(FoldingSetNodeID &ID, Init *Start, Init *List, + Init *A, Init *B, Init *Expr, RecTy *Type) { ID.AddPointer(Start); ID.AddPointer(List); ID.AddPointer(A); @@ -1776,6 +1834,9 @@ DefInit *VarDefInit::instantiate() { for (const RecordVal &Val : Class->getValues()) NewRec->addValue(Val); + // Copy assertions from class to instance. + NewRec->appendAssertions(Class); + // Substitute and resolve template arguments ArrayRef<Init *> TArgs = Class->getTemplateArgs(); MapResolver R(NewRec); @@ -1804,6 +1865,9 @@ DefInit *VarDefInit::instantiate() { NewRec->resolveReferences(); Records.addDef(std::move(NewRecOwner)); + // Check the assertions. + NewRec->checkRecordAssertions(); + Def = DefInit::get(NewRec); } @@ -1888,7 +1952,7 @@ Init *FieldInit::Fold(Record *CurRec) const { FieldName->getAsUnquotedString() + "' of '" + Rec->getAsString() + "' is a forbidden self-reference"); Init *FieldVal = Def->getValue(FieldName)->getValue(); - if (FieldVal->isComplete()) + if (FieldVal->isConcrete()) return FieldVal; } return const_cast<FieldInit *>(this); @@ -2304,6 +2368,14 @@ void Record::getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const { } void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { + Init *OldName = getNameInit(); + Init *NewName = Name->resolveReferences(R); + if (NewName != OldName) { + // Re-register with RecordKeeper. + setName(NewName); + } + + // Resolve the field values. for (RecordVal &Value : Values) { if (SkipVal == &Value) // Skip resolve the same field as the given one continue; @@ -2314,26 +2386,29 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { if (TypedInit *VRT = dyn_cast<TypedInit>(VR)) Type = (Twine("of type '") + VRT->getType()->getAsString() + "' ").str(); - PrintFatalError(getLoc(), Twine("Invalid value ") + Type + - "is found when setting '" + - Value.getNameInitAsString() + - "' of type '" + - Value.getType()->getAsString() + - "' after resolving references: " + - VR->getAsUnquotedString() + "\n"); + PrintFatalError( + getLoc(), + Twine("Invalid value ") + Type + "found when setting field '" + + Value.getNameInitAsString() + "' of type '" + + Value.getType()->getAsString() + + "' after resolving references: " + VR->getAsUnquotedString() + + "\n"); } } } - Init *OldName = getNameInit(); - Init *NewName = Name->resolveReferences(R); - if (NewName != OldName) { - // Re-register with RecordKeeper. - setName(NewName); + + // Resolve the assertion expressions. + for (auto &Assertion : Assertions) { + Init *Value = Assertion.Condition->resolveReferences(R); + Assertion.Condition = Value; + Value = Assertion.Message->resolveReferences(R); + Assertion.Message = Value; } } -void Record::resolveReferences() { +void Record::resolveReferences(Init *NewName) { RecordResolver R(*this); + R.setName(NewName); R.setFinal(true); resolveReferences(R); } @@ -2570,6 +2645,21 @@ DagInit *Record::getValueAsDag(StringRef FieldName) const { FieldName + "' does not have a dag initializer!"); } +// Check all record assertions: For each one, resolve the condition +// and message, then call CheckAssert(). +// Note: The condition and message are probably already resolved, +// but resolving again allows calls before records are resolved. +void Record::checkRecordAssertions() { + RecordResolver R(*this); + R.setFinal(true); + + for (auto Assertion : getAssertions()) { + Init *Condition = Assertion.Condition->resolveReferences(R); + Init *Message = Assertion.Message->resolveReferences(R); + CheckAssert(Assertion.Loc, Condition, Message); + } +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void RecordKeeper::dump() const { errs() << *this; } #endif @@ -2588,7 +2678,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { /// GetNewAnonymousName - Generate a unique anonymous name that can be used as /// an identifier. Init *RecordKeeper::getNewAnonymousName() { - return StringInit::get("anonymous_" + utostr(AnonCounter++)); + return AnonymousNameInit::get(AnonCounter++); } // These functions implement the phase timing facility. Starting a timer @@ -2690,10 +2780,8 @@ Init *RecordResolver::resolve(Init *VarName) { if (Val) return Val; - for (Init *S : Stack) { - if (S == VarName) - return nullptr; // prevent infinite recursion - } + if (llvm::is_contained(Stack, VarName)) + return nullptr; // prevent infinite recursion if (RecordVal *RV = getCurrentRecord()->getValue(VarName)) { if (!isa<UnsetInit>(RV->getValue())) { @@ -2702,6 +2790,10 @@ Init *RecordResolver::resolve(Init *VarName) { Val = Val->resolveReferences(*this); Stack.pop_back(); } + } else if (Name && VarName == getCurrentRecord()->getNameInit()) { + Stack.push_back(VarName); + Val = Name->resolveReferences(*this); + Stack.pop_back(); } Cache[VarName] = Val; |
