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.
This commit is contained in:
Родитель
893d340c4f
Коммит
e4ceb30434
|
@ -190,7 +190,7 @@ public:
|
|||
SparseMultiSet()
|
||||
: 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.
|
||||
/// The universe must be sized before any elements can be added.
|
||||
|
@ -204,11 +204,14 @@ public:
|
|||
// Hysteresis prevents needless reallocations.
|
||||
if (U >= Universe/4 && U <= Universe)
|
||||
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
|
||||
// would be enough here, but that will cause tools like valgrind to
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ public:
|
|||
typedef const ValueT *const_pointer;
|
||||
|
||||
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
|
||||
/// set can hold. The universe must be sized before any elements can be
|
||||
|
@ -159,11 +159,14 @@ public:
|
|||
// Hysteresis prevents needless reallocations.
|
||||
if (U >= Universe/4 && U <= Universe)
|
||||
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
|
||||
// would be enough here, but that will cause tools like valgrind to
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
free(TheTable);
|
||||
::operator delete(TheTable); // HLSL Change Begin: Use overridable operator delete
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -420,7 +420,21 @@ public:
|
|||
Head = 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ class PressureDiffs {
|
|||
unsigned Max;
|
||||
public:
|
||||
PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {}
|
||||
~PressureDiffs() { free(PDiffArray); }
|
||||
~PressureDiffs() { delete[] PDiffArray; } // HLSL Change: Use overridable operator delete
|
||||
|
||||
void clear() { Size = 0; }
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ private:
|
|||
// Important things that make up a function!
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
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
|
||||
FunctionType *Ty;
|
||||
|
||||
|
|
|
@ -51,6 +51,12 @@ public:
|
|||
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
|
||||
/// automatically inserted into the end of the specified modules global list.
|
||||
GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage,
|
||||
|
|
|
@ -93,18 +93,14 @@ public:
|
|||
_Ret_notnull_ // HLSL Change - SAL
|
||||
LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
|
||||
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.
|
||||
using AllocatorBase<MallocAllocator>::Allocate;
|
||||
|
||||
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.
|
||||
|
@ -314,6 +310,7 @@ private:
|
|||
void StartNewSlab() {
|
||||
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);
|
||||
Slabs.push_back(NewSlab);
|
||||
CurPtr = (char *)(NewSlab);
|
||||
|
|
|
@ -94,8 +94,10 @@ private:
|
|||
|
||||
/// \brief Resize the hash table, moving the old entries into the new buckets.
|
||||
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.
|
||||
for (size_t I = 0; I < NumBuckets; ++I)
|
||||
for (Item *E = Buckets[I].Head; E;) {
|
||||
|
@ -105,7 +107,7 @@ private:
|
|||
E = N;
|
||||
}
|
||||
|
||||
free(Buckets);
|
||||
delete[] Buckets; // HLSL Change: Use overridable operator delete
|
||||
NumBuckets = NewSize;
|
||||
Buckets = NewBuckets;
|
||||
}
|
||||
|
@ -188,11 +190,13 @@ public:
|
|||
NumBuckets = 64;
|
||||
// Note that we do not need to run the constructors of the individual
|
||||
// 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.
|
||||
|
|
|
@ -34,11 +34,12 @@ const InterferenceCache::BlockInterference
|
|||
// numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized.
|
||||
void InterferenceCache::reinitPhysRegEntries() {
|
||||
if (PhysRegEntriesCount == TRI->getNumRegs()) return;
|
||||
free(PhysRegEntries);
|
||||
delete[] PhysRegEntries; // HLSL Change: Use overridable operator delete
|
||||
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,
|
||||
|
|
|
@ -154,7 +154,7 @@ public:
|
|||
PhysRegEntriesCount(0), RoundRobin(0) {}
|
||||
|
||||
~InterferenceCache() {
|
||||
free(PhysRegEntries);
|
||||
delete[] PhysRegEntries; // HLSL Change: Use overridable operator delete
|
||||
}
|
||||
|
||||
void reinitPhysRegEntries();
|
||||
|
|
|
@ -388,9 +388,11 @@ void PressureDiffs::init(unsigned N) {
|
|||
return;
|
||||
}
|
||||
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.
|
||||
|
|
|
@ -42,13 +42,19 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
|
|||
BasicBlock *InsertBefore)
|
||||
: 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)
|
||||
insertInto(NewParent, InsertBefore);
|
||||
else
|
||||
assert(!InsertBefore &&
|
||||
"Cannot insert block before another block with no function!");
|
||||
|
||||
setName(Name);
|
||||
// setName(Name); // HLSL Change: moved above
|
||||
}
|
||||
|
||||
void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {
|
||||
|
|
|
@ -525,7 +525,7 @@ public:
|
|||
for (const auto &I : LayoutInfo) {
|
||||
StructLayout *Value = I.second;
|
||||
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.
|
||||
int NumElts = Ty->getNumElements();
|
||||
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
|
||||
// entries to be added to TheMap, invalidating our reference.
|
||||
|
|
|
@ -256,7 +256,7 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name,
|
|||
assert(FunctionType::isValidReturnType(getReturnType()) &&
|
||||
"invalid return type");
|
||||
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 (Ty->getNumParams())
|
||||
|
@ -277,7 +277,7 @@ Function::~Function() {
|
|||
|
||||
// Delete all of the method arguments and unlink from symbol table...
|
||||
ArgumentList.clear();
|
||||
delete SymTab;
|
||||
SymTab.reset(); // HLSL Change: use unique_ptr
|
||||
|
||||
// Remove the function from the on-the-side GC table.
|
||||
clearGC();
|
||||
|
|
|
@ -32,6 +32,7 @@ LLVMContext& llvm::getGlobalContext() {
|
|||
}
|
||||
|
||||
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
|
||||
// MD_* enum values so that they correspond.
|
||||
|
||||
|
@ -104,6 +105,8 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
|
|||
assert(DereferenceableOrNullID == MD_dereferenceable_or_null &&
|
||||
"dereferenceable_or_null kind id drifted");
|
||||
(void)DereferenceableOrNullID;
|
||||
|
||||
implPtrGuard.release(); // HLSL Change: Destructor now on the hook for destruction
|
||||
}
|
||||
LLVMContext::~LLVMContext() { delete pImpl; }
|
||||
|
||||
|
|
|
@ -365,9 +365,17 @@ MDString *MDString::get(LLVMContext &Context, StringRef Str) {
|
|||
|
||||
auto *Entry =
|
||||
StringMapEntry<MDString>::Create(Str, Store.getAllocator(), MDString());
|
||||
// HLSL Change Begin: Don't leak on insertion failure
|
||||
try {
|
||||
bool WasInserted = Store.insert(Entry);
|
||||
(void)WasInserted;
|
||||
assert(WasInserted && "Expected entry to be inserted");
|
||||
}
|
||||
catch (...) {
|
||||
Entry->Destroy();
|
||||
throw;
|
||||
}
|
||||
// HLSL Change End
|
||||
Entry->second.Entry = Entry;
|
||||
return &Entry->second;
|
||||
}
|
||||
|
|
|
@ -181,7 +181,15 @@ void Value::setValueName(ValueName *VN) {
|
|||
return;
|
||||
}
|
||||
|
||||
// HLSL Change Begin: try/catch to not leak VN on exceptions
|
||||
try {
|
||||
Ctx.pImpl->ValueNames[this] = VN;
|
||||
}
|
||||
catch (...) {
|
||||
VN->Destroy();
|
||||
throw;
|
||||
}
|
||||
// HLSL Change End
|
||||
HasName = true; // HLSL Change - only set this to true after assignment
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ add_llvm_library(LLVMSupport
|
|||
regexec.c
|
||||
regfree.c
|
||||
regstrlcpy.c
|
||||
regmalloc.cpp # HLSL Change
|
||||
|
||||
# System
|
||||
assert.cpp # HLSL Change
|
||||
|
|
|
@ -40,10 +40,14 @@ void StringMapImpl::init(unsigned InitSize) {
|
|||
NumItems = 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
|
||||
// end.
|
||||
|
@ -201,10 +205,11 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
|
|||
unsigned NewBucketNo = BucketNo;
|
||||
// Allocate one extra bucket which will always be non-empty. This allows the
|
||||
// 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);
|
||||
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;
|
||||
NumBuckets = NewSize;
|
||||
|
|
|
@ -187,15 +187,15 @@ llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags)
|
|||
len = strlen((const char *)pattern);
|
||||
|
||||
/* 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));
|
||||
if (g == NULL)
|
||||
return(REG_ESPACE);
|
||||
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;
|
||||
if (p->strip == NULL) {
|
||||
free((char *)g);
|
||||
regex_free((char *)g); // HLSL Change: Use custom allocator
|
||||
return(REG_ESPACE);
|
||||
}
|
||||
|
||||
|
@ -1082,12 +1082,12 @@ allocset(struct parse *p)
|
|||
assert(nc % CHAR_BIT == 0);
|
||||
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)
|
||||
goto nomem;
|
||||
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)
|
||||
goto nomem;
|
||||
p->g->setbits = ptr;
|
||||
|
@ -1113,9 +1113,9 @@ allocset(struct parse *p)
|
|||
|
||||
return(cs);
|
||||
nomem:
|
||||
free(p->g->sets);
|
||||
regex_free(p->g->sets); // HLSL Change: Use custom allocator
|
||||
p->g->sets = NULL;
|
||||
free(p->g->setbits);
|
||||
regex_free(p->g->setbits); // HLSL Change: Use custom allocator
|
||||
p->g->setbits = NULL;
|
||||
|
||||
SETERROR(REG_ESPACE);
|
||||
|
@ -1218,10 +1218,10 @@ mcadd( struct parse *p, cset *cs, const char *cp)
|
|||
void *np;
|
||||
|
||||
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 (cs->multis)
|
||||
free(cs->multis);
|
||||
regex_free(cs->multis); // HLSL Change: Use custom allocator
|
||||
cs->multis = NULL;
|
||||
SETERROR(REG_ESPACE);
|
||||
return;
|
||||
|
@ -1430,7 +1430,7 @@ enlarge(struct parse *p, sopno size)
|
|||
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) {
|
||||
SETERROR(REG_ESPACE);
|
||||
return;
|
||||
|
@ -1452,7 +1452,7 @@ stripsnug(struct parse *p, struct re_guts *g)
|
|||
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) {
|
||||
SETERROR(REG_ESPACE);
|
||||
g->strip = p->strip;
|
||||
|
@ -1526,7 +1526,7 @@ findmust(struct parse *p, struct re_guts *g)
|
|||
return;
|
||||
|
||||
/* 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 */
|
||||
g->mlen = 0;
|
||||
return;
|
||||
|
|
|
@ -184,8 +184,8 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
|
|||
for (;;) {
|
||||
endp = fast(m, start, stop, gf, gl);
|
||||
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);
|
||||
return(REG_NOMATCH);
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
|
|||
|
||||
/* oh my, they want the subexpressions... */
|
||||
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));
|
||||
if (m->pmatch == NULL) {
|
||||
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);
|
||||
} else {
|
||||
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 *));
|
||||
if (g->nplus > 0 && m->lastpos == NULL) {
|
||||
free(m->pmatch);
|
||||
regex_free(m->pmatch); // HLSL Change: Use custom allocator
|
||||
STATETEARDOWN(m);
|
||||
return(REG_ESPACE);
|
||||
}
|
||||
|
@ -281,9 +281,9 @@ matcher(struct re_guts *g, const char *string, size_t nmatch,
|
|||
}
|
||||
|
||||
if (m->pmatch != NULL)
|
||||
free((char *)m->pmatch);
|
||||
regex_free((char *)m->pmatch); // HLSL Change: Use custom allocator
|
||||
if (m->lastpos != NULL)
|
||||
free((char *)m->lastpos);
|
||||
regex_free((char *)m->lastpos); // HLSL Change: Use custom allocator
|
||||
STATETEARDOWN(m);
|
||||
return(0);
|
||||
}
|
||||
|
|
|
@ -112,10 +112,12 @@
|
|||
#define ASSIGN(d, s) memmove(d, s, m->g->nstates)
|
||||
#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0)
|
||||
#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); \
|
||||
(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 onestate long
|
||||
#define INIT(o, n) ((o) = (n))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,8 @@
|
|||
#ifndef LLVM_SUPPORT_REGUTILS_H
|
||||
#define LLVM_SUPPORT_REGUTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* utility definitions */
|
||||
#define NC (CHAR_MAX - CHAR_MIN + 1)
|
||||
typedef unsigned char uch;
|
||||
|
@ -55,4 +57,18 @@ typedef unsigned char uch;
|
|||
#define memmove(d, s, c) bcopy(s, d, c)
|
||||
#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
|
||||
|
|
|
@ -368,7 +368,7 @@ public:
|
|||
|
||||
~NestedNameSpecifierLocBuilder() {
|
||||
if (BufferCapacity)
|
||||
free(Buffer);
|
||||
delete[] Buffer;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the representation of the nested-name-specifier.
|
||||
|
|
|
@ -184,8 +184,8 @@ namespace clang {
|
|||
static TemplateIdAnnotation *
|
||||
Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
|
||||
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;
|
||||
|
||||
// Default-construct nested-name-specifier.
|
||||
|
@ -202,7 +202,7 @@ namespace clang {
|
|||
|
||||
void Destroy() {
|
||||
SS.~CXXScopeSpec();
|
||||
free(this);
|
||||
::operator delete(this); // HLSL Change: Use overridable operator delete
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1117,8 +1117,16 @@ DiagnosticsEngine &ASTContext::getDiagnostics() const {
|
|||
AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
|
||||
AttrVec *&Result = DeclAttrs[D];
|
||||
if (!Result) {
|
||||
try { // HLSL Change
|
||||
void *Mem = Allocate(sizeof(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;
|
||||
|
|
|
@ -445,10 +445,10 @@ namespace {
|
|||
unsigned NewCapacity = std::max(
|
||||
(unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
|
||||
(unsigned)(BufferSize + (End - Start)));
|
||||
char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
|
||||
char *NewBuffer = new char[NewCapacity]; // HLSL Change: Use overridable operator new
|
||||
if (BufferCapacity) {
|
||||
memcpy(NewBuffer, Buffer, BufferSize);
|
||||
free(Buffer);
|
||||
delete[] Buffer; // HLSL Change: Use overridable operator delete
|
||||
}
|
||||
Buffer = NewBuffer;
|
||||
BufferCapacity = NewCapacity;
|
||||
|
|
|
@ -88,8 +88,8 @@ void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
|
|||
|
||||
// Emit the HTML.
|
||||
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);
|
||||
Out->write(Buffer, RewriteBuf.size());
|
||||
free(Buffer);
|
||||
delete[] Buffer; // HLSL Change: Use overridable operator delete
|
||||
}
|
||||
|
|
|
@ -64,9 +64,13 @@ PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
|
|||
}
|
||||
|
||||
void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
|
||||
// HLSL Change Begins: Don't leak on exceptions
|
||||
std::unique_ptr<PragmaHandler> HandlerPtr(Handler);
|
||||
assert(!Handlers.lookup(Handler->getName()) &&
|
||||
"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) {
|
||||
|
@ -724,6 +728,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
|
|||
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
|
||||
void Preprocessor::AddPragmaHandler(StringRef Namespace,
|
||||
PragmaHandler *Handler) {
|
||||
std::unique_ptr<PragmaHandler> HandlerPtr(Handler); // HLSL Change: Don't leak on exceptions
|
||||
PragmaNamespace *InsertNS = PragmaHandlers.get();
|
||||
|
||||
// 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.
|
||||
assert(!InsertNS->FindHandler(Handler->getName()) &&
|
||||
"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
|
||||
|
|
|
@ -251,11 +251,10 @@ void Parser::initializePragmaHandlers() {
|
|||
} // HLSL Change, matching HLSL check to remove pragma processing
|
||||
else {
|
||||
// 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.
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче