Răsfoiți Sursa

Convert more mallocs/frees to news/deletes (#2157)

This change replaces more malloc/calloc/realloc/free calls to new/delete. This creates several new out of memory exception paths (especially due to changing MallocAllocator) which exposed many memory mismanagement bugs that I found using the OOM test. Hence this grew to be a pretty big change.
Tristan Labelle 6 ani în urmă
părinte
comite
e4ceb30434

+ 6 - 3
include/llvm/ADT/SparseMultiSet.h

@@ -190,7 +190,7 @@ public:
   SparseMultiSet()
   SparseMultiSet()
     : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {}
     : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {}
 
 
-  ~SparseMultiSet() { free(Sparse); }
+  ~SparseMultiSet() { delete[] Sparse; } // HLSL Change: Use overridable operator new
 
 
   /// Set the universe size which determines the largest key the set can hold.
   /// Set the universe size which determines the largest key the set can hold.
   /// The universe must be sized before any elements can be added.
   /// The universe must be sized before any elements can be added.
@@ -204,11 +204,14 @@ public:
     // Hysteresis prevents needless reallocations.
     // Hysteresis prevents needless reallocations.
     if (U >= Universe/4 && U <= Universe)
     if (U >= Universe/4 && U <= Universe)
       return;
       return;
-    free(Sparse);
+    // HLSL Change Begin: Use overridable operator new/delete
+    delete[] Sparse;
     // The Sparse array doesn't actually need to be initialized, so malloc
     // The Sparse array doesn't actually need to be initialized, so malloc
     // would be enough here, but that will cause tools like valgrind to
     // would be enough here, but that will cause tools like valgrind to
     // complain about branching on uninitialized data.
     // complain about branching on uninitialized data.
-    Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
+    Sparse = new SparseT[U];
+    std::memset(Sparse, 0, U * sizeof(SparseT));
+    // HLSL Change End
     Universe = U;
     Universe = U;
   }
   }
 
 

+ 6 - 3
include/llvm/ADT/SparseSet.h

@@ -144,7 +144,7 @@ public:
   typedef const ValueT *const_pointer;
   typedef const ValueT *const_pointer;
 
 
   SparseSet() : Sparse(nullptr), Universe(0) {}
   SparseSet() : Sparse(nullptr), Universe(0) {}
-  ~SparseSet() { free(Sparse); }
+  ~SparseSet() { delete[] Sparse; } // HLSL Change Begin: Use overridable operator delete
 
 
   /// setUniverse - Set the universe size which determines the largest key the
   /// setUniverse - Set the universe size which determines the largest key the
   /// set can hold.  The universe must be sized before any elements can be
   /// set can hold.  The universe must be sized before any elements can be
@@ -159,11 +159,14 @@ public:
     // Hysteresis prevents needless reallocations.
     // Hysteresis prevents needless reallocations.
     if (U >= Universe/4 && U <= Universe)
     if (U >= Universe/4 && U <= Universe)
       return;
       return;
-    free(Sparse);
+    // HLSL Change Begin: Use overridable operator new/delete
+    delete[] Sparse;
     // The Sparse array doesn't actually need to be initialized, so malloc
     // The Sparse array doesn't actually need to be initialized, so malloc
     // would be enough here, but that will cause tools like valgrind to
     // would be enough here, but that will cause tools like valgrind to
     // complain about branching on uninitialized data.
     // complain about branching on uninitialized data.
-    Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
+    Sparse = new SparseT[U];
+    std::memset(Sparse, 0, U * sizeof(SparseT));
+    // HLSL Change End
     Universe = U;
     Universe = U;
   }
   }
 
 

+ 1 - 1
include/llvm/ADT/StringMap.h

@@ -382,7 +382,7 @@ public:
         }
         }
       }
       }
     }
     }
-    free(TheTable);
+    ::operator delete(TheTable); // HLSL Change Begin: Use overridable operator delete
   }
   }
 };
 };
 
 

+ 15 - 1
include/llvm/ADT/ilist.h

@@ -420,7 +420,21 @@ public:
       Head = New;
       Head = New;
     this->setPrev(CurNode, New);
     this->setPrev(CurNode, New);
 
 
-    this->addNodeToList(New);  // Notify traits that we added a node...
+    // HLSL Change Begin: Undo insertion if exception
+    try {
+      this->addNodeToList(New);  // Notify traits that we added a node...
+    } catch (...) {
+      // Undo insertion
+      if (New == Head)
+        Head = CurNode;
+      else
+        this->setNext(PrevNode, CurNode);
+      this->setPrev(CurNode, PrevNode);
+      this->setPrev(New, nullptr);
+      this->setNext(New, nullptr);
+      throw;
+    }
+    // HLSL Change End
     return New;
     return New;
   }
   }
 
 

+ 1 - 1
include/llvm/CodeGen/RegisterPressure.h

