Change TSymbolTable::insertBuiltIn() TType* pointers to const.

Const types make it possible to implement caching and
other optimizations.

BUG=492725

Change-Id: I64398bb9effcc909dd052a038acbb5ec0ca730e8
Reviewed-on: https://chromium-review.googlesource.com/281046
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Dmitry Skiba <dskiba@google.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 8e95560..2d08172 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -557,7 +557,7 @@
     bool arrayArg = false;
     for (size_t i = 0; i < function.getParamCount(); ++i)
     {
-        const TParameter &param = function.getParam(i);
+        const TConstParameter &param = function.getParam(i);
         size += param.type->getObjectSize();
 
         if (constructingMatrix && param.type->isMatrix())
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 9525040..cc6879e 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -139,7 +139,7 @@
     return false;
 }
 
-TType *SpecificType(TType *type, int size)
+const TType *SpecificType(const TType *type, int size)
 {
     ASSERT(size >= 1 && size <= 4);
 
@@ -160,7 +160,7 @@
     }
 }
 
-TType *VectorType(TType *type, int size)
+const TType *VectorType(const TType *type, int size)
 {
     ASSERT(size >= 2 && size <= 4);
 
@@ -181,8 +181,8 @@
     }
 }
 
-void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name,
-                                 TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5)
+void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
+                                 const TType *ptype1, const TType *ptype2, const TType *ptype3, const TType *ptype4, const TType *ptype5)
 {
     if (ptype1->getBasicType() == EbtGSampler2D)
     {
@@ -231,31 +231,26 @@
     {
         TFunction *function = new TFunction(NewPoolTString(name), *rvalue, op, ext);
 
-        TParameter param1 = {0, ptype1};
-        function->addParameter(param1);
+        function->addParameter(TConstParameter(ptype1));
 
         if (ptype2)
         {
-            TParameter param2 = {0, ptype2};
-            function->addParameter(param2);
+            function->addParameter(TConstParameter(ptype2));
         }
 
         if (ptype3)
         {
-            TParameter param3 = {0, ptype3};
-            function->addParameter(param3);
+            function->addParameter(TConstParameter(ptype3));
         }
 
         if (ptype4)
         {
-            TParameter param4 = {0, ptype4};
-            function->addParameter(param4);
+            function->addParameter(TConstParameter(ptype4));
         }
 
         if (ptype5)
         {
-            TParameter param5 = {0, ptype5};
-            function->addParameter(param5);
+            function->addParameter(TConstParameter(ptype5));
         }
 
         insert(level, function);
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 8ccb443..fe2e9ec 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -163,10 +163,55 @@
     TConstantUnion *unionArray;
 };
 
+// Immutable version of TParameter.
+struct TConstParameter
+{
+    TConstParameter()
+        : name(nullptr),
+          type(nullptr)
+    {
+    }
+    explicit TConstParameter(const TString *n)
+        : name(n),
+          type(nullptr)
+    {
+    }
+    explicit TConstParameter(const TType *t)
+        : name(nullptr),
+          type(t)
+    {
+    }
+    TConstParameter(const TString *n, const TType *t)
+        : name(n),
+          type(t)
+    {
+    }
+
+    // Both constructor arguments must be const.
+    TConstParameter(TString *n, TType *t) = delete;
+    TConstParameter(const TString *n, TType *t) = delete;
+    TConstParameter(TString *n, const TType *t) = delete;
+
+    const TString *name;
+    const TType *type;
+};
+
 // The function sub-class of symbols and the parser will need to
 // share this definition of a function parameter.
 struct TParameter
 {
+    // Destructively converts to TConstParameter.
+    // This method resets name and type to nullptrs to make sure
+    // their content cannot be modified after the call.
+    TConstParameter turnToConst()
+    {
+        const TString *constName = name;
+        const TType *constType = type;
+        name = nullptr;
+        type = nullptr;
+        return TConstParameter(constName, constType);
+    }
+
     TString *name;
     TType *type;
 };
@@ -206,7 +251,7 @@
         return TString(mangledName.c_str(), mangledName.find_first_of('('));
     }
 
-    void addParameter(TParameter &p)
+    void addParameter(const TConstParameter &p)
     { 
         parameters.push_back(p);
         mangledName = mangledName + p.type->getMangledName();
@@ -239,13 +284,13 @@
     {
         return parameters.size();
     }
-    const TParameter &getParam(size_t i) const
+    const TConstParameter &getParam(size_t i) const
     {
         return parameters[i];
     }
 
   private:
-    typedef TVector<TParameter> TParamList;
+    typedef TVector<TConstParameter> TParamList;
     TParamList parameters;
     TType returnType;
     TString mangledName;
@@ -368,23 +413,23 @@
         return insert(level, constant);
     }
 
-    void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name,
-                       TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0);
+    void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
+                       const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0);
 
-    void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name,
-                       TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+    void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name,
+                       const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     {
         insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     }
 
