1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // FunctionLookup.cpp: Used for storing function calls that have not yet been resolved during
7 // parsing.
8 //
9 
10 #include "compiler/translator/FunctionLookup.h"
11 #include "compiler/translator/ImmutableStringBuilder.h"
12 
13 namespace sh
14 {
15 
16 namespace
17 {
18 
19 const char kFunctionMangledNameSeparator = '(';
20 
21 constexpr const ImmutableString kEmptyName("");
22 
23 // Helper function for GetMangledNames
24 // Gets all ordered combinations of elements in list[currentIndex, end]
GetImplicitConversionCombinations(const std::vector<int> & list)25 std::vector<std::vector<int>> GetImplicitConversionCombinations(const std::vector<int> &list)
26 {
27     std::vector<std::vector<int>> target;
28     target.push_back(std::vector<int>());
29 
30     for (size_t currentIndex = 0; currentIndex < list.size(); currentIndex++)
31     {
32         size_t prevIterSize = target.size();
33         for (size_t copyIndex = 0; copyIndex < prevIterSize; copyIndex++)
34         {
35             std::vector<int> combination = target[copyIndex];
36             combination.push_back(list[currentIndex]);
37             target.push_back(combination);
38         }
39     }
40 
41     return target;
42 }
43 
44 }  // anonymous namespace
45 
TFunctionLookup(const ImmutableString & name,const TType * constructorType,const TSymbol * symbol)46 TFunctionLookup::TFunctionLookup(const ImmutableString &name,
47                                  const TType *constructorType,
48                                  const TSymbol *symbol)
49     : mName(name), mConstructorType(constructorType), mThisNode(nullptr), mSymbol(symbol)
50 {}
51 
52 // static
CreateConstructor(const TType * type)53 TFunctionLookup *TFunctionLookup::CreateConstructor(const TType *type)
54 {
55     ASSERT(type != nullptr);
56     return new TFunctionLookup(kEmptyName, type, nullptr);
57 }
58 
59 // static
CreateFunctionCall(const ImmutableString & name,const TSymbol * symbol)60 TFunctionLookup *TFunctionLookup::CreateFunctionCall(const ImmutableString &name,
61                                                      const TSymbol *symbol)
62 {
63     ASSERT(name != "");
64     return new TFunctionLookup(name, nullptr, symbol);
65 }
66 
name() const67 const ImmutableString &TFunctionLookup::name() const
68 {
69     return mName;
70 }
71 
getMangledName() const72 ImmutableString TFunctionLookup::getMangledName() const
73 {
74     return GetMangledName(mName.data(), mArguments);
75 }
76 
GetMangledName(const char * functionName,const TIntermSequence & arguments)77 ImmutableString TFunctionLookup::GetMangledName(const char *functionName,
78                                                 const TIntermSequence &arguments)
79 {
80     std::string newName(functionName);
81     newName += kFunctionMangledNameSeparator;
82 
83     for (TIntermNode *argument : arguments)
84     {
85         newName += argument->getAsTyped()->getType().getMangledName();
86     }
87     return ImmutableString(newName);
88 }
89 
GetMangledNames(const char * functionName,const TIntermSequence & arguments)90 std::vector<ImmutableString> GetMangledNames(const char *functionName,
91                                              const TIntermSequence &arguments)
92 {
93     std::vector<ImmutableString> target;
94 
95     std::vector<int> indexes;
96     for (int i = 0; i < static_cast<int>(arguments.size()); i++)
97     {
98         TIntermNode *argument = arguments[i];
99         TBasicType argType    = argument->getAsTyped()->getType().getBasicType();
100         if (argType == EbtInt || argType == EbtUInt)
101         {
102             indexes.push_back(i);
103         }
104     }
105 
106     std::vector<std::vector<int>> combinations = GetImplicitConversionCombinations(indexes);
107     for (const std::vector<int> &combination : combinations)
108     {
109         // combination: ordered list of indexes for arguments that should be converted to float
110         std::string newName(functionName);
111         newName += kFunctionMangledNameSeparator;
112         // combination[currentIndex] represents index of next argument to be converted
113         int currentIndex = 0;
114         for (int i = 0; i < (int)arguments.size(); i++)
115         {
116             TIntermNode *argument = arguments[i];
117 
118             if (currentIndex != static_cast<int>(combination.size()) &&
119                 combination[currentIndex] == i)
120             {
121                 // Convert
122                 TType type = argument->getAsTyped()->getType();
123                 type.setBasicType(EbtFloat);
124                 newName += type.getMangledName();
125                 currentIndex++;
126             }
127             else
128             {
129                 // Don't convert
130                 newName += argument->getAsTyped()->getType().getMangledName();
131             }
132         }
133         target.push_back(ImmutableString(newName));
134     }
135 
136     return target;
137 }
138 
getMangledNamesForImplicitConversions() const139 std::vector<ImmutableString> TFunctionLookup::getMangledNamesForImplicitConversions() const
140 {
141     return GetMangledNames(mName.data(), mArguments);
142 }
143 
isConstructor() const144 bool TFunctionLookup::isConstructor() const
145 {
146     return mConstructorType != nullptr;
147 }
148 
constructorType() const149 const TType &TFunctionLookup::constructorType() const
150 {
151     return *mConstructorType;
152 }
153 
setThisNode(TIntermTyped * thisNode)154 void TFunctionLookup::setThisNode(TIntermTyped *thisNode)
155 {
156     mThisNode = thisNode;
157 }
158 
thisNode() const159 TIntermTyped *TFunctionLookup::thisNode() const
160 {
161     return mThisNode;
162 }
163 
addArgument(TIntermTyped * argument)164 void TFunctionLookup::addArgument(TIntermTyped *argument)
165 {
166     mArguments.push_back(argument);
167 }
168 
arguments()169 TIntermSequence &TFunctionLookup::arguments()
170 {
171     return mArguments;
172 }
173 
symbol() const174 const TSymbol *TFunctionLookup::symbol() const
175 {
176     return mSymbol;
177 }
178 
179 }  // namespace sh
180