@@ -146,7 +146,7 @@ class PressureDiffs {
   unsigned Max;
   unsigned Max;
 public:
 public:
   PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {}
   PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {}
-  ~PressureDiffs() { free(PDiffArray); }
+  ~PressureDiffs() { delete[] PDiffArray; } // HLSL Change: Use overridable operator delete
 
 
   void clear() { Size = 0; }
   void clear() { Size = 0; }
 
 

+ 1 - 1
include/llvm/IR/Function.h

@@ -66,7 +66,7 @@ private:
   // Important things that make up a function!
   // Important things that make up a function!
   BasicBlockListType  BasicBlocks;        ///< The basic blocks
   BasicBlockListType  BasicBlocks;        ///< The basic blocks
   mutable ArgumentListType ArgumentList;  ///< The formal arguments
   mutable ArgumentListType ArgumentList;  ///< The formal arguments
-  ValueSymbolTable *SymTab;               ///< Symbol table of args/instructions
+  std::unique_ptr<ValueSymbolTable> SymTab; ///< Symbol table of args/instructions // HLSL Change: use unique_ptr
   AttributeSet AttributeSets;             ///< Parameter attributes
   AttributeSet AttributeSets;             ///< Parameter attributes
   FunctionType *Ty;
   FunctionType *Ty;
 
 

+ 6 - 0
include/llvm/IR/GlobalVariable.h

@@ -51,6 +51,12 @@ public:
     return User::operator new(s, 1);
     return User::operator new(s, 1);
   }
   }
 
 
+  // HLSL Change Begin: Match operator new/delete
+  void operator delete(void* Ptr) {
+    User::operator delete(Ptr, 1);
+  }
+  // HLSL Change End
+
   /// GlobalVariable ctor - If a parent module is specified, the global is
   /// GlobalVariable ctor - If a parent module is specified, the global is
   /// automatically inserted into the end of the specified modules global list.
   /// automatically inserted into the end of the specified modules global list.
   GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage,
   GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage,

+ 3 - 6
include/llvm/Support/Allocator.h

@@ -93,18 +93,14 @@ public:
   _Ret_notnull_   // HLSL Change - SAL
   _Ret_notnull_   // HLSL Change - SAL
   LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
   LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
                                                 size_t /*Alignment*/) {
                                                 size_t /*Alignment*/) {
-    // HLSL Change Starts - throw on OOM
-    void* result = malloc(Size);
-    if (result == nullptr) throw std::bad_alloc();
-    return result;
-    // HLSL Change Ends - throw on OOM
+    return ::operator new(Size); // HLSL Change: use overridable operator new and throw on OOM
   }
   }
 
 
   // Pull in base class overloads.
   // Pull in base class overloads.
   using AllocatorBase<MallocAllocator>::Allocate;
   using AllocatorBase<MallocAllocator>::Allocate;
 
 
   void Deallocate(const void *Ptr, size_t /*Size*/) {
   void Deallocate(const void *Ptr, size_t /*Size*/) {
-    free(const_cast<void *>(Ptr));
+    ::operator delete(const_cast<void*>(Ptr)); // HLSL Change: use overridable operator delete
   }
   }
 
 
   // Pull in base class overloads.
   // Pull in base class overloads.
@@ -314,6 +310,7 @@ private:
   void StartNewSlab() {
   void StartNewSlab() {
     size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
     size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
 
 
+    Slabs.reserve(Slabs.size() + 1); // HLSL Change: Prevent leak on push_back exception
     void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
     void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
     Slabs.push_back(NewSlab);
     Slabs.push_back(NewSlab);
     CurPtr = (char *)(NewSlab);
     CurPtr = (char *)(NewSlab);

+ 10 - 6
include/llvm/Support/OnDiskHashTable.h

@@ -94,8 +94,10 @@ private:
 
 
   /// \brief Resize the hash table, moving the old entries into the new buckets.
   /// \brief Resize the hash table, moving the old entries into the new buckets.
   void resize(size_t NewSize) {
   void resize(size_t NewSize) {
-    Bucket *NewBuckets = (Bucket *)std::calloc(NewSize, sizeof(Bucket));
-    if (NewBuckets == nullptr) throw std::bad_alloc(); // HLSL Change
+    // HLSL Change Begin: Use overridable operator new
+    Bucket* NewBuckets = new Bucket[NewSize];
+    std::memset(NewBuckets, 0, NewSize * sizeof(Bucket));
+    // HLSL Change End
     // Populate NewBuckets with the old entries.
     // Populate NewBuckets with the old entries.
     for (size_t I = 0; I < NumBuckets; ++I)
     for (size_t I = 0; I < NumBuckets; ++I)
       for (Item *E = Buckets[I].Head; E;) {
       for (Item *E = Buckets[I].Head; E;) {
@@ -105,7 +107,7 @@ private:
         E = N;
         E = N;
       }
       }
 
 
-    free(Buckets);
+    delete[] Buckets; // HLSL Change: Use overridable operator delete
     NumBuckets = NewSize;
     NumBuckets = NewSize;
     Buckets = NewBuckets;
     Buckets = NewBuckets;
   }
   }
@@ -188,11 +190,13 @@ public:
     NumBuckets = 64;
     NumBuckets = 64;
     // Note that we do not need to run the constructors of the individual
     // Note that we do not need to run the constructors of the individual
     // Bucket objects since 'calloc' returns bytes that are all 0.
     // Bucket objects since 'calloc' returns bytes that are all 0.
-    Buckets = (Bucket *)std::calloc(NumBuckets, sizeof(Bucket));
-    if (Buckets == nullptr) throw std::bad_alloc(); // HLSL Change
+    // HLSL Change Begin: Use overridable operator new
+    Buckets = new Bucket[NumBuckets];
+    std::memset(Buckets, 0, NumBuckets * sizeof(Bucket));
+    // HLSL Change End
   }
   }
 
 
