blob: 322595b78a952e44634444a9721202d1a513e3e2 [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
2// Copyright (c) 2002-2010 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
7#include "compiler/Initialize.h"
8#include "compiler/ParseHelper.h"
9#include "compiler/ShHandle.h"
10
11static bool InitializeSymbolTable(
12 const TBuiltInStrings& builtInStrings,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000013 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
alokp@chromium.org07620a52010-09-23 17:53:56 +000014 TInfoSink& infoSink, TSymbolTable& symbolTable)
15{
16 TIntermediate intermediate(infoSink);
17 TExtensionBehavior extBehavior;
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000018 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000019
20 GlobalParseContext = &parseContext;
21
alokp@chromium.org07620a52010-09-23 17:53:56 +000022 assert(symbolTable.isEmpty());
23 //
24 // Parse the built-ins. This should only happen once per
25 // language symbol table.
26 //
27 // Push the symbol table to give it an initial scope. This
28 // push should not have a corresponding pop, so that built-ins
29 // are preserved, and the test for an empty table fails.
30 //
31 symbolTable.push();
alokp@chromium.org07620a52010-09-23 17:53:56 +000032
33 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
34 {
alokp@chromium.org570bfc72010-09-24 17:19:25 +000035 const char* builtInShaders = i->c_str();
36 int builtInLengths = static_cast<int>(i->size());
37 if (builtInLengths <= 0)
38 continue;
alokp@chromium.org07620a52010-09-23 17:53:56 +000039
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000040 if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
alokp@chromium.org07620a52010-09-23 17:53:56 +000041 {
42 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
43 return false;
44 }
45 }
46
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000047 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000048
alokp@chromium.org07620a52010-09-23 17:53:56 +000049 return true;
50}
51
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000052TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
53 : shaderType(type),
54 shaderSpec(spec)
55{
56}
57
58TCompiler::~TCompiler()
59{
60}
61
62bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +000063{
64 // Generate built-in symbol table.
65 if (!InitBuiltInSymbolTable(resources))
66 return false;
67
68 InitExtensionBehavior(resources, extensionBehavior);
69 return true;
70}
71
72bool TCompiler::compile(const char* const shaderStrings[],
73 const int numStrings,
74 int compileOptions)
75{
76 clearResults();
77
78 if (numStrings == 0)
79 return true;
80
alokp@chromium.org1f299542010-11-12 15:50:23 +000081 // If compiling for WebGL, validate control-flow and indexing as well.
82 if (shaderSpec == SH_WEBGL_SPEC) {
83 compileOptions |= SH_VALIDATE_CONTROL_FLOW | SH_VALIDATE_INDEXING;
84 }
85
alokp@chromium.org07620a52010-09-23 17:53:56 +000086 TIntermediate intermediate(infoSink);
87 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000088 shaderType, shaderSpec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000089 GlobalParseContext = &parseContext;
alokp@chromium.org07620a52010-09-23 17:53:56 +000090
91 // We preserve symbols at the built-in level from compile-to-compile.
92 // Start pushing the user-defined symbols at global level.
93 symbolTable.push();
94 if (!symbolTable.atGlobalLevel())
95 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
96
97 // Parse shader.
98 bool success =
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000099 (PaParseStrings(numStrings, shaderStrings, NULL, &parseContext) == 0) &&
alokp@chromium.org07620a52010-09-23 17:53:56 +0000100 (parseContext.treeRoot != NULL);
101 if (success) {
102 success = intermediate.postProcess(parseContext.treeRoot);
103
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000104 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000105 intermediate.outputTree(parseContext.treeRoot);
106
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000107 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000108 translate(parseContext.treeRoot);
109
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000110 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000111 collectAttribsUniforms(parseContext.treeRoot);
112 }
113
114 // Cleanup memory.
115 intermediate.remove(parseContext.treeRoot);
116 // Ensure symbol table is returned to the built-in level,
117 // throwing away all but the built-ins.
118 while (!symbolTable.atBuiltInLevel())
119 symbolTable.pop();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000120
121 return success;
122}
123
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000124bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000125{
126 TBuiltIns builtIns;
127
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000128 builtIns.initialize(shaderType, shaderSpec, resources);
129 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
130 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000131}
132
133void TCompiler::clearResults()
134{
135 infoSink.info.erase();
136 infoSink.obj.erase();
137 infoSink.debug.erase();
138
139 attribs.clear();
140 uniforms.clear();
141}
142
143void TCompiler::collectAttribsUniforms(TIntermNode* root)
144{
145 CollectAttribsUniforms collect(attribs, uniforms);
146 root->traverse(&collect);
147}
148