Expose the IntermNode tree generated in the compiler for testing

This refactoring makes it possible for tests to access the IntermNode
tree produced by compilation by calling compileTree(). Removing
ParseContext usage from OutputHLSL has the additional benefit of better
separation between parsing and output.

BUG=angle:916

Change-Id: Ib40954832316328772a5c1dcbbe6b46b238e4e65
Reviewed-on: https://chromium-review.googlesource.com/249723
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 9e64bcb..b8eebc9 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -125,7 +125,8 @@
       maxCallStackDepth(0),
       fragmentPrecisionHigh(false),
       clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
-      builtInFunctionEmulator(type)
+      builtInFunctionEmulator(type),
+      mSourcePath(NULL)
 {
 }
 
@@ -158,15 +159,19 @@
     return true;
 }
 
-bool TCompiler::compile(const char* const shaderStrings[],
-                        size_t numStrings,
-                        int compileOptions)
+TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
+    size_t numStrings, int compileOptions)
 {
-    TScopedPoolAllocator scopedAlloc(&allocator);
+    return compileTreeImpl(shaderStrings, numStrings, compileOptions);
+}
+
+TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
+    size_t numStrings, int compileOptions)
+{
     clearResults();
 
-    if (numStrings == 0)
-        return true;
+    ASSERT(numStrings > 0);
+    ASSERT(GetGlobalPoolAllocator());
 
     // Reset the extension behavior for each compilation unit.
     ResetExtensionBehavior(extensionBehavior);
@@ -176,11 +181,10 @@
         compileOptions |= SH_VALIDATE_LOOP_INDEXING;
 
     // First string is path of source file if flag is set. The actual source follows.
-    const char* sourcePath = NULL;
     size_t firstSource = 0;
     if (compileOptions & SH_SOURCE_PATH)
     {
-        sourcePath = shaderStrings[0];
+        mSourcePath = shaderStrings[0];
         ++firstSource;
     }
 
@@ -188,7 +192,7 @@
     TIntermediate intermediate(infoSink);
     TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
                                shaderType, shaderSpec, compileOptions, true,
-                               sourcePath, infoSink, debugShaderPrecision);
+                               infoSink, debugShaderPrecision);
 
     parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
     SetGlobalParseContext(&parseContext);
@@ -210,6 +214,8 @@
         success = false;
     }
 
+    TIntermNode *root = NULL;
+
     if (success)
     {
         mPragma = parseContext.pragma();
@@ -218,7 +224,7 @@
             symbolTable.setGlobalInvariant();
         }
 
-        TIntermNode* root = parseContext.treeRoot;
+        root = parseContext.treeRoot;
         success = intermediate.postProcess(root);
 
         // Disallow expressions deemed too complex.
@@ -305,18 +311,37 @@
             RegenerateStructNames gen(symbolTable, shaderVersion);
             root->traverse(&gen);
         }
-
-        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
-            intermediate.outputTree(root);
-
-        if (success && (compileOptions & SH_OBJECT_CODE))
-            translate(root);
     }
 
-    // Cleanup. The IntermNode tree doesn't need to be deleted here, since the
-    // memory will be freed in a big chunk by the PoolAllocator.
     SetGlobalParseContext(NULL);
-    return success;
+    if (success)
+        return root;
+
+    return NULL;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+    size_t numStrings, int compileOptions)
+{
+    if (numStrings == 0)
+        return true;
+
+    TScopedPoolAllocator scopedAlloc(&allocator);
+    TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
+
+    if (root)
+    {
+        if (compileOptions & SH_INTERMEDIATE_TREE)
+            TIntermediate::outputTree(root, infoSink.info);
+
+        if (compileOptions & SH_OBJECT_CODE)
+            translate(root, compileOptions);
+
+        // The IntermNode tree doesn't need to be deleted here, since the
+        // memory will be freed in a big chunk by the PoolAllocator.
+        return true;
+    }
+    return false;
 }
 
 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
@@ -424,6 +449,8 @@
     builtInFunctionEmulator.Cleanup();
 
     nameMap.clear();
+
+    mSourcePath = NULL;
 }
 
 bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth)
@@ -602,6 +629,11 @@
     return extensionBehavior;
 }
 