-  ~OnDiskChainedHashTableGenerator() { std::free(Buckets); }
+  ~OnDiskChainedHashTableGenerator() { delete[] Buckets; } // HLSL Change: Use overridable operator delete
 };
 };
 
 
 /// \brief Provides lookup on an on disk hash table.
 /// \brief Provides lookup on an on disk hash table.

+ 5 - 4
lib/CodeGen/InterferenceCache.cpp

@@ -34,11 +34,12 @@ const InterferenceCache::BlockInterference
 // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized.
 // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized.
 void InterferenceCache::reinitPhysRegEntries() {
 void InterferenceCache::reinitPhysRegEntries() {
   if (PhysRegEntriesCount == TRI->getNumRegs()) return;
   if (PhysRegEntriesCount == TRI->getNumRegs()) return;
-  free(PhysRegEntries);
+  delete[] PhysRegEntries; // HLSL Change: Use overridable operator delete
   PhysRegEntriesCount = TRI->getNumRegs();
   PhysRegEntriesCount = TRI->getNumRegs();
-  PhysRegEntries = (unsigned char*)
-    calloc(PhysRegEntriesCount, sizeof(unsigned char));
-  if (PhysRegEntries == nullptr) throw std::bad_alloc(); // HLSL Change
+  // HLSL Change Begin: Use overridable operator new
+  PhysRegEntries = new unsigned char[PhysRegEntriesCount];
+  std::memset(PhysRegEntries, 0, PhysRegEntriesCount);
+  // HLSL Change End
 }
 }
 
 
 void InterferenceCache::init(MachineFunction *mf,
 void InterferenceCache::init(MachineFunction *mf,

+ 1 - 1
lib/CodeGen/InterferenceCache.h

@@ -154,7 +154,7 @@ public:
       PhysRegEntriesCount(0), RoundRobin(0) {}
       PhysRegEntriesCount(0), RoundRobin(0) {}
 
 
   ~InterferenceCache() {
   ~InterferenceCache() {
-    free(PhysRegEntries);
+    delete[] PhysRegEntries; // HLSL Change: Use overridable operator delete
   }
   }
 
 
   void reinitPhysRegEntries();
   void reinitPhysRegEntries();

+ 5 - 3
lib/CodeGen/RegisterPressure.cpp

@@ -388,9 +388,11 @@ void PressureDiffs::init(unsigned N) {
     return;
     return;
   }
   }
   Max = Size;
   Max = Size;
-  free(PDiffArray);
-  PDiffArray = reinterpret_cast<PressureDiff*>(calloc(N, sizeof(PressureDiff)));
-  if (PDiffArray == nullptr) throw std::bad_alloc(); // HLSL Change
+  // HLSL Change Begin: Use overridable operator new/delete
+  delete[] PDiffArray;
+  PDiffArray = new PressureDiff[N];
+  std::memset(PDiffArray, 0, N * sizeof(PressureDiff));
+  // HLSL Change End
 }
 }
 
 
 /// Add a change in pressure to the pressure diff of a given instruction.
 /// Add a change in pressure to the pressure diff of a given instruction.

+ 7 - 1
lib/IR/BasicBlock.cpp

@@ -42,13 +42,19 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
                        BasicBlock *InsertBefore)
                        BasicBlock *InsertBefore)
   : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) {
   : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) {
 
 
+  // HLSL Change Begin
+  // Do everything that can throw before inserting into the
+  // linked list, which takes ownership of this object on success.
+  setName(Name);
+  // HLSL Change End
+
   if (NewParent)
   if (NewParent)
     insertInto(NewParent, InsertBefore);
     insertInto(NewParent, InsertBefore);
   else
   else
     assert(!InsertBefore &&
     assert(!InsertBefore &&
            "Cannot insert block before another block with no function!");
            "Cannot insert block before another block with no function!");
 
 
-  setName(Name);
+  // setName(Name); // HLSL Change: moved above
 }
 }
 
 
 void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {
 void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {

+ 2 - 2
lib/IR/DataLayout.cpp

@@ -525,7 +525,7 @@ public:
     for (const auto &I : LayoutInfo) {
     for (const auto &I : LayoutInfo) {
       StructLayout *Value = I.second;
       StructLayout *Value = I.second;
       Value->~StructLayout();
       Value->~StructLayout();
-      free(Value);
+      ::operator delete(Value); // HLSL Change: Use overridable operator delete
     }
     }
   }
   }
 
 
@@ -560,7 +560,7 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
   // malloc it, then use placement new.
   // malloc it, then use placement new.
   int NumElts = Ty->getNumElements();
   int NumElts = Ty->getNumElements();
   StructLayout *L =
   StructLayout *L =
-    (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
+    (StructLayout *)::operator new(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t)); // HLSL Change: Use overridable operator new
 
 
   // Set SL before calling StructLayout's ctor.  The ctor could cause other
   // Set SL before calling StructLayout's ctor.  The ctor could cause other
   // entries to be added to TheMap, invalidating our reference.
   // entries to be added to TheMap, invalidating our reference.

+ 2 - 2
lib/IR/Function.cpp

@@ -256,7 +256,7 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name,
   assert(FunctionType::isValidReturnType(getReturnType()) &&
   assert(FunctionType::isValidReturnType(getReturnType()) &&
          "invalid return type");
          "invalid return type");
   setGlobalObjectSubClassData(0);
   setGlobalObjectSubClassData(0);
