translator: Add define to disable pool allocation.

This will help ASan find bugs in the translator when fuzzing, by making
separate allocations instead of using suballocations within the pool.

BUG=swiftshader:86

Change-Id: Ic59f7eef2c7985f7bf545d41be956df478331e2d
Reviewed-on: https://swiftshader-review.googlesource.com/13488
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Corentin Wallez <cwallez@google.com>
diff --git a/src/OpenGL/compiler/BUILD.gn b/src/OpenGL/compiler/BUILD.gn
index 3759f1c..3596e38 100644
--- a/src/OpenGL/compiler/BUILD.gn
+++ b/src/OpenGL/compiler/BUILD.gn
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 import("../../swiftshader.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
 
 # Need a separate config to ensure the warnings are added to the end.
 config("swiftshader_opengl_compiler_private_config") {
@@ -37,6 +38,10 @@
   }
 }
 
+config("swiftshader_translator_disable_pool_alloc") {
+    defines = [ "SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC" ]
+}
+
 swiftshader_source_set("swiftshader_opengl_compiler") {
   deps = [
     "preprocessor:swiftshader_opengl_preprocessor",
@@ -67,6 +72,10 @@
     "util.cpp",
   ]
 
+  if (use_fuzzing_engine) {
+    all_dependent_configs = [ ":swiftshader_translator_disable_pool_alloc" ]
+  }
+
   if (is_linux || is_mac) {
     sources += [ "ossource_posix.cpp" ]
   } else if (is_win) {
diff --git a/src/OpenGL/compiler/PoolAlloc.cpp b/src/OpenGL/compiler/PoolAlloc.cpp
index f3d19eb..1235023 100644
--- a/src/OpenGL/compiler/PoolAlloc.cpp
+++ b/src/OpenGL/compiler/PoolAlloc.cpp
@@ -57,27 +57,16 @@
 // is documented in PoolAlloc.h.
 //
 TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
-	pageSize(growthIncrement),
-	alignment(allocationAlignment),
+	alignment(allocationAlignment)
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	, pageSize(growthIncrement),
 	freeList(0),
 	inUseList(0),
 	numCalls(0),
 	totalBytes(0)
+#endif
 {
 	//
-	// Don't allow page sizes we know are smaller than all common
-	// OS page sizes.
-	//
-	if (pageSize < 4*1024)
-		pageSize = 4*1024;
-
-	//
-	// A large currentPageOffset indicates a new page needs to
-	// be obtained to allocate memory.
-	//
-	currentPageOffset = pageSize;
-
-	//
 	// Adjust alignment to be at least pointer aligned and
 	// power of 2.
 	//
@@ -91,6 +80,20 @@
 	alignment = a;
 	alignmentMask = a - 1;
 
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	//
+	// Don't allow page sizes we know are smaller than all common
+	// OS page sizes.
+	//
+	if (pageSize < 4*1024)
+		pageSize = 4*1024;
+
+	//
+	// A large currentPageOffset indicates a new page needs to
+	// be obtained to allocate memory.
+	//
+	currentPageOffset = pageSize;
+
 	//
 	// Align header skip
 	//
@@ -98,10 +101,14 @@
 	if (headerSkip < sizeof(tHeader)) {
 		headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
 	}
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	mStack.push_back({});
+#endif
 }
 
 TPoolAllocator::~TPoolAllocator()
 {
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
 	while (inUseList) {
 		tHeader* next = inUseList->nextPage;
 		inUseList->~tHeader();
@@ -118,6 +125,14 @@
 		delete [] reinterpret_cast<char*>(freeList);
 		freeList = next;
 	}
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	for (auto& allocs : mStack) {
+		for (auto alloc : allocs) {
+			free(alloc);
+		}
+	}
+	mStack.clear();
+#endif
 }
 
 // Support MSVC++ 6.0
@@ -158,14 +173,18 @@
 
 void TPoolAllocator::push()
 {
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
 	tAllocState state = { currentPageOffset, inUseList };
 
-	stack.push_back(state);
+	mStack.push_back(state);
 
 	//
 	// Indicate there is no current page to allocate from.
 	//
 	currentPageOffset = pageSize;
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	mStack.push_back({});
+#endif
 }
 
 //
@@ -177,11 +196,12 @@
 //
 void TPoolAllocator::pop()
 {
-	if (stack.size() < 1)
+	if (mStack.size() < 1)
 		return;
 
-	tHeader* page = stack.back().page;
-	currentPageOffset = stack.back().offset;
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	tHeader* page = mStack.back().page;
+	currentPageOffset = mStack.back().offset;
 
 	while (inUseList != page) {
 		// invoke destructor to free allocation list
@@ -197,7 +217,13 @@
 		inUseList = nextInUse;
 	}
 
-	stack.pop_back();
+	mStack.pop_back();
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	for (auto alloc : mStack.back()) {
+		free(alloc);
+	}
+	mStack.pop_back();
+#endif
 }
 
 //
@@ -206,12 +232,13 @@
 //
 void TPoolAllocator::popAll()
 {
-	while (stack.size() > 0)
+	while (mStack.size() > 0)
 		pop();
 }
 
 void* TPoolAllocator::allocate(size_t numBytes)
 {
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
 	//
 	// Just keep some interesting statistics.
 	//
@@ -288,6 +315,14 @@
 	currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
 
 	return initializeAllocation(inUseList, ret, numBytes);
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	void *alloc = malloc(numBytes + alignmentMask);
+	mStack.back().push_back(alloc);
+
+	intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
+	intAlloc = (intAlloc + alignmentMask) & ~alignmentMask;
+	return reinterpret_cast<void *>(intAlloc);
+#endif
 }
 
 
diff --git a/src/OpenGL/compiler/PoolAlloc.h b/src/OpenGL/compiler/PoolAlloc.h
index 1aca1c9..d645a04 100644
--- a/src/OpenGL/compiler/PoolAlloc.h
+++ b/src/OpenGL/compiler/PoolAlloc.h
@@ -160,7 +160,12 @@
 	// by calling pop(), and to not have to solve memory leak problems.
 	//
 
-protected:
+private:
+	size_t alignment; // all returned allocations will be aligned at
+                      // this granularity, which will be a power of 2
+	size_t alignmentMask;
+
+#if !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
 	friend struct tHeader;
 
 	struct tHeader {
@@ -203,20 +208,21 @@
 	}
 
 	size_t pageSize;        // granularity of allocation from the OS
-	size_t alignment;       // all returned allocations will be aligned at
-							// this granularity, which will be a power of 2
-	size_t alignmentMask;
 	size_t headerSkip;      // amount of memory to skip to make room for the
 							//      header (basically, size of header, rounded
 							//      up to make it aligned
 	size_t currentPageOffset;  // next offset in top of inUseList to allocate from
 	tHeader* freeList;      // list of popped memory
 	tHeader* inUseList;     // list of all memory currently being used
-	tAllocStack stack;      // stack of where to allocate from, to partition pool
+	tAllocStack mStack;     // stack of where to allocate from, to partition pool
 
 	int numCalls;           // just an interesting statistic
 	size_t totalBytes;      // just an interesting statistic
-private:
+
+#else  // !defined(SWIFTSHADER_TRANSLATOR_DISABLE_POOL_ALLOC)
+	std::vector<std::vector<void *>> mStack;
+#endif
+
 	TPoolAllocator& operator=(const TPoolAllocator&);  // dont allow assignment operator
 	TPoolAllocator(const TPoolAllocator&);  // dont allow default copy constructor
 };