+const char *TCompiler::getSourcePath() const
+{
+    return mSourcePath;
+}
+
 const ShBuiltInResources& TCompiler::getResources() const
 {
     return compileResources;
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index 21185af..842bc76 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -61,9 +61,15 @@
     virtual TCompiler* getAsCompiler() { return this; }
 
     bool Init(const ShBuiltInResources& resources);
+
+    // compileTreeForTesting should be used only when tests require access to
+    // the AST. Users of this function need to manually manage the global pool
+    // allocator. Returns NULL whenever there are compilation errors.
+    TIntermNode *compileTreeForTesting(const char* const shaderStrings[],
+        size_t numStrings, int compileOptions);
+
     bool compile(const char* const shaderStrings[],
-                 size_t numStrings,
-                 int compileOptions);
+        size_t numStrings, int compileOptions);
 
     // Get results of the last compilation.
     int getShaderVersion() const { return shaderVersion; }
@@ -105,7 +111,7 @@
     // Collect info for all attribs, uniforms, varyings.
     void collectVariables(TIntermNode* root);
     // Translate to object code.
-    virtual void translate(TIntermNode* root) = 0;
+    virtual void translate(TIntermNode *root, int compileOptions) = 0;
     // Returns true if, after applying the packing rules in the GLSL 1.017 spec
     // Appendix A, section 7, the shader does not use too many uniforms.
     bool enforcePackingRestrictions();
@@ -130,6 +136,7 @@
     bool limitExpressionComplexity(TIntermNode* root);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
+    const char *getSourcePath() const;
     const TPragma& getPragma() const { return mPragma; }
     void writePragma();
 
@@ -145,6 +152,9 @@
     std::vector<sh::InterfaceBlock> interfaceBlocks;
 
   private:
+    TIntermNode *compileTreeImpl(const char* const shaderStrings[],
+        size_t numStrings, int compileOptions);
+
     sh::GLenum shaderType;
     ShShaderSpec shaderSpec;
     ShShaderOutput outputType;
@@ -170,6 +180,7 @@
     // Results of compilation.
     int shaderVersion;
     TInfoSink infoSink;  // Output sink.
+    const char *mSourcePath; // Path of source file or NULL
 
     // name hashing.
     ShHashFunction64 hashFunction;
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 5f707c0..2d52900 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -36,6 +36,7 @@
 class TIntermSymbol;
 class TIntermLoop;
 class TInfoSink;
+class TInfoSinkBase;
 class TIntermRaw;
 
 //
diff --git a/src/compiler/translator/Intermediate.h b/src/compiler/translator/Intermediate.h
index c7250b8..cb5b060 100644
--- a/src/compiler/translator/Intermediate.h
+++ b/src/compiler/translator/Intermediate.h
@@ -55,7 +55,8 @@
     TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
     TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
     bool postProcess(TIntermNode *);
-    void outputTree(TIntermNode *);
+
+    static void outputTree(TIntermNode *, TInfoSinkBase &);
 
   private:
     void operator=(TIntermediate &); // prevent assignments
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 37e713b..045ea4c 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -95,12 +95,21 @@
     return false;
 }
 
-OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
+OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion,
+    const TExtensionBehavior &extensionBehavior,
+    const char *sourcePath, ShShaderOutput outputType,
+    int numRenderTargets, const std::vector<Uniform> &uniforms,
+    int compileOptions)
     : TIntermTraverser(true, true, true),