-  SymTab = new ValueSymbolTable();
+  SymTab.reset(new ValueSymbolTable()); // HLSL Change: use unique_ptr
 
 
   // If the function has arguments, mark them as lazily built.
   // If the function has arguments, mark them as lazily built.
   if (Ty->getNumParams())
   if (Ty->getNumParams())
@@ -277,7 +277,7 @@ Function::~Function() {
 
 
   // Delete all of the method arguments and unlink from symbol table...
   // Delete all of the method arguments and unlink from symbol table...
   ArgumentList.clear();
   ArgumentList.clear();
-  delete SymTab;
+  SymTab.reset(); // HLSL Change: use unique_ptr
 
 
   // Remove the function from the on-the-side GC table.
   // Remove the function from the on-the-side GC table.
   clearGC();
   clearGC();

+ 3 - 0
lib/IR/LLVMContext.cpp

@@ -32,6 +32,7 @@ LLVMContext& llvm::getGlobalContext() {
 }
 }
 
 
 LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
 LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
+  std::unique_ptr<LLVMContextImpl> implPtrGuard(pImpl); // HLSL Change: Don't leak if constructor throws.
   // Create the fixed metadata kinds. This is done in the same order as the
   // Create the fixed metadata kinds. This is done in the same order as the
   // MD_* enum values so that they correspond.
   // MD_* enum values so that they correspond.
 
 
@@ -104,6 +105,8 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
   assert(DereferenceableOrNullID == MD_dereferenceable_or_null && 
   assert(DereferenceableOrNullID == MD_dereferenceable_or_null && 
          "dereferenceable_or_null kind id drifted");
          "dereferenceable_or_null kind id drifted");
   (void)DereferenceableOrNullID;
   (void)DereferenceableOrNullID;
+
+  implPtrGuard.release(); // HLSL Change: Destructor now on the hook for destruction
 }
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
 

+ 8 - 0
lib/IR/Metadata.cpp

@@ -365,9 +365,17 @@ MDString *MDString::get(LLVMContext &Context, StringRef Str) {
 
 
   auto *Entry =
   auto *Entry =
       StringMapEntry<MDString>::Create(Str, Store.getAllocator(), MDString());
       StringMapEntry<MDString>::Create(Str, Store.getAllocator(), MDString());
+  // HLSL Change Begin: Don't leak on insertion failure
+  try {
   bool WasInserted = Store.insert(Entry);
   bool WasInserted = Store.insert(Entry);
   (void)WasInserted;
   (void)WasInserted;
   assert(WasInserted && "Expected entry to be inserted");
   assert(WasInserted && "Expected entry to be inserted");
+  }
+  catch (...) {
+    Entry->Destroy();
+    throw;
+  }
+  // HLSL Change End
   Entry->second.Entry = Entry;
   Entry->second.Entry = Entry;
   return &Entry->second;
   return &Entry->second;
 }
 }

+ 8 - 0
lib/IR/Value.cpp

@@ -181,7 +181,15 @@ void Value::setValueName(ValueName *VN) {
     return;
     return;
   }
   }
 
 
+  // HLSL Change Begin: try/catch to not leak VN on exceptions
+  try {
   Ctx.pImpl->ValueNames[this] = VN;
   Ctx.pImpl->ValueNames[this] = VN;
+  }
+  catch (...) {
+    VN->Destroy();
+    throw;
+  }
+  // HLSL Change End
   HasName = true; // HLSL Change - only set this to true after assignment
   HasName = true; // HLSL Change - only set this to true after assignment
 }
 }
 
 

+ 1 - 0
lib/Support/CMakeLists.txt

@@ -105,6 +105,7 @@ add_llvm_library(LLVMSupport
   regexec.c
   regexec.c
   regfree.c
   regfree.c
   regstrlcpy.c
   regstrlcpy.c
+  regmalloc.cpp # HLSL Change
 
 
 # System
 # System
   assert.cpp      # HLSL Change
   assert.cpp      # HLSL Change

+ 14 - 9
lib/Support/StringMap.cpp

@@ -40,10 +40,14 @@ void StringMapImpl::init(unsigned InitSize) {
   NumItems = 0;
   NumItems = 0;
   NumTombstones = 0;
   NumTombstones = 0;
   
   
-  TheTable = (StringMapEntryBase **)calloc(NumBuckets+1,
-                                           sizeof(StringMapEntryBase **) +
-                                           sizeof(unsigned));
-  if (TheTable == nullptr) throw std::bad_alloc(); // HLSL Change
+  // HLSL Change Begin: Use overridable operator new
+  unsigned NewNumBuckets = NumBuckets;
+  NumBuckets = 0; // If allocation fails, we should have zero buckets.
+  size_t TableSize = (NewNumBuckets + 1) * (sizeof(StringMapEntryBase *) + sizeof(unsigned));
+  TheTable = (StringMapEntryBase **)::operator new(TableSize);
+  std::memset(TheTable, 0, TableSize);
+  NumBuckets = NewNumBuckets;
+  // HLSL Change End
 
 
   // Allocate one extra bucket, set it to look filled so the iterators stop at
   // Allocate one extra bucket, set it to look filled so the iterators stop at
   // end.
   // end.
@@ -201,10 +205,11 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
   unsigned NewBucketNo = BucketNo;
   unsigned NewBucketNo = BucketNo;
   // Allocate one extra bucket which will always be non-empty.  This allows the
   // Allocate one extra bucket which will always be non-empty.  This allows the
   // iterators to stop at end.
   // iterators to stop at end.
-  StringMapEntryBase **NewTableArray =
-    (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) +
-                                             sizeof(unsigned));
-  if (NewTableArray == nullptr) throw std::bad_alloc(); // HLSL Change
+  // HLSL Change Begin: Use overridable operator new
+  size_t NewTableSize = (NewSize + 1) * (sizeof(StringMapEntryBase*) + sizeof(unsigned));
+  StringMapEntryBase **NewTableArray = (StringMapEntryBase **)::operator new(NewTableSize);
+  std::memset(NewTableArray, 0, NewTableSize);
+  // HLSL Change End
   unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
   unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
   NewTableArray[NewSize] = (StringMapEntryBase*)2;
   NewTableArray[NewSize] = (StringMapEntryBase*)2;
 
 
@@ -238,7 +243,7 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
     }
     }
   }
   }
   
   
