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