-      mContext(context),
-      mOutputType(parentTranslator->getOutputType())
+      mShaderType(shaderType),
+      mShaderVersion(shaderVersion),
+      mExtensionBehavior(extensionBehavior),
+      mSourcePath(sourcePath),
+      mOutputType(outputType),
+      mNumRenderTargets(numRenderTargets),
+      mCompileOptions(compileOptions)
 {
-    mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
+    mUnfoldShortCircuit = new UnfoldShortCircuit(this);
     mInsideFunction = false;
 
     mUsesFragColor = false;
@@ -116,9 +125,6 @@
     mUsesDiscardRewriting = false;
     mUsesNestedBreak = false;
 
-    const ShBuiltInResources &resources = parentTranslator->getResources();
-    mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
-
     mUniqueIndex = 0;
 
     mContainsLoopDiscontinuity = false;
@@ -130,11 +136,11 @@
     mExcessiveLoopIndex = NULL;
 
     mStructureHLSL = new StructureHLSL;
-    mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator);
+    mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms);
 
     if (mOutputType == SH_HLSL9_OUTPUT)
     {
-        if (mContext.shaderType == GL_FRAGMENT_SHADER)
+        if (mShaderType == GL_FRAGMENT_SHADER)
         {
             // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
             mUniformHLSL->reserveUniformRegisters(3);
@@ -157,26 +163,26 @@
     SafeDelete(mUniformHLSL);
 }
 
-void OutputHLSL::output()
+void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
 {
-    mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
-    mContainsAnyLoop = containsAnyLoop(mContext.treeRoot);
-    const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
+    mContainsLoopDiscontinuity = mShaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(treeRoot);
+    mContainsAnyLoop = containsAnyLoop(treeRoot);
+    const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(treeRoot);
     makeFlaggedStructMaps(flaggedStructs);
 
     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
     // use a vertex attribute as a condition, and some related computation in the else block.
-    if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER)
+    if (mOutputType == SH_HLSL9_OUTPUT && mShaderType == GL_VERTEX_SHADER)
     {
-        RewriteElseBlocks(mContext.treeRoot);
+        RewriteElseBlocks(treeRoot);
     }
 
     BuiltInFunctionEmulatorHLSL builtInFunctionEmulator;
-    builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(mContext.treeRoot);
+    builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot);
 
     // Output the body and footer first to determine what has to go in the header
     mInfoSinkStack.push(&mBody);
-    mContext.treeRoot->traverse(this);
+    treeRoot->traverse(this);
     mInfoSinkStack.pop();
 
     mInfoSinkStack.push(&mFooter);
@@ -190,10 +196,9 @@
     header(&builtInFunctionEmulator);
     mInfoSinkStack.pop();
 
-    TInfoSinkBase& sink = mContext.infoSink().obj;
-    sink << mHeader.c_str();
-    sink << mBody.c_str();
-    sink << mFooter.c_str();
+    objSink << mHeader.c_str();
+    objSink << mBody.c_str();
+    objSink << mFooter.c_str();
 
     builtInFunctionEmulator.Cleanup();
 }
@@ -353,16 +358,16 @@
            "#define FLATTEN\n"
            "#endif\n";
 
-    if (mContext.shaderType == GL_FRAGMENT_SHADER)
+    if (mShaderType == GL_FRAGMENT_SHADER)
     {
-        TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
-        const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
+        TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers");
+        const bool usingMRTExtension = (iter != mExtensionBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire));
 
         out << "// Varyings\n";
         out <<  varyings;
         out << "\n";
 