-  free(TheTable);
+  ::operator delete(TheTable); // HLSL Change: Use overridable operator delete
   
   
   TheTable = NewTableArray;
   TheTable = NewTableArray;
   NumBuckets = NewSize;
   NumBuckets = NewSize;

+ 12 - 12
lib/Support/regcomp.c

@@ -187,15 +187,15 @@ llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags)
 		len = strlen((const char *)pattern);
 		len = strlen((const char *)pattern);
 
 
 	/* do the mallocs early so failure handling is easy */
 	/* do the mallocs early so failure handling is easy */
-	g = (struct re_guts *)malloc(sizeof(struct re_guts) +
+	g = (struct re_guts *)regex_malloc(sizeof(struct re_guts) + // HLSL Change: Use custom allocator
 							(NC-1)*sizeof(cat_t));
 							(NC-1)*sizeof(cat_t));
 	if (g == NULL)
 	if (g == NULL)
 		return(REG_ESPACE);
 		return(REG_ESPACE);
 	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
 	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
-	p->strip = (sop *)calloc(p->ssize, sizeof(sop));
+	p->strip = (sop *)regex_calloc(p->ssize, sizeof(sop)); // HLSL Change: Use custom allocator
 	p->slen = 0;
 	p->slen = 0;
 	if (p->strip == NULL) {
 	if (p->strip == NULL) {
-		free((char *)g);
+		regex_free((char *)g); // HLSL Change: Use custom allocator
 		return(REG_ESPACE);
 		return(REG_ESPACE);
 	}
 	}
 
 
@@ -1082,12 +1082,12 @@ allocset(struct parse *p)
 		assert(nc % CHAR_BIT == 0);
 		assert(nc % CHAR_BIT == 0);
 		nbytes = nc / CHAR_BIT * css;
 		nbytes = nc / CHAR_BIT * css;
 
 
-		ptr = (cset *)realloc((char *)p->g->sets, nc * sizeof(cset));
+		ptr = (cset *)regex_realloc((char *)p->g->sets, no * sizeof(cset), nc * sizeof(cset)); // HLSL Change: Use custom allocator
 		if (ptr == NULL)
 		if (ptr == NULL)
 			goto nomem;
 			goto nomem;
 		p->g->sets = ptr;
 		p->g->sets = ptr;
 
 
-		ptr = (uch *)realloc((char *)p->g->setbits, nbytes);
+		ptr = (uch *)regex_realloc((char *)p->g->setbits, no / CHAR_BIT * css, nbytes); // HLSL Change: Use custom allocator
 		if (ptr == NULL)
 		if (ptr == NULL)
 			goto nomem;
 			goto nomem;
 		p->g->setbits = ptr;
 		p->g->setbits = ptr;
@@ -1113,9 +1113,9 @@ allocset(struct parse *p)
 
 
 	return(cs);
 	return(cs);
 nomem:
 nomem:
-	free(p->g->sets);
+	regex_free(p->g->sets); // HLSL Change: Use custom allocator
 	p->g->sets = NULL;
 	p->g->sets = NULL;
-	free(p->g->setbits);
+	regex_free(p->g->setbits); // HLSL Change: Use custom allocator
 	p->g->setbits = NULL;
 	p->g->setbits = NULL;
 
 
 	SETERROR(REG_ESPACE);
 	SETERROR(REG_ESPACE);
@@ -1218,10 +1218,10 @@ mcadd( struct parse *p, cset *cs, const char *cp)
 	void *np;
 	void *np;
 
 
 	cs->smultis += strlen(cp) + 1;
 	cs->smultis += strlen(cp) + 1;
-	np = realloc(cs->multis, cs->smultis);
+	np = regex_realloc(cs->multis, oldend, cs->smultis); // HLSL Change: Use custom allocator
 	if (np == NULL) {
 	if (np == NULL) {
 		if (cs->multis)
 		if (cs->multis)
-			free(cs->multis);
+			regex_free(cs->multis); // HLSL Change: Use custom allocator
 		cs->multis = NULL;
 		cs->multis = NULL;
 		SETERROR(REG_ESPACE);
 		SETERROR(REG_ESPACE);
 		return;
 		return;
@@ -1430,7 +1430,7 @@ enlarge(struct parse *p, sopno size)
 		return;
 		return;
 	}
 	}
 
 
