Commit 8156b6be by Alok Priyadarshi Committed by Jamie Madill

Fixed memory leak associated with TLS.

We used to allocate thread-local memory on each compile. If the compile did not happen on the same thread as ShInitialize, we leaked the thread-local memory. It turns out that there is no need to allocate any thread-local memory. This patch cleans up all the unnecessary junk around TLS. BUG=crbug.com/181691 R=kbr@chromium.org Review URL: https://codereview.appspot.com/11679046 Conflicts: src/compiler/ConstantUnion.h src/compiler/ShaderLang.cpp src/compiler/Types.h src/compiler/ValidateLimitations.cpp
parent 36be856c
...@@ -24,12 +24,12 @@ struct TSourceLoc { ...@@ -24,12 +24,12 @@ struct TSourceLoc {
// //
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
// //
#define POOL_ALLOCATOR_NEW_DELETE(A) \ #define POOL_ALLOCATOR_NEW_DELETE() \
void* operator new(size_t s) { return (A).allocate(s); } \ void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new(size_t, void *_Where) { return (_Where); } \ void* operator new(size_t, void *_Where) { return (_Where); } \
void operator delete(void*) { } \ void operator delete(void*) { } \
void operator delete(void *, void *) { } \ void operator delete(void *, void *) { } \
void* operator new[](size_t s) { return (A).allocate(s); } \ void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new[](size_t, void *_Where) { return (_Where); } \ void* operator new[](size_t, void *_Where) { return (_Where); } \
void operator delete[](void*) { } \ void operator delete[](void*) { } \
void operator delete[](void *, void *) { } void operator delete[](void *, void *) { }
...@@ -42,7 +42,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri ...@@ -42,7 +42,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s) inline TString* NewPoolTString(const char* s)
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
return new(memory) TString(s); return new(memory) TString(s);
} }
......
...@@ -127,7 +127,7 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -127,7 +127,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
shaderType, shaderSpec, compileOptions, true, shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink); sourcePath, infoSink);
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
GlobalParseContext = &parseContext; SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile. // We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level. // Start pushing the user-defined symbols at global level.
......
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
class ConstantUnion { class ConstantUnion {
public: public:
POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion() ConstantUnion()
{ {
iConst = 0; iConst = 0;
type = EbtVoid; type = EbtVoid;
} }
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void setIConst(int i) {iConst = i; type = EbtInt; } void setIConst(int i) {iConst = i; type = EbtInt; }
void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
void setFConst(float f) {fConst = f; type = EbtFloat; } void setFConst(float f) {fConst = f; type = EbtFloat; }
......
...@@ -10,25 +10,8 @@ ...@@ -10,25 +10,8 @@
#include "compiler/InitializeParseContext.h" #include "compiler/InitializeParseContext.h"
#include "compiler/osinclude.h" #include "compiler/osinclude.h"
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
bool InitProcess() bool InitProcess()
{ {
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
//
// Function is re-entrant.
//
return true;
}
ThreadInitializeIndex = OS_AllocTLSIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
return false;
}
if (!InitializePoolIndex()) { if (!InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initalize global pool"); assert(0 && "InitProcess(): Failed to initalize global pool");
return false; return false;
...@@ -39,77 +22,11 @@ bool InitProcess() ...@@ -39,77 +22,11 @@ bool InitProcess()
return false; return false;
} }
return InitThread();
}
bool DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
success = DetachThread();
if (!FreeParseContextIndex())
success = false;
FreePoolIndex();
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
return success;
}
bool InitThread()
{
//
// This function is re-entrant
//
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitThread(): Process hasn't been initalised.");
return false;
}
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
return true;
InitializeGlobalPools();
if (!InitializeGlobalParseContext())
return false;
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
assert(0 && "InitThread(): Unable to set init flag.");
return false;
}
return true; return true;
} }
bool DetachThread() void DetachProcess()
{ {
bool success = true; FreeParseContextIndex();
FreePoolIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
//
// Function is re-entrant and this thread may not have been initalised.
//
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
assert(0 && "DetachThread(): Unable to clear init flag.");
success = false;
}
if (!FreeParseContext())
success = false;
FreeGlobalPools();
}
return success;
} }
...@@ -7,10 +7,7 @@ ...@@ -7,10 +7,7 @@
#define __INITIALIZEDLL_H #define __INITIALIZEDLL_H
bool InitProcess(); bool InitProcess();
bool DetachProcess(); void DetachProcess();
bool InitThread();
bool DetachThread();
#endif // __INITIALIZEDLL_H #endif // __INITIALIZEDLL_H
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#ifndef __INITIALIZE_GLOBALS_INCLUDED_ #ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_
void InitializeGlobalPools();
void FreeGlobalPools();
bool InitializePoolIndex(); bool InitializePoolIndex();
void FreePoolIndex(); void FreePoolIndex();
......
...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; ...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
bool InitializeParseContextIndex() bool InitializeParseContextIndex()
{ {
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
//
// Allocate a TLS index.
//
GlobalParseContextIndex = OS_AllocTLSIndex(); GlobalParseContextIndex = OS_AllocTLSIndex();
return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
return true;
} }
bool FreeParseContextIndex() void FreeParseContextIndex()
{ {
OS_TLSIndex tlsiIndex = GlobalParseContextIndex; assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
return false;
}
OS_FreeTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = OS_INVALID_TLS_INDEX; GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
return OS_FreeTLSIndex(tlsiIndex);
} }
bool InitializeGlobalParseContext() void SetGlobalParseContext(TParseContext* context)
{ {
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized"); OS_SetTLSValue(GlobalParseContextIndex, context);
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext != 0) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
TThreadParseContext *lpThreadData = new TThreadParseContext();
if (lpThreadData == 0) {
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
return false;
}
lpThreadData->lpGlobalParseContext = 0;
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
return true;
} }
bool FreeParseContext() TParseContext* GetGlobalParseContext()
{ {
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
assert(0 && "FreeParseContext(): Parse Context index not initalized"); return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext)
delete lpParseContext;
return true;
}
TParseContextPointer& GetGlobalParseContext()
{
//
// Minimal error checking for speed
//
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
return lpParseContext->lpGlobalParseContext;
} }
...@@ -8,19 +8,10 @@ ...@@ -8,19 +8,10 @@
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
bool InitializeParseContextIndex(); bool InitializeParseContextIndex();
bool FreeParseContextIndex(); void FreeParseContextIndex();
bool InitializeGlobalParseContext();
bool FreeParseContext();
struct TParseContext; struct TParseContext;
typedef TParseContext* TParseContextPointer; extern void SetGlobalParseContext(TParseContext* context);
extern TParseContextPointer& GetGlobalParseContext(); extern TParseContext* GetGlobalParseContext();
#define GlobalParseContext GetGlobalParseContext()
typedef struct TThreadParseContextRec
{
TParseContext *lpGlobalParseContext;
} TThreadParseContext;
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
...@@ -17,55 +17,32 @@ ...@@ -17,55 +17,32 @@
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
void InitializeGlobalPools()
{
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (globalPools)
return;
TThreadGlobalPools* threadData = new TThreadGlobalPools();
threadData->globalPoolAllocator = 0;
OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
{
// Release the allocated memory for this thread.
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (!globalPools)
return;
delete globalPools;
}
bool InitializePoolIndex() bool InitializePoolIndex()
{ {
// Allocate a TLS index. assert(PoolIndex == OS_INVALID_TLS_INDEX);
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
return false;
return true; PoolIndex = OS_AllocTLSIndex();
return PoolIndex != OS_INVALID_TLS_INDEX;
} }
void FreePoolIndex() void FreePoolIndex()
{ {
// Release the TLS index. assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_FreeTLSIndex(PoolIndex); OS_FreeTLSIndex(PoolIndex);
PoolIndex = OS_INVALID_TLS_INDEX;
} }
TPoolAllocator& GetGlobalPoolAllocator() TPoolAllocator* GetGlobalPoolAllocator()
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
return *threadData->globalPoolAllocator;
} }
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_SetTLSValue(PoolIndex, poolAllocator);
threadData->globalPoolAllocator = poolAllocator;
} }
// //
......
...@@ -219,14 +219,8 @@ private: ...@@ -219,14 +219,8 @@ private:
// different times. But a simple use is to have a global pop // different times. But a simple use is to have a global pop
// with everyone using the same global allocator. // with everyone using the same global allocator.
// //
extern TPoolAllocator& GetGlobalPoolAllocator(); extern TPoolAllocator* GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
#define GlobalPoolAllocator GetGlobalPoolAllocator()
struct TThreadGlobalPools
{
TPoolAllocator* globalPoolAllocator;
};
// //
// This STL compatible allocator is intended to be used as the allocator // This STL compatible allocator is intended to be used as the allocator
...@@ -253,7 +247,7 @@ public: ...@@ -253,7 +247,7 @@ public:
pointer address(reference x) const { return &x; } pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; }
pool_allocator() : allocator(&GlobalPoolAllocator) { } pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { }
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
......
...@@ -99,9 +99,7 @@ int ShInitialize() ...@@ -99,9 +99,7 @@ int ShInitialize()
// //
int ShFinalize() int ShFinalize()
{ {
if (!DetachProcess()) DetachProcess();
return 0;
return 1; return 1;
} }
...@@ -149,9 +147,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ...@@ -149,9 +147,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
ShShaderOutput output, ShShaderOutput output,
const ShBuiltInResources* resources) const ShBuiltInResources* resources)
{ {
if (!InitThread())
return 0;
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
TCompiler* compiler = base->getAsCompiler(); TCompiler* compiler = base->getAsCompiler();
if (compiler == 0) if (compiler == 0)
...@@ -190,9 +185,6 @@ int ShCompile( ...@@ -190,9 +185,6 @@ int ShCompile(
size_t numStrings, size_t numStrings,
int compileOptions) int compileOptions)
{ {
if (!InitThread())
return 0;
if (handle == 0) if (handle == 0)
return 0; return 0;
......
...@@ -41,9 +41,10 @@ ...@@ -41,9 +41,10 @@
// //
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbol(const TString *n) : name(n) { } TSymbol(const TString *n) : name(n) { }
virtual ~TSymbol() { /* don't delete name, it's from the pool */ } virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
const TString& getName() const { return *name; } const TString& getName() const { return *name; }
virtual const TString& getMangledName() const { return getName(); } virtual const TString& getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
...@@ -193,7 +194,7 @@ public: ...@@ -193,7 +194,7 @@ public:
typedef const tLevel::value_type tLevelPair; typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult; typedef std::pair<tLevel::iterator, bool> tInsertResult;
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbolTableLevel() { } TSymbolTableLevel() { }
~TSymbolTableLevel(); ~TSymbolTableLevel();
......
...@@ -19,7 +19,7 @@ class TType; ...@@ -19,7 +19,7 @@ class TType;
class TField class TField
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator); POOL_ALLOCATOR_NEW_DELETE();
TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {} TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {}
// TODO(alokp): We should only return const type. // TODO(alokp): We should only return const type.
...@@ -40,7 +40,7 @@ private: ...@@ -40,7 +40,7 @@ private:
typedef TVector<TField*> TFieldList; typedef TVector<TField*> TFieldList;
inline TFieldList* NewPoolTFieldList() inline TFieldList* NewPoolTFieldList()
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
return new(memory) TFieldList; return new(memory) TFieldList;
} }
...@@ -82,7 +82,7 @@ protected: ...@@ -82,7 +82,7 @@ protected:
class TStructure : public TFieldListCollection class TStructure : public TFieldListCollection
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator); POOL_ALLOCATOR_NEW_DELETE();
TStructure(const TString* name, TFieldList* fields) TStructure(const TString* name, TFieldList* fields)
: TFieldListCollection(name, fields), : TFieldListCollection(name, fields),
mDeepestNesting(0) { mDeepestNesting(0) {
...@@ -106,7 +106,7 @@ private: ...@@ -106,7 +106,7 @@ private:
class TInterfaceBlock : public TFieldListCollection class TInterfaceBlock : public TFieldListCollection
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator); POOL_ALLOCATOR_NEW_DELETE();
TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier) TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier)
: TFieldListCollection(name, fields), : TFieldListCollection(name, fields),
mInstanceName(instanceName), mInstanceName(instanceName),
...@@ -138,7 +138,7 @@ private: ...@@ -138,7 +138,7 @@ private:
class TType class TType
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TType() {} TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) : TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) :
type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), layoutQualifier(TLayoutQualifier::create()), arraySize(0), type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
......
...@@ -439,8 +439,8 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) ...@@ -439,8 +439,8 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
return true; return true;
bool valid = true; bool valid = true;
TSymbolTable& symbolTable = GlobalParseContext->symbolTable; TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
TSymbol* symbol = symbolTable.find(node->getName(), GlobalParseContext->shaderVersion); TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->shaderVersion);
ASSERT(symbol && symbol->isFunction()); ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol); TFunction* function = static_cast<TFunction*>(symbol);
for (ParamIndex::const_iterator i = pIndex.begin(); for (ParamIndex::const_iterator i = pIndex.begin();
......
...@@ -216,8 +216,7 @@ class TInfoSink; ...@@ -216,8 +216,7 @@ class TInfoSink;
// //
class TIntermNode { class TIntermNode {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermNode() { TIntermNode() {
// TODO: Move this to TSourceLoc constructor // TODO: Move this to TSourceLoc constructor
// after getting rid of TPublicType. // after getting rid of TPublicType.
...@@ -555,8 +554,7 @@ enum Visit ...@@ -555,8 +554,7 @@ enum Visit
class TIntermTraverser class TIntermTraverser
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit), preVisit(preVisit),
inVisit(inVisit), inVisit(inVisit),
......
...@@ -21,9 +21,9 @@ struct TVectorFields { ...@@ -21,9 +21,9 @@ struct TVectorFields {
class TInfoSink; class TInfoSink;
class TIntermediate { class TIntermediate {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink& i) : infoSink(i) { } TIntermediate(TInfoSink& i) : infoSink(i) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment