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 std::string kRequire("require"); 25 static const std::string kEnable("enable"); 26 static const std::string kDisable("disable"); 27 static const std::string 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 { 59 static const std::string kSTDGL("STDGL"); 60 static const std::string kOptimize("optimize"); 61 static const std::string kDebug("debug"); 62 static const std::string kOn("on"); 63 static const std::string kOff("off"); 64 65 bool invalidValue = false; 66 if (name == kSTDGL) 67 { 68 // The STDGL pragma is used to reserve pragmas for use by future 69 // revisions of GLSL. Ignore it. 70 return; 71 } 72 else if (name == kOptimize) 73 { 74 if (value == kOn) mPragma.optimize = true; 75 else if (value == kOff) mPragma.optimize = false; 76 else invalidValue = true; 77 } 78 else if (name == kDebug) 79 { 80 if (value == kOn) mPragma.debug = true; 81 else if (value == kOff) mPragma.debug = false; 82 else invalidValue = true; 83 } 84 else 85 { 86 mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name); 87 return; 88 } 89 90 if (invalidValue) 91 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, 92 "invalid pragma value", value, 93 "'on' or 'off' expected"); 94 } 95 96 void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, 97 const std::string& name, 98 const std::string& behavior) 99 { 100 static const std::string kExtAll("all"); 101 102 TBehavior behaviorVal = getBehavior(behavior); 103 if (behaviorVal == EBhUndefined) 104 { 105 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, 106 "behavior", name, "invalid"); 107 return; 108 } 109 110 if (name == kExtAll) 111 { 112 if (behaviorVal == EBhRequire) 113 { 114 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, 115 "extension", name, 116 "cannot have 'require' behavior"); 117 } 118 else if (behaviorVal == EBhEnable) 119 { 120 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, 121 "extension", name, 122 "cannot have 'enable' behavior"); 123 } 124 else 125 { 126 for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); 127 iter != mExtensionBehavior.end(); ++iter) 128 iter->second = behaviorVal; 129 } 130 return; 131 } 132 133 TExtensionBehavior::iterator iter = mExtensionBehavior.find(name); 134 if (iter != mExtensionBehavior.end()) 135 { 136 iter->second = behaviorVal; 137 return; 138 } 139 140 pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR; 141 switch (behaviorVal) { 142 case EBhRequire: 143 severity = pp::Diagnostics::PP_ERROR; 144 break; 145 case EBhEnable: 146 case EBhWarn: 147 case EBhDisable: 148 severity = pp::Diagnostics::PP_WARNING; 149 break; 150 default: 151 UNREACHABLE(behaviorVal); 152 break; 153 } 154 mDiagnostics.writeInfo(severity, loc, 155 "extension", name, "is not supported"); 156 } 157 158 void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, 159 int version) 160 { 161 if (version == 100 || 162 version == 300) 163 { 164 mShaderVersion = version; 165 } 166 else 167 { 168 std::stringstream stream; 169 stream << version; 170 std::string str = stream.str(); 171 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, 172 "version number", str, "not supported"); 173 } 174 } 175