-	sp = (sop *)realloc(p->strip, size*sizeof(sop));
+	sp = (sop *)regex_realloc(p->strip, p->ssize*sizeof(sop), size*sizeof(sop)); // HLSL Change: Use custom allocator
 	if (sp == NULL) {
 	if (sp == NULL) {
 		SETERROR(REG_ESPACE);
 		SETERROR(REG_ESPACE);
 		return;
 		return;
@@ -1452,7 +1452,7 @@ stripsnug(struct parse *p, struct re_guts *g)
 		return;
 		return;
 	}
 	}
 
 
-	g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
+	g->strip = (sop *)regex_realloc((char *)p->strip, p->slen * sizeof(sop), p->slen * sizeof(sop)); // HLSL Change: Use custom allocator
 	if (g->strip == NULL) {
 	if (g->strip == NULL) {
 		SETERROR(REG_ESPACE);
 		SETERROR(REG_ESPACE);
 		g->strip = p->strip;
 		g->strip = p->strip;
@@ -1526,7 +1526,7 @@ findmust(struct parse *p, struct re_guts *g)
 		return;
 		return;
 
 
 	/* turn it into a character string */
 	/* turn it into a character string */
-	g->must = malloc((size_t)g->mlen + 1);
+	g->must = regex_malloc((size_t)g->mlen + 1); // HLSL Change: Use custom allocator
 	if (g->must == NULL) {		/* argh; just forget it */
 	if (g->must == NULL) {		/* argh; just forget it */
 		g->mlen = 0;
 		g->mlen = 0;
 		return;
 		return;

+ 7 - 7
lib/Support/regengine.inc

@@ -184,8 +184,8 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
 	for (;;) {
 	for (;;) {
 		endp = fast(m, start, stop, gf, gl);
 		endp = fast(m, start, stop, gf, gl);
 		if (endp == NULL) {		/* a miss */
 		if (endp == NULL) {		/* a miss */
-			free(m->pmatch);
-			free((void*)m->lastpos);
+			regex_free(m->pmatch); // HLSL Change: Use custom allocator
+			regex_free((void*)m->lastpos); // HLSL Change: Use custom allocator
 			STATETEARDOWN(m);
 			STATETEARDOWN(m);
 			return(REG_NOMATCH);
 			return(REG_NOMATCH);
 		}
 		}
@@ -207,7 +207,7 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
 
 
 		/* oh my, they want the subexpressions... */
 		/* oh my, they want the subexpressions... */
 		if (m->pmatch == NULL)
 		if (m->pmatch == NULL)
-			m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) *
+			m->pmatch = (llvm_regmatch_t *)regex_malloc((m->g->nsub + 1) * // HLSL Change: Use custom allocator
 							sizeof(llvm_regmatch_t));
 							sizeof(llvm_regmatch_t));
 		if (m->pmatch == NULL) {
 		if (m->pmatch == NULL) {
 			STATETEARDOWN(m);
 			STATETEARDOWN(m);
@@ -220,10 +220,10 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
 			dp = dissect(m, m->coldp, endp, gf, gl);
 			dp = dissect(m, m->coldp, endp, gf, gl);
 		} else {
 		} else {
 			if (g->nplus > 0 && m->lastpos == NULL)
 			if (g->nplus > 0 && m->lastpos == NULL)
-				m->lastpos = (const char **)malloc((g->nplus+1) *
+				m->lastpos = (const char **)regex_malloc((g->nplus+1) * // HLSL Change: Use custom allocator
 							sizeof(char *));
 							sizeof(char *));
 			if (g->nplus > 0 && m->lastpos == NULL) {
 			if (g->nplus > 0 && m->lastpos == NULL) {
-				free(m->pmatch);
+				regex_free(m->pmatch); // HLSL Change: Use custom allocator
 				STATETEARDOWN(m);
 				STATETEARDOWN(m);
 				return(REG_ESPACE);
 				return(REG_ESPACE);
 			}
 			}
@@ -281,9 +281,9 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
 	}
 	}
 
 
 	if (m->pmatch != NULL)
 	if (m->pmatch != NULL)
-		free((char *)m->pmatch);
+		regex_free((char *)m->pmatch); // HLSL Change: Use custom allocator
 	if (m->lastpos != NULL)
 	if (m->lastpos != NULL)
-		free((char *)m->lastpos);
+		regex_free((char *)m->lastpos); // HLSL Change: Use custom allocator
 	STATETEARDOWN(m);
 	STATETEARDOWN(m);
 	return(0);
 	return(0);
 }
 }

+ 4 - 2
lib/Support/regexec.c

@@ -112,10 +112,12 @@
 #define	ASSIGN(d, s)	memmove(d, s, m->g->nstates)
 #define	ASSIGN(d, s)	memmove(d, s, m->g->nstates)
 #define	EQ(a, b)	(memcmp(a, b, m->g->nstates) == 0)
 #define	EQ(a, b)	(memcmp(a, b, m->g->nstates) == 0)
 #define	STATEVARS	long vn; char *space
 #define	STATEVARS	long vn; char *space
-#define	STATESETUP(m, nv)	{ (m)->space = malloc((nv)*(m)->g->nstates); \
+ // HLSL Change Begin: Use custom allocator
+#define	STATESETUP(m, nv)	{ (m)->space = regex_malloc((nv)*(m)->g->nstates); \
 				if ((m)->space == NULL) return(REG_ESPACE); \
 				if ((m)->space == NULL) return(REG_ESPACE); \
 				(m)->vn = 0; }
 				(m)->vn = 0; }