-    void insertBuiltIn(ESymbolLevel level, const char *ext, TType *rvalue, const char *name,
-                       TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+    void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name,
+                       const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     {
         insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     }
 
-    void insertBuiltIn(ESymbolLevel level, TOperator op, TType *rvalue, const char *name,
-                       TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+    void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name,
+                       const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     {
         insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     }
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 651c925..0e1fb7d 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -401,7 +401,7 @@
         structure = s;
     }
 
-    const TString &getMangledName()
+    const TString &getMangledName() const
     {
         if (mangled.empty())
         {
diff --git a/src/compiler/translator/ValidateLimitations.cpp b/src/compiler/translator/ValidateLimitations.cpp
index efb0601..f8d2306 100644
--- a/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/compiler/translator/ValidateLimitations.cpp
@@ -400,7 +400,7 @@
     for (ParamIndex::const_iterator i = pIndex.begin();
          i != pIndex.end(); ++i)
     {
-        const TParameter &param = function->getParam(*i);
+        const TConstParameter &param = function->getParam(*i);
         TQualifier qual = param.type->getQualifier();
         if ((qual == EvqOut) || (qual == EvqInOut))
         {
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 4a540ae..94f578f 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -338,14 +338,14 @@
 
 function_call_header_with_parameters
     : function_call_header assignment_expression {
-        TParameter param = { 0, new TType($2->getType()) };
-        $1->addParameter(param);
+        const TType *type = new TType($2->getType());
+        $1->addParameter(TConstParameter(type));
         $$.function = $1;
         $$.nodePair.node1 = $2;
     }
     | function_call_header_with_parameters COMMA assignment_expression {
-        TParameter param = { 0, new TType($3->getType()) };
-        $1.function->addParameter(param);
+        const TType *type = new TType($3->getType());
+        $1.function->addParameter(TConstParameter(type));
         $$.function = $1.function;
         $$.nodePair.node1 = context->intermediate.growAggregate($1.intermNode, $3, @2);
     }
@@ -608,7 +608,7 @@
         
         for (size_t i = 0; i < function.getParamCount(); i++)
         {
-            const TParameter &param = function.getParam(i);
+            const TConstParameter &param = function.getParam(i);
             if (param.name != 0)
             {
                 TVariable variable(param.name, *param.type);
@@ -732,7 +732,7 @@
         // Add the parameter
         $$ = $1;
         if ($2.param.type->getBasicType() != EbtVoid)
-            $1->addParameter($2.param);
+            $1->addParameter($2.param.turnToConst());
         else
             delete $2.param.type;
     }
@@ -751,7 +751,7 @@
         } else {
             // Add the parameter
             $$ = $1;
-            $1->addParameter($3.param);
+            $1->addParameter($3.param.turnToConst());
         }
     }
     ;
@@ -1719,7 +1719,7 @@
         //
         TIntermAggregate* paramNodes = new TIntermAggregate;
         for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TParameter& param = function->getParam(i);
+            const TConstParameter& param = function->getParam(i);
             if (param.name != 0) {
                 TVariable *variable = new TVariable(param.name, *param.type);
                 //
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 23bb762..3b407cc 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -2560,8 +2560,8 @@
   case 25:
 
     {
-        TParameter param = { 0, new TType((yyvsp[0].interm.intermTypedNode)->getType()) };
-        (yyvsp[-1].interm.function)->addParameter(param);
+        const TType *type = new TType((yyvsp[0].interm.intermTypedNode)->getType());
+        (yyvsp[-1].interm.function)->addParameter(TConstParameter(type));
         (yyval.interm).function = (yyvsp[-1].interm.function);
         (yyval.interm).nodePair.node1 = (yyvsp[0].interm.intermTypedNode);
     }
@@ -2571,8 +2571,8 @@
   case 26:
 
     {
-        TParameter param = { 0, new TType((yyvsp[0].interm.intermTypedNode)->getType()) };
-        (yyvsp[-2].interm).function->addParameter(param);
+        const TType *type = new TType((yyvsp[0].interm.intermTypedNode)->getType());
+        (yyvsp[-2].interm).function->addParameter(TConstParameter(type));
         (yyval.interm).function = (yyvsp[-2].interm).function;
         (yyval.interm).nodePair.node1 = context->intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
@@ -3075,7 +3075,7 @@
         
         for (size_t i = 0; i < function.getParamCount(); i++)
         {
-            const TParameter &param = function.getParam(i);
+            const TConstParameter &param = function.getParam(i);
             if (param.name != 0)
             {
                 TVariable variable(param.name, *param.type);
@@ -3239,7 +3239,7 @@
         // Add the parameter
         (yyval.interm.function) = (yyvsp[-1].interm.function);
         if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid)
-            (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param);
+            (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
         else
             delete (yyvsp[0].interm).param.type;
     }
@@ -3263,7 +3263,7 @@
         } else {
             // Add the parameter
             (yyval.interm.function) = (yyvsp[-2].interm.function);
-            (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param);
+            (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
         }
     }
 
@@ -4957,7 +4957,7 @@
         //
         TIntermAggregate* paramNodes = new TIntermAggregate;
         for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TParameter& param = function->getParam(i);
+            const TConstParameter& param = function->getParam(i);
             if (param.name != 0) {
                 TVariable *variable = new TVariable(param.name, *param.type);
                 //