-        if (mContext.getShaderVersion() >= 300)
+        if (mShaderVersion >= 300)
         {
             for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
             {
@@ -2051,7 +2056,7 @@
 
                     bool bias = (arguments->size() > mandatoryArgumentCount);   // Bias argument is optional
 
-                    if (lod0 || mContext.shaderType == GL_VERTEX_SHADER)
+                    if (lod0 || mShaderType == GL_VERTEX_SHADER)
                     {
                         if (bias)
                         {
@@ -2180,7 +2185,7 @@
         // however flattening all the ifs in branch heavy shaders made D3D error too.
         // As a temporary workaround we flatten the ifs only if there is at least a loop
         // present somewhere in the shader.
-        if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
+        if (mShaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
         {
             out << "FLATTEN ";
         }
@@ -2649,16 +2654,16 @@
 
 void OutputHLSL::outputLineDirective(int line)
 {
-    if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+    if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0))
     {
         TInfoSinkBase &out = getInfoSink();
 
         out << "\n";
         out << "#line " << line;
 
-        if (mContext.sourcePath)
+        if (mSourcePath)
         {
-            out << " \"" << mContext.sourcePath << "\"";
+            out << " \"" << mSourcePath << "\"";
         }
 
         out << "\n";
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index db13d57..2ad0349 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -29,10 +29,15 @@
 class OutputHLSL : public TIntermTraverser
 {
   public:
-    OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator);
+    OutputHLSL(sh::GLenum shaderType, int shaderVersion,
+        const TExtensionBehavior &extensionBehavior,
+        const char *sourcePath, ShShaderOutput outputType,
+        int numRenderTargets, const std::vector<Uniform> &uniforms,
+        int compileOptions);
+
     ~OutputHLSL();
 
-    void output();
+    void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
 
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
     const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
@@ -76,8 +81,13 @@
     // Returns the function name
     TString addStructEqualityFunction(const TStructure &structure);
 
-    TParseContext &mContext;
+    sh::GLenum mShaderType;
+    int mShaderVersion;
+    const TExtensionBehavior &mExtensionBehavior;
+    const char *mSourcePath;
     const ShShaderOutput mOutputType;
+    int mCompileOptions;
+
     UnfoldShortCircuit *mUnfoldShortCircuit;
     bool mInsideFunction;
 
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index f38cc96..35de1b5 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -25,13 +25,12 @@
 // they can be passed to the parser without needing a global.
 //
 struct TParseContext {
-    TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is, bool debugShaderPrecisionSupported) :
+    TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink& is, bool debugShaderPrecisionSupported) :
             intermediate(interm),
             symbolTable(symt),
             shaderType(type),
             shaderSpec(spec),
             compileOptions(options),
-            sourcePath(sourcePath),
             treeRoot(0),
             loopNestingLevel(0),
             structNestingLevel(0),
@@ -51,7 +50,6 @@
     ShShaderSpec shaderSpec;              // The language specification compiler conforms to - GLES2 or WebGL.
     int shaderVersion;
     int compileOptions;
-    const char* sourcePath;      // Path of source file or NULL.
     TIntermNode* treeRoot;       // root of parse tree being created
     int loopNestingLevel;        // 0 if outside all loops
     int structNestingLevel;      // incremented while parsing a struct declaration
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index 5f064f9..3a611b8 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -14,7 +14,7 @@
     : TCompiler(type, spec, SH_ESSL_OUTPUT) {
 }
 
-void TranslatorESSL::translate(TIntermNode* root) {
+void TranslatorESSL::translate(TIntermNode *root, int) {
     TInfoSinkBase& sink = getInfoSink().obj;
 
     writePragma();
diff --git a/src/compiler/translator/TranslatorESSL.h b/src/compiler/translator/TranslatorESSL.h
index 8a94483..bab44fe 100644
--- a/src/compiler/translator/TranslatorESSL.h
+++ b/src/compiler/translator/TranslatorESSL.h
@@ -14,7 +14,7 @@
     TranslatorESSL(sh::GLenum type, ShShaderSpec spec);
 
 protected:
-    virtual void translate(TIntermNode* root);
+    virtual void translate(TIntermNode *root, int compileOptions);
 
 private:
     void writeExtensionBehavior();
diff --git a/src/compiler/translator/TranslatorGLSL.cpp b/src/compiler/translator/TranslatorGLSL.cpp
index 83c0a69..c47e8b5 100644
--- a/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/compiler/translator/TranslatorGLSL.cpp
@@ -15,7 +15,7 @@
     : TCompiler(type, spec, SH_GLSL_OUTPUT) {
 }
 
-void TranslatorGLSL::translate(TIntermNode* root) {
+void TranslatorGLSL::translate(TIntermNode *root, int) {
     TInfoSinkBase& sink = getInfoSink().obj;
 
     // Write GLSL version.
diff --git a/src/compiler/translator/TranslatorGLSL.h b/src/compiler/translator/TranslatorGLSL.h
index ada76b5..c202bde 100644
--- a/src/compiler/translator/TranslatorGLSL.h
+++ b/src/compiler/translator/TranslatorGLSL.h
@@ -15,7 +15,7 @@
     TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
 
   protected:
-    virtual void translate(TIntermNode *root);
+    virtual void translate(TIntermNode *root, int compileOptions);
 
   private:
     void writeVersion(TIntermNode *root);
diff --git a/src/compiler/translator/TranslatorHLSL.cpp b/src/compiler/translator/TranslatorHLSL.cpp
index 22bf60e..ca0ee80 100644
--- a/src/compiler/translator/TranslatorHLSL.cpp
+++ b/src/compiler/translator/TranslatorHLSL.cpp
@@ -6,7 +6,6 @@
 
 #include "compiler/translator/TranslatorHLSL.h"
 
-#include "compiler/translator/InitializeParseContext.h"
 #include "compiler/translator/OutputHLSL.h"
 
 TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
@@ -14,12 +13,15 @@
 {
 }
 
-void TranslatorHLSL::translate(TIntermNode *root)
+void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
 {
-    TParseContext& parseContext = *GetGlobalParseContext();
-    sh::OutputHLSL outputHLSL(parseContext, this);
+    const ShBuiltInResources &resources = getResources();
+    int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
 
-    outputHLSL.output();
+    sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
+        getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
+
+    outputHLSL.output(root, getInfoSink().obj);
 
     mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
     mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
diff --git a/src/compiler/translator/TranslatorHLSL.h b/src/compiler/translator/TranslatorHLSL.h
index 0024c22..1920ed5 100644
--- a/src/compiler/translator/TranslatorHLSL.h
+++ b/src/compiler/translator/TranslatorHLSL.h
@@ -22,7 +22,7 @@
     unsigned int getUniformRegister(const std::string &uniformName) const;
 
   protected:
-    virtual void translate(TIntermNode* root);
+    virtual void translate(TIntermNode *root, int compileOptions);
 
     std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
     std::map<std::string, unsigned int> mUniformRegisterMap;
diff --git a/src/compiler/translator/UnfoldShortCircuit.cpp b/src/compiler/translator/UnfoldShortCircuit.cpp
index c80336a..f79f9dd 100644
--- a/src/compiler/translator/UnfoldShortCircuit.cpp
+++ b/src/compiler/translator/UnfoldShortCircuit.cpp
@@ -16,7 +16,7 @@
 
 namespace sh
 {
-UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+UnfoldShortCircuit::UnfoldShortCircuit(OutputHLSL *outputHLSL) : mOutputHLSL(outputHLSL)
 {
     mTemporaryIndex = 0;
 }
diff --git a/src/compiler/translator/UnfoldShortCircuit.h b/src/compiler/translator/UnfoldShortCircuit.h
index 12ecd6a..eaceb0a 100644
--- a/src/compiler/translator/UnfoldShortCircuit.h
+++ b/src/compiler/translator/UnfoldShortCircuit.h
@@ -19,7 +19,7 @@
 class UnfoldShortCircuit : public TIntermTraverser
 {
   public:
-    UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL);
+    UnfoldShortCircuit(OutputHLSL *outputHLSL);
 
     void traverse(TIntermNode *node);
     bool visitBinary(Visit visit, TIntermBinary*);
@@ -29,7 +29,6 @@
     int getNextTemporaryIndex();
 
   protected:
-    TParseContext &mContext;
     OutputHLSL *const mOutputHLSL;
 
     int mTemporaryIndex;
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index 1517bfa..f22e0c6 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -11,7 +11,6 @@
 
 #include "common/utilities.h"
 #include "compiler/translator/StructureHLSL.h"
-#include "compiler/translator/TranslatorHLSL.h"
 #include "compiler/translator/UtilsHLSL.h"
 #include "compiler/translator/blocklayout.h"
 #include "compiler/translator/util.h"
@@ -61,13 +60,13 @@
     return DecoratePrivate(interfaceBlock.name()) + "_type";
 }
 
-UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator)
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms)
     : mUniformRegister(0),
       mInterfaceBlockRegister(0),
       mSamplerRegister(0),
       mStructureHLSL(structureHLSL),
-      mOutputType(translator->getOutputType()),
-      mUniforms(translator->getUniforms())
+      mOutputType(outputType),
+      mUniforms(uniforms)
 {}
 
 void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
diff --git a/src/compiler/translator/UniformHLSL.h b/src/compiler/translator/UniformHLSL.h
index 8dac639..1d875c1 100644
--- a/src/compiler/translator/UniformHLSL.h
+++ b/src/compiler/translator/UniformHLSL.h
@@ -19,7 +19,7 @@
 class UniformHLSL
 {
   public:
-    UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator);
+    UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms);
 
     void reserveUniformRegisters(unsigned int registerCount);
     void reserveInterfaceBlockRegisters(unsigned int registerCount);
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index 44a5c03..3d6a15a 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -613,14 +613,13 @@
 //
 // This function is the one to call externally to start the traversal.
 // Individual functions can be initialized to 0 to skip processing of that
-// type of node.  It's children will still be processed.
+// type of node. Its children will still be processed.
 //
-void TIntermediate::outputTree(TIntermNode *root)
+void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
 {
-    if (root == NULL)
-        return;
+    TOutputTraverser it(infoSink);
 
-    TOutputTraverser it(mInfoSink.info);
+    ASSERT(root);
 
     root->traverse(&it);
 }