-#define	STATETEARDOWN(m)	{ free((m)->space); }
+#define	STATETEARDOWN(m)	{ regex_free((m)->space); }
+ // HLSL Change End
 #define	SETUP(v)	((v) = &m->space[m->vn++ * m->g->nstates])
 #define	SETUP(v)	((v) = &m->space[m->vn++ * m->g->nstates])
 #define	onestate	long
 #define	onestate	long
 #define	INIT(o, n)	((o) = (n))
 #define	INIT(o, n)	((o) = (n))

+ 36 - 0
lib/Support/regmalloc.cpp

@@ -0,0 +1,36 @@
+//===-- regmalloc.cpp - Memory allocation for regex implementation --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Support operator new/delete overriding for regex memory allocations.
+//===----------------------------------------------------------------------===//
+
+#include "regutils.h"
+#include <algorithm>
+#include <new>
+#include <cstring>
+
+extern "C" {
+  void *regex_malloc(size_t size) {
+    return ::operator new(size, std::nothrow);
+  }
+  void *regex_calloc(size_t num, size_t size) {
+    void* ptr = regex_malloc(num * size);
+    if (ptr) std::memset(ptr, 0, num * size);
+    return ptr;
+  }
+  void* regex_realloc(void* ptr, size_t oldsize, size_t newsize) {
+    void* newptr = regex_malloc(newsize);
+    if (newptr == nullptr) return nullptr;
+    std::memcpy(newptr, ptr, std::min(oldsize, newsize));
+    regex_free(ptr);
+    return newptr;
+  }
+  void regex_free(void *ptr) {
+    return ::operator delete(ptr);
+  }
+}

+ 16 - 0
lib/Support/regutils.h

@@ -38,6 +38,8 @@
 #ifndef LLVM_SUPPORT_REGUTILS_H
 #ifndef LLVM_SUPPORT_REGUTILS_H
 #define LLVM_SUPPORT_REGUTILS_H
 #define LLVM_SUPPORT_REGUTILS_H
 
 
+#include <stdlib.h>
+
 /* utility definitions */
 /* utility definitions */
 #define	NC		(CHAR_MAX - CHAR_MIN + 1)
 #define	NC		(CHAR_MAX - CHAR_MIN + 1)
 typedef unsigned char uch;
 typedef unsigned char uch;
@@ -55,4 +57,18 @@ typedef unsigned char uch;
 #define	memmove(d, s, c)	bcopy(s, d, c)
 #define	memmove(d, s, c)	bcopy(s, d, c)
 #endif
 #endif
 
 
+// HLSL Change Begin: Use custom allocators
+#ifdef __cplusplus
+extern "C" {
+#endif
+void* regex_malloc(size_t size);
+void* regex_calloc(size_t num, size_t size);
+// Realloc diverges from standard because we can't implement it in terms of new[]/delete[]
+void* regex_realloc(void* ptr, size_t oldsize, size_t newsize);
+void regex_free(void* ptr);
+#ifdef __cplusplus
+}
+#endif
+// HLSL Change Ends
+
 #endif
 #endif

+ 1 - 1
tools/clang/include/clang/AST/NestedNameSpecifier.h

@@ -368,7 +368,7 @@ public:
 
 
   ~NestedNameSpecifierLocBuilder() {
   ~NestedNameSpecifierLocBuilder() {
     if (BufferCapacity)
     if (BufferCapacity)
-      free(Buffer);
+      delete[] Buffer;
   }
   }
 
 
   /// \brief Retrieve the representation of the nested-name-specifier.
   /// \brief Retrieve the representation of the nested-name-specifier.

+ 3 - 3
tools/clang/include/clang/Sema/ParsedTemplate.h

@@ -184,8 +184,8 @@ namespace clang {
     static TemplateIdAnnotation *
     static TemplateIdAnnotation *
     Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
     Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
       TemplateIdAnnotation *TemplateId
       TemplateIdAnnotation *TemplateId
-        = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
-                                      sizeof(ParsedTemplateArgument) * NumArgs);
+        = (TemplateIdAnnotation *)::operator new(sizeof(TemplateIdAnnotation) +
+                                      sizeof(ParsedTemplateArgument) * NumArgs); // HLSL Change: Use overridable operator new
       TemplateId->NumArgs = NumArgs;
       TemplateId->NumArgs = NumArgs;
       
       
       // Default-construct nested-name-specifier.
       // Default-construct nested-name-specifier.
@@ -202,7 +202,7 @@ namespace clang {
     
     
     void Destroy() { 
     void Destroy() { 
       SS.~CXXScopeSpec();
       SS.~CXXScopeSpec();
-      free(this); 
+      ::operator delete(this); // HLSL Change: Use overridable operator delete 
     }
     }
   };
   };
 
 

+ 8 - 0
tools/clang/lib/AST/ASTContext.cpp

