blob: 1b3a249b56ad9042bd3b694564a3f98f0d544c70 [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org07620a52010-09-23 17:53:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
zmo@google.com32e97312011-08-24 01:03:11 +00007#include "compiler/BuiltInFunctionEmulator.h"
zmo@google.comb1762df2011-07-30 02:04:23 +00008#include "compiler/DetectRecursion.h"
zmo@google.com0c6bb7a2011-08-17 19:39:58 +00009#include "compiler/ForLoopUnroll.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000010#include "compiler/Initialize.h"
alokp@chromium.org8b851c62012-06-15 16:25:11 +000011#include "compiler/InitializeParseContext.h"
zmo@google.comb9f64aa2012-01-20 00:35:15 +000012#include "compiler/MapLongVariableNames.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000013#include "compiler/ParseHelper.h"
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000014#include "compiler/RenameFunction.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000015#include "compiler/ShHandle.h"
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000016#include "compiler/ValidateLimitations.h"
gman@chromium.org8d804792012-10-17 21:33:48 +000017#include "compiler/VariablePacker.h"
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +000018#include "compiler/depgraph/DependencyGraph.h"
19#include "compiler/depgraph/DependencyGraphOutput.h"
20#include "compiler/timing/RestrictFragmentShaderTiming.h"
21#include "compiler/timing/RestrictVertexShaderTiming.h"
shannon.woods@transgaming.comda1ed362013-01-25 21:54:57 +000022#include "third_party/compiler/ArrayBoundsClamper.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000023
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000024bool isWebGLBasedSpec(ShShaderSpec spec)
25{
26 return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
27}
28
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000029namespace {
30bool InitializeSymbolTable(
31 const TBuiltInStrings& builtInStrings,
32 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
33 TInfoSink& infoSink, TSymbolTable& symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +000034{
35 TIntermediate intermediate(infoSink);
36 TExtensionBehavior extBehavior;
zmo@google.com09c323a2011-08-12 18:22:25 +000037 InitExtensionBehavior(resources, extBehavior);
zmo@google.comdc4b4f82011-06-17 00:42:53 +000038 // The builtins deliberately don't specify precisions for the function
39 // arguments and return types. For that reason we don't try to check them.
40 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +000041 parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.org07620a52010-09-23 17:53:56 +000042
43 GlobalParseContext = &parseContext;
44
alokp@chromium.org07620a52010-09-23 17:53:56 +000045 assert(symbolTable.isEmpty());
46 //
47 // Parse the built-ins. This should only happen once per
48 // language symbol table.
49 //
50 // Push the symbol table to give it an initial scope. This
51 // push should not have a corresponding pop, so that built-ins
52 // are preserved, and the test for an empty table fails.
53 //
alokp@chromium.org07620a52010-09-23 17:53:56 +000054
shannonwoods@chromium.org6e10a0e2013-05-30 00:02:13 +000055 symbolTable.push(); // TODO: Common built-ins.
56
57 // GLSL ES 1.0 built-ins
58 symbolTable.push();
alokp@chromium.org07620a52010-09-23 17:53:56 +000059 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
60 {
alokp@chromium.org570bfc72010-09-24 17:19:25 +000061 const char* builtInShaders = i->c_str();
62 int builtInLengths = static_cast<int>(i->size());
63 if (builtInLengths <= 0)
64 continue;
alokp@chromium.org07620a52010-09-23 17:53:56 +000065
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000066 if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
alokp@chromium.org07620a52010-09-23 17:53:56 +000067 {
68 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
69 return false;
70 }
71 }
72
shannonwoods@chromium.org6e10a0e2013-05-30 00:02:13 +000073 symbolTable.push(); // TODO: GLSL ES 3.0 built-ins.
74
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000075 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000076
alokp@chromium.org07620a52010-09-23 17:53:56 +000077 return true;
78}
79
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000080class TScopedPoolAllocator {
81public:
82 TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
83 : mAllocator(allocator), mPushPopAllocator(pushPop) {
84 if (mPushPopAllocator) mAllocator->push();
85 SetGlobalPoolAllocator(mAllocator);
86 }
87 ~TScopedPoolAllocator() {
88 SetGlobalPoolAllocator(NULL);
89 if (mPushPopAllocator) mAllocator->pop();
90 }
91
92private:
93 TPoolAllocator* mAllocator;
94 bool mPushPopAllocator;
95};
96} // namespace
97
98TShHandleBase::TShHandleBase() {
99 allocator.push();
100 SetGlobalPoolAllocator(&allocator);
101}
102
103TShHandleBase::~TShHandleBase() {
104 SetGlobalPoolAllocator(NULL);
105 allocator.popAll();
106}
107
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000108TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
109 : shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +0000110 shaderSpec(spec),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000111 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000112 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
zmo@google.com9996b8e2012-01-19 01:43:55 +0000113 builtInFunctionEmulator(type)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000114{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000115 longNameMap = LongNameMap::GetInstance();
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000116}
117
118TCompiler::~TCompiler()
119{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000120 ASSERT(longNameMap);
121 longNameMap->Release();
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000122}
123
124bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000125{
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000126 shaderVersion = 100;
gman@chromium.org8d804792012-10-17 21:33:48 +0000127 maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
128 resources.MaxVertexUniformVectors :
129 resources.MaxFragmentUniformVectors;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000130 TScopedPoolAllocator scopedAlloc(&allocator, false);
131
alokp@chromium.org07620a52010-09-23 17:53:56 +0000132 // Generate built-in symbol table.
133 if (!InitBuiltInSymbolTable(resources))
134 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000135 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000136 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000137
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000138 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
139 clampingStrategy = resources.ArrayIndexClampingStrategy;
140
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000141 hashFunction = resources.HashFunction;
142
alokp@chromium.org07620a52010-09-23 17:53:56 +0000143 return true;
144}
145
146bool TCompiler::compile(const char* const shaderStrings[],
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000147 size_t numStrings,
alokp@chromium.org07620a52010-09-23 17:53:56 +0000148 int compileOptions)
149{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000150 TScopedPoolAllocator scopedAlloc(&allocator, true);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000151 clearResults();
152
153 if (numStrings == 0)
154 return true;
155
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000156 // If compiling for WebGL, validate loop and indexing as well.
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000157 if (isWebGLBasedSpec(shaderSpec))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000158 compileOptions |= SH_VALIDATE_LOOP_INDEXING;
alokp@chromium.org1f299542010-11-12 15:50:23 +0000159
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000160 // First string is path of source file if flag is set. The actual source follows.
161 const char* sourcePath = NULL;
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000162 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000163 if (compileOptions & SH_SOURCE_PATH)
164 {
165 sourcePath = shaderStrings[0];
166 ++firstSource;
167 }
168
alokp@chromium.org07620a52010-09-23 17:53:56 +0000169 TIntermediate intermediate(infoSink);
170 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
zmo@google.comdc4b4f82011-06-17 00:42:53 +0000171 shaderType, shaderSpec, compileOptions, true,
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000172 sourcePath, infoSink);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000173 parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000174 GlobalParseContext = &parseContext;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000175
176 // We preserve symbols at the built-in level from compile-to-compile.
177 // Start pushing the user-defined symbols at global level.
178 symbolTable.push();
179 if (!symbolTable.atGlobalLevel())
180 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
181
182 // Parse shader.
183 bool success =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000184 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
alokp@chromium.org07620a52010-09-23 17:53:56 +0000185 (parseContext.treeRoot != NULL);
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000186
shannon.woods%transgaming.com@gtempaccount.com5524db02013-04-13 03:38:16 +0000187 shaderVersion = parseContext.getShaderVersion();
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000188
alokp@chromium.org07620a52010-09-23 17:53:56 +0000189 if (success) {
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000190 TIntermNode* root = parseContext.treeRoot;
191 success = intermediate.postProcess(root);
192
zmo@google.comb1762df2011-07-30 02:04:23 +0000193 if (success)
194 success = detectRecursion(root);
195
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000196 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
197 success = validateLimitations(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000198
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000199 if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000200 success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000201
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000202 if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
203 rewriteCSSShader(root);
204
zmo@google.com0c6bb7a2011-08-17 19:39:58 +0000205 // Unroll for-loop markup needs to happen after validateLimitations pass.
206 if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
207 ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
208
zmo@google.com32e97312011-08-24 01:03:11 +0000209 // Built-in function emulation needs to happen after validateLimitations pass.
210 if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
211 builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
212
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000213 // Clamping uniform array bounds needs to happen after validateLimitations pass.
214 if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
215 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
216
zmo@google.comfd747b82011-04-23 01:30:07 +0000217 // Call mapLongVariableNames() before collectAttribsUniforms() so in
218 // collectAttribsUniforms() we already have the mapped symbol names and
219 // we could composite mapped and original variable names.
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000220 // Also, if we hash all the names, then no need to do this for long names.
221 if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
zmo@google.comfd747b82011-04-23 01:30:07 +0000222 mapLongVariableNames(root);
223
gman@chromium.org8d804792012-10-17 21:33:48 +0000224 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
zmo@google.comfd747b82011-04-23 01:30:07 +0000225 collectAttribsUniforms(root);
gman@chromium.org8d804792012-10-17 21:33:48 +0000226 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
227 success = enforcePackingRestrictions();
228 if (!success) {
229 infoSink.info.message(EPrefixError, "too many uniforms");
230 }
231 }
232 }
zmo@google.comfd747b82011-04-23 01:30:07 +0000233
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000234 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000235 intermediate.outputTree(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000236
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000237 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000238 translate(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000239 }
240
241 // Cleanup memory.
242 intermediate.remove(parseContext.treeRoot);
243 // Ensure symbol table is returned to the built-in level,
244 // throwing away all but the built-ins.
245 while (!symbolTable.atBuiltInLevel())
246 symbolTable.pop();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000247
248 return success;
249}
250
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000251bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000252{
253 TBuiltIns builtIns;
254
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000255 compileResources = resources;
shannon.woods%transgaming.com@gtempaccount.com5209de82013-04-13 03:41:53 +0000256 builtIns.initialize(shaderType, shaderSpec, resources, extensionBehavior);
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000257 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
258 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000259}
260
261void TCompiler::clearResults()
262{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000263 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000264 infoSink.info.erase();
265 infoSink.obj.erase();
266 infoSink.debug.erase();
267
268 attribs.clear();
269 uniforms.clear();
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000270
271 builtInFunctionEmulator.Cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000272
273 nameMap.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000274}
275
zmo@google.comb1762df2011-07-30 02:04:23 +0000276bool TCompiler::detectRecursion(TIntermNode* root)
277{
278 DetectRecursion detect;
279 root->traverse(&detect);
280 switch (detect.detectRecursion()) {
281 case DetectRecursion::kErrorNone:
282 return true;
283 case DetectRecursion::kErrorMissingMain:
284 infoSink.info.message(EPrefixError, "Missing main()");
285 return false;
286 case DetectRecursion::kErrorRecursion:
287 infoSink.info.message(EPrefixError, "Function recursion detected");
288 return false;
289 default:
290 UNREACHABLE();
291 return false;
292 }
293}
294
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000295void TCompiler::rewriteCSSShader(TIntermNode* root)
296{
297 RenameFunction renamer("main(", "css_main(");
298 root->traverse(&renamer);
299}
300
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000301bool TCompiler::validateLimitations(TIntermNode* root) {
302 ValidateLimitations validate(shaderType, infoSink.info);
303 root->traverse(&validate);
304 return validate.numErrors() == 0;
305}
306
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000307bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000308{
309 if (shaderSpec != SH_WEBGL_SPEC) {
310 infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
311 return false;
312 }
313
314 if (shaderType == SH_FRAGMENT_SHADER) {
315 TDependencyGraph graph(root);
316
317 // Output any errors first.
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000318 bool success = enforceFragmentShaderTimingRestrictions(graph);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000319
320 // Then, output the dependency graph.
321 if (outputGraph) {
322 TDependencyGraphOutput output(infoSink.info);
323 output.outputAllSpanningTrees(graph);
324 }
325
326 return success;
327 }
328 else {
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000329 return enforceVertexShaderTimingRestrictions(root);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000330 }
331}
332
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000333bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000334{
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000335 RestrictFragmentShaderTiming restrictor(infoSink.info);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000336 restrictor.enforceRestrictions(graph);
337 return restrictor.numErrors() == 0;
338}
339
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000340bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000341{
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000342 RestrictVertexShaderTiming restrictor(infoSink.info);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000343 restrictor.enforceRestrictions(root);
344 return restrictor.numErrors() == 0;
345}
346
alokp@chromium.org07620a52010-09-23 17:53:56 +0000347void TCompiler::collectAttribsUniforms(TIntermNode* root)
348{
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000349 CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000350 root->traverse(&collect);
351}
zmo@google.comfd747b82011-04-23 01:30:07 +0000352
gman@chromium.org8d804792012-10-17 21:33:48 +0000353bool TCompiler::enforcePackingRestrictions()
354{
355 VariablePacker packer;
356 return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
357}
358
zmo@google.comfd747b82011-04-23 01:30:07 +0000359void TCompiler::mapLongVariableNames(TIntermNode* root)
360{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000361 ASSERT(longNameMap);
362 MapLongVariableNames map(longNameMap);
zmo@google.com9996b8e2012-01-19 01:43:55 +0000363 root->traverse(&map);
zmo@google.comfd747b82011-04-23 01:30:07 +0000364}
365
366int TCompiler::getMappedNameMaxLength() const
367{
kbr@chromium.org22152112011-10-26 01:18:28 +0000368 return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
zmo@google.comfd747b82011-04-23 01:30:07 +0000369}
zmo@google.com5601ea02011-06-10 18:23:25 +0000370
371const TExtensionBehavior& TCompiler::getExtensionBehavior() const
372{
373 return extensionBehavior;
374}
zmo@google.com32e97312011-08-24 01:03:11 +0000375
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000376const ShBuiltInResources& TCompiler::getResources() const
377{
378 return compileResources;
379}
380
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000381const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
382{
383 return arrayBoundsClamper;
384}
385
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000386ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
387{
388 return clampingStrategy;
389}
390
391const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
392{
393 return builtInFunctionEmulator;
394}