1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "DirectiveHandler.h"
16
17#include <sstream>
18
19#include "debug.h"
20#include "Diagnostics.h"
21
22static TBehavior getBehavior(const std::string& str)
23{
24 static const char kRequire[] = "require";
25 static const char kEnable[] = "enable";
26 static const char kDisable[] = "disable";
27 static const char kWarn[] = "warn";
28
29 if (str == kRequire) return EBhRequire;
30 else if (str == kEnable) return EBhEnable;
31 else if (str == kDisable) return EBhDisable;
32 else if (str == kWarn) return EBhWarn;
33 return EBhUndefined;
34}
35
36TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
37 TDiagnostics& diagnostics,
38 int& shaderVersion)
39 : mExtensionBehavior(extBehavior),
40 mDiagnostics(diagnostics),
41 mShaderVersion(shaderVersion)
42{
43}
44
45TDirectiveHandler::~TDirectiveHandler()
46{
47}
48
49void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
50 const std::string& msg)
51{
52 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", "");
53}
54
55void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
56 const std::string& name,
57 const std::string& value,
58 bool stdgl)
59{
60 static const char kSTDGL[] = "STDGL";
61 static const char kOptimize[] = "optimize";
62 static const char kDebug[] = "debug";
63 static const char kOn[] = "on";
64 static const char kOff[] = "off";
65
66 bool invalidValue = false;
67 if (stdgl || (name == kSTDGL))
68 {
69 // The STDGL pragma is used to reserve pragmas for use by future
70 // revisions of GLSL. Ignore it.
71 return;
72 }
73 else if (name == kOptimize)
74 {
75 if (value == kOn) mPragma.optimize = true;
76 else if (value == kOff) mPragma.optimize = false;
77 else invalidValue = true;
78 }
79 else if (name == kDebug)
80 {
81 if (value == kOn) mPragma.debug = true;
82 else if (value == kOff) mPragma.debug = false;
83 else invalidValue = true;
84 }
85 else
86 {
87 mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
88 return;
89 }
90
91 if (invalidValue)
92 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
93 "invalid pragma value", value,
94 "'on' or 'off' expected");
95}
96
97void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
98 const std::string& name,
99 const std::string& behavior)
100{
101 static const char kExtAll[] = "all";
102
103 TBehavior behaviorVal = getBehavior(behavior);
104 if (behaviorVal == EBhUndefined)
105 {
106 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
107 "behavior", name, "invalid");
108 return;
109 }
110
111 if (name == kExtAll)
112 {
113 if (behaviorVal == EBhRequire)
114 {
115 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
116 "extension", name,
117 "cannot have 'require' behavior");
118 }
119 else if (behaviorVal == EBhEnable)
120 {
121 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
122 "extension", name,
123 "cannot have 'enable' behavior");
124 }
125 else
126 {
127 for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
128 iter != mExtensionBehavior.end(); ++iter)
129 iter->second = behaviorVal;
130 }
131 return;
132 }
133
134 TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
135 if (iter != mExtensionBehavior.end())
136 {
137 iter->second = behaviorVal;
138 return;
139 }
140
141 pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
142 switch (behaviorVal) {
143 case EBhRequire:
144 severity = pp::Diagnostics::PP_ERROR;
145 break;
146 case EBhEnable:
147 case EBhWarn:
148 case EBhDisable:
149 severity = pp::Diagnostics::PP_WARNING;
150 break;
151 default:
152 UNREACHABLE(behaviorVal);
153 break;
154 }
155 mDiagnostics.writeInfo(severity, loc,
156 "extension", name, "is not supported");
157}
158
159void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
160 int version)
161{
162 if (version == 100 ||
163 version == 300)
164 {
165 mShaderVersion = version;
166 }
167 else
168 {
169 std::stringstream stream;
170 stream << version;
171 std::string str = stream.str();
172 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
173 "version number", str, "not supported");
174 }
175}
176