@@ -1117,8 +1117,16 @@ DiagnosticsEngine &ASTContext::getDiagnostics() const {
 AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
 AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
   AttrVec *&Result = DeclAttrs[D];
   AttrVec *&Result = DeclAttrs[D];
   if (!Result) {
   if (!Result) {
+    try { // HLSL Change
     void *Mem = Allocate(sizeof(AttrVec));
     void *Mem = Allocate(sizeof(AttrVec));
     Result = new (Mem) AttrVec;
     Result = new (Mem) AttrVec;
+    // HLSL Change Begin: Don't leave empty entry on exception
+    }
+    catch (...) {
+      DeclAttrs.erase(D);
+      throw;
+    }
+    // HLSL Change End
   }
   }
     
     
   return *Result;
   return *Result;

+ 2 - 2
tools/clang/lib/AST/NestedNameSpecifier.cpp

@@ -445,10 +445,10 @@ namespace {
       unsigned NewCapacity = std::max(
       unsigned NewCapacity = std::max(
           (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
           (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
           (unsigned)(BufferSize + (End - Start)));
           (unsigned)(BufferSize + (End - Start)));
-      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+      char *NewBuffer = new char[NewCapacity]; // HLSL Change: Use overridable operator new
       if (BufferCapacity) {
       if (BufferCapacity) {
         memcpy(NewBuffer, Buffer, BufferSize);
         memcpy(NewBuffer, Buffer, BufferSize);
-        free(Buffer);
+        delete[] Buffer; // HLSL Change: Use overridable operator delete
       }
       }
       Buffer = NewBuffer;
       Buffer = NewBuffer;
       BufferCapacity = NewCapacity;
       BufferCapacity = NewCapacity;

+ 2 - 2
tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp

@@ -88,8 +88,8 @@ void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
 
 
   // Emit the HTML.
   // Emit the HTML.
   const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
   const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
-  char *Buffer = (char*)malloc(RewriteBuf.size());
+  char *Buffer = new char[RewriteBuf.size()]; // HLSL Change: Use overridable operator new
   std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
   std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
   Out->write(Buffer, RewriteBuf.size());
   Out->write(Buffer, RewriteBuf.size());
-  free(Buffer);
+  delete[] Buffer; // HLSL Change: Use overridable operator delete
 }
 }

+ 7 - 2
tools/clang/lib/Lex/Pragma.cpp

@@ -64,9 +64,13 @@ PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
 }
 }
 
 
 void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
 void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
+  // HLSL Change Begins: Don't leak on exceptions
+  std::unique_ptr<PragmaHandler> HandlerPtr(Handler);
   assert(!Handlers.lookup(Handler->getName()) &&
   assert(!Handlers.lookup(Handler->getName()) &&
          "A handler with this name is already registered in this namespace");
          "A handler with this name is already registered in this namespace");
-  Handlers[Handler->getName()] = Handler;
+  PragmaHandler*& MapHandler = Handlers[Handler->getName()];
+  MapHandler = HandlerPtr.release();
+  // HLSL Change Ends
 }
 }
 
 
 void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
 void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
@@ -724,6 +728,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
 /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
 /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
 void Preprocessor::AddPragmaHandler(StringRef Namespace,
 void Preprocessor::AddPragmaHandler(StringRef Namespace,
                                     PragmaHandler *Handler) {
                                     PragmaHandler *Handler) {
+  std::unique_ptr<PragmaHandler> HandlerPtr(Handler); // HLSL Change: Don't leak on exceptions
   PragmaNamespace *InsertNS = PragmaHandlers.get();
   PragmaNamespace *InsertNS = PragmaHandlers.get();
 
 
   // If this is specified to be in a namespace, step down into it.
   // If this is specified to be in a namespace, step down into it.
@@ -746,7 +751,7 @@ void Preprocessor::AddPragmaHandler(StringRef Namespace,
   // Check to make sure we don't already have a pragma for this identifier.
   // Check to make sure we don't already have a pragma for this identifier.
   assert(!InsertNS->FindHandler(Handler->getName()) &&
   assert(!InsertNS->FindHandler(Handler->getName()) &&
          "Pragma handler already exists for this identifier!");
          "Pragma handler already exists for this identifier!");
-  InsertNS->AddPragma(Handler);
+  InsertNS->AddPragma(HandlerPtr.release()); // HLSL Change: Don't leak on exceptions
 }
 }
 
 
 /// RemovePragmaHandler - Remove the specific pragma handler from the
 /// RemovePragmaHandler - Remove the specific pragma handler from the

+ 4 - 5
tools/clang/lib/Parse/ParsePragma.cpp

@@ -251,11 +251,10 @@ void Parser::initializePragmaHandlers() {
   } // HLSL Change, matching HLSL check to remove pragma processing
   } // HLSL Change, matching HLSL check to remove pragma processing
   else {
   else {
     // HLSL Change Begin - packmatrix.
     // HLSL Change Begin - packmatrix.
-    // The pointer ownership goes to PP, which deletes it in its destructor
-    // unless it is removed & deleted via resetPragmaHandlers
-    std::unique_ptr<PragmaHandler> pHandler(new PragmaPackMatrixHandler(Actions));
-    PP.AddPragmaHandler(pHandler.get());
-    pPackMatrixHandler = pHandler.release();
+    // The pointer ownership goes to PP as soon as we do the call,
+    // which deletes it in its destructor unless it is removed & deleted via resetPragmaHandlers
+    pPackMatrixHandler = new PragmaPackMatrixHandler(Actions);
+    PP.AddPragmaHandler(pPackMatrixHandler);
     // HLSL Change End.
     // HLSL Change End.
   }
   }
 }
 }