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 22 static 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 36 TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, 37 TDiagnostics& diagnostics, 38 int& shaderVersion) 39 : mExtensionBehavior(extBehavior), 40 mDiagnostics(diagnostics), 41 mShaderVersion(shaderVersion) 42 { 43 } 44 45 TDirectiveHandler::~TDirectiveHandler() 46 { 47 } 48 49 void TDirectiveHandler::handleError(const pp::SourceLocation& loc, 50 const std::string& msg) 51 { 52 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", ""); 53 } 54 55 void 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 97 void 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 159 void 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