diff options
author | Craig Topper <craig.topper@gmail.com> | 2017-05-27 17:36:50 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@gmail.com> | 2017-05-27 17:36:50 +0000 |
commit | 67886788e22447032d6396589dc5f895e2ebe108 (patch) | |
tree | abbbd2a85ec8a497f8ebc3f5d09cd5cb0f01bd07 | |
parent | 8e1db259e8606ac91d37266e5561a85a7d1823bd (diff) |
[TableGen] Prevent DagInit from leaking its Args and ArgNames when they exceed the size of the SmallVector.
DagInits are allocated in a BumpPtrAllocator so they are never destructed. This means the destructor for the SmallVector never runs.
To fix this we now allocate the vectors in the BumpPtrAllocator too using TrailingObjects.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304077 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/TableGen/Record.h | 46 | ||||
-rw-r--r-- | lib/TableGen/Record.cpp | 27 |
2 files changed, 42 insertions, 31 deletions
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index ced21c2efb2..d14a56cb87e 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1137,17 +1137,19 @@ public: /// to have at least one value then a (possibly empty) list of arguments. Each /// argument can have a name associated with it. /// -class DagInit : public TypedInit, public FoldingSetNode { +class DagInit final : public TypedInit, public FoldingSetNode, + public TrailingObjects<DagInit, Init *, StringInit *> { Init *Val; StringInit *ValName; - SmallVector<Init*, 4> Args; - SmallVector<StringInit*, 4> ArgNames; + unsigned NumArgs; + unsigned NumArgNames; - DagInit(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange, - ArrayRef<StringInit *> NameRange) + DagInit(Init *V, StringInit *VN, unsigned NumArgs, unsigned NumArgNames) : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN), - Args(ArgRange.begin(), ArgRange.end()), - ArgNames(NameRange.begin(), NameRange.end()) {} + NumArgs(NumArgs), NumArgNames(NumArgNames) {} + + friend TrailingObjects; + size_t numTrailingObjects(OverloadToken<Init *>) const { return NumArgs; } public: DagInit(const DagInit &Other) = delete; @@ -1173,20 +1175,24 @@ public: return ValName ? ValName->getValue() : StringRef(); } - unsigned getNumArgs() const { return Args.size(); } + unsigned getNumArgs() const { return NumArgs; } Init *getArg(unsigned Num) const { - assert(Num < Args.size() && "Arg number out of range!"); - return Args[Num]; + assert(Num < NumArgs && "Arg number out of range!"); + return getTrailingObjects<Init *>()[Num]; } StringInit *getArgName(unsigned Num) const { - assert(Num < ArgNames.size() && "Arg number out of range!"); - return ArgNames[Num]; + assert(Num < NumArgNames && "Arg number out of range!"); + return getTrailingObjects<StringInit *>()[Num]; } StringRef getArgNameStr(unsigned Num) const { StringInit *Init = getArgName(Num); return Init ? Init->getValue() : StringRef(); } + ArrayRef<StringInit *> getArgNames() const { + return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames); + } + Init *resolveReferences(Record &R, const RecordVal *RV) const override; std::string getAsString() const override; @@ -1194,20 +1200,20 @@ public: typedef SmallVectorImpl<Init*>::const_iterator const_arg_iterator; typedef SmallVectorImpl<StringInit*>::const_iterator const_name_iterator; - inline const_arg_iterator arg_begin() const { return Args.begin(); } - inline const_arg_iterator arg_end () const { return Args.end(); } + inline const_arg_iterator arg_begin() const { return getTrailingObjects<Init *>(); } + inline const_arg_iterator arg_end () const { return arg_begin() + NumArgs; } inline iterator_range<const_arg_iterator> args() const { return llvm::make_range(arg_begin(), arg_end()); } - inline size_t arg_size () const { return Args.size(); } - inline bool arg_empty() const { return Args.empty(); } + inline size_t arg_size () const { return NumArgs; } + inline bool arg_empty() const { return NumArgs == 0; } - inline const_name_iterator name_begin() const { return ArgNames.begin(); } - inline const_name_iterator name_end () const { return ArgNames.end(); } + inline const_name_iterator name_begin() const { return getTrailingObjects<StringInit *>(); } + inline const_name_iterator name_end () const { return name_begin() + NumArgNames; } - inline size_t name_size () const { return ArgNames.size(); } - inline bool name_empty() const { return ArgNames.empty(); } + inline size_t name_size () const { return NumArgNames; } + inline bool name_empty() const { return NumArgNames == 0; } Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off dag"); diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 3bd0db6c96b..09f9759ce7d 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -1501,7 +1501,12 @@ DagInit::get(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange, if (DagInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) return I; - DagInit *I = new(Allocator) DagInit(V, VN, ArgRange, NameRange); + void *Mem = Allocator.Allocate(totalSizeToAlloc<Init *, StringInit *>(ArgRange.size(), NameRange.size()), alignof(BitsInit)); + DagInit *I = new(Mem) DagInit(V, VN, ArgRange.size(), NameRange.size()); + std::uninitialized_copy(ArgRange.begin(), ArgRange.end(), + I->getTrailingObjects<Init *>()); + std::uninitialized_copy(NameRange.begin(), NameRange.end(), + I->getTrailingObjects<StringInit *>()); ThePool.InsertNode(I, IP); return I; } @@ -1521,7 +1526,7 @@ DagInit::get(Init *V, StringInit *VN, } void DagInit::Profile(FoldingSetNodeID &ID) const { - ProfileDagInit(ID, Val, ValName, Args, ArgNames); + ProfileDagInit(ID, Val, ValName, makeArrayRef(getTrailingObjects<Init *>(), NumArgs), makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames)); } Init *DagInit::convertInitializerTo(RecTy *Ty) const { @@ -1533,9 +1538,9 @@ Init *DagInit::convertInitializerTo(RecTy *Ty) const { Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { SmallVector<Init*, 8> NewArgs; - NewArgs.reserve(Args.size()); + NewArgs.reserve(arg_size()); bool ArgsChanged = false; - for (const Init *Arg : Args) { + for (const Init *Arg : args()) { Init *NewArg = Arg->resolveReferences(R, RV); NewArgs.push_back(NewArg); ArgsChanged |= NewArg != Arg; @@ -1543,7 +1548,7 @@ Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { Init *Op = Val->resolveReferences(R, RV); if (Op != Val || ArgsChanged) - return DagInit::get(Op, ValName, NewArgs, ArgNames); + return DagInit::get(Op, ValName, NewArgs, getArgNames()); return const_cast<DagInit *>(this); } @@ -1552,12 +1557,12 @@ std::string DagInit::getAsString() const { std::string Result = "(" + Val->getAsString(); if (ValName) Result += ":" + ValName->getAsUnquotedString(); - if (!Args.empty()) { - Result += " " + Args[0]->getAsString(); - if (ArgNames[0]) Result += ":$" + ArgNames[0]->getAsUnquotedString(); - for (unsigned i = 1, e = Args.size(); i != e; ++i) { - Result += ", " + Args[i]->getAsString(); - if (ArgNames[i]) Result += ":$" + ArgNames[i]->getAsUnquotedString(); + if (!arg_empty()) { + Result += " " + getArg(0)->getAsString(); + if (getArgName(0)) Result += ":$" + getArgName(0)->getAsUnquotedString(); + for (unsigned i = 1, e = getNumArgs(); i != e; ++i) { + Result += ", " + getArg(i)->getAsString(); + if (getArgName(i)) Result += ":$" + getArgName(i)->getAsUnquotedString(); } } return Result + ")"; |