validate_layout.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // Copyright (c) 2015-2016 The Khronos Group Inc.
  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. // Source code for logical layout validation as described in section 2.4
  15. #include <cassert>
  16. #include "DebugInfo.h"
  17. #include "NonSemanticShaderDebugInfo100.h"
  18. #include "OpenCLDebugInfo100.h"
  19. #include "source/diagnostic.h"
  20. #include "source/opcode.h"
  21. #include "source/operand.h"
  22. #include "source/val/function.h"
  23. #include "source/val/instruction.h"
  24. #include "source/val/validate.h"
  25. #include "source/val/validation_state.h"
  26. namespace spvtools {
  27. namespace val {
  28. namespace {
  29. // Module scoped instructions are processed by determining if the opcode
  30. // is part of the current layout section. If it is not then the next sections is
  31. // checked.
  32. spv_result_t ModuleScopedInstructions(ValidationState_t& _,
  33. const Instruction* inst, spv::Op opcode) {
  34. switch (opcode) {
  35. case spv::Op::OpExtInst:
  36. if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
  37. const uint32_t ext_inst_index = inst->word(4);
  38. bool local_debug_info = false;
  39. if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
  40. const OpenCLDebugInfo100Instructions ext_inst_key =
  41. OpenCLDebugInfo100Instructions(ext_inst_index);
  42. if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
  43. ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
  44. ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
  45. ext_inst_key == OpenCLDebugInfo100DebugValue) {
  46. local_debug_info = true;
  47. }
  48. } else if (inst->ext_inst_type() ==
  49. SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
  50. const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
  51. NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
  52. if (ext_inst_key == NonSemanticShaderDebugInfo100DebugScope ||
  53. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoScope ||
  54. ext_inst_key == NonSemanticShaderDebugInfo100DebugDeclare ||
  55. ext_inst_key == NonSemanticShaderDebugInfo100DebugValue ||
  56. ext_inst_key == NonSemanticShaderDebugInfo100DebugLine ||
  57. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoLine ||
  58. ext_inst_key ==
  59. NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
  60. local_debug_info = true;
  61. }
  62. } else {
  63. const DebugInfoInstructions ext_inst_key =
  64. DebugInfoInstructions(ext_inst_index);
  65. if (ext_inst_key == DebugInfoDebugScope ||
  66. ext_inst_key == DebugInfoDebugNoScope ||
  67. ext_inst_key == DebugInfoDebugDeclare ||
  68. ext_inst_key == DebugInfoDebugValue) {
  69. local_debug_info = true;
  70. }
  71. }
  72. if (local_debug_info) {
  73. if (_.in_function_body() == false) {
  74. // DebugScope, DebugNoScope, DebugDeclare, DebugValue must
  75. // appear in a function body.
  76. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  77. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  78. << "of debug info extension must appear in a function "
  79. << "body";
  80. }
  81. } else {
  82. // Debug info extinst opcodes other than DebugScope, DebugNoScope,
  83. // DebugDeclare, DebugValue must be placed between section 9 (types,
  84. // constants, global variables) and section 10 (function
  85. // declarations).
  86. if (_.current_layout_section() < kLayoutTypes ||
  87. _.current_layout_section() >= kLayoutFunctionDeclarations) {
  88. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  89. << "Debug info extension instructions other than "
  90. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  91. << "must appear between section 9 (types, constants, "
  92. << "global variables) and section 10 (function "
  93. << "declarations)";
  94. }
  95. }
  96. } else if (spvExtInstIsNonSemantic(inst->ext_inst_type())) {
  97. // non-semantic extinst opcodes are allowed beginning in the types
  98. // section, but since they must name a return type they cannot be the
  99. // first instruction in the types section. Therefore check that we are
  100. // already in it.
  101. if (_.current_layout_section() < kLayoutTypes) {
  102. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  103. << "Non-semantic OpExtInst must not appear before types "
  104. << "section";
  105. }
  106. } else {
  107. // otherwise they must be used in a block
  108. if (_.current_layout_section() < kLayoutFunctionDefinitions) {
  109. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  110. << spvOpcodeString(opcode) << " must appear in a block";
  111. }
  112. }
  113. break;
  114. default:
  115. break;
  116. }
  117. while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) {
  118. if (_.IsOpcodeInPreviousLayoutSection(opcode)) {
  119. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  120. << spvOpcodeString(opcode) << " is in an invalid layout section";
  121. }
  122. _.ProgressToNextLayoutSectionOrder();
  123. switch (_.current_layout_section()) {
  124. case kLayoutMemoryModel:
  125. if (opcode != spv::Op::OpMemoryModel) {
  126. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  127. << spvOpcodeString(opcode)
  128. << " cannot appear before the memory model instruction";
  129. }
  130. break;
  131. case kLayoutFunctionDeclarations:
  132. // All module sections have been processed. Recursively call
  133. // ModuleLayoutPass to process the next section of the module
  134. return ModuleLayoutPass(_, inst);
  135. default:
  136. break;
  137. }
  138. }
  139. return SPV_SUCCESS;
  140. }
  141. // Function declaration validation is performed by making sure that the
  142. // FunctionParameter and FunctionEnd instructions only appear inside of
  143. // functions. It also ensures that the Function instruction does not appear
  144. // inside of another function. This stage ends when the first label is
  145. // encountered inside of a function.
  146. spv_result_t FunctionScopedInstructions(ValidationState_t& _,
  147. const Instruction* inst,
  148. spv::Op opcode) {
  149. // Make sure we advance into the function definitions when we hit
  150. // non-function declaration instructions.
  151. if (_.current_layout_section() == kLayoutFunctionDeclarations &&
  152. !_.IsOpcodeInCurrentLayoutSection(opcode)) {
  153. _.ProgressToNextLayoutSectionOrder();
  154. if (_.in_function_body()) {
  155. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  156. FunctionDecl::kFunctionDeclDefinition)) {
  157. return error;
  158. }
  159. }
  160. }
  161. if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
  162. switch (opcode) {
  163. case spv::Op::OpFunction: {
  164. if (_.in_function_body()) {
  165. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  166. << "Cannot declare a function in a function body";
  167. }
  168. auto control_mask = inst->GetOperandAs<spv::FunctionControlMask>(2);
  169. if (auto error =
  170. _.RegisterFunction(inst->id(), inst->type_id(), control_mask,
  171. inst->GetOperandAs<uint32_t>(3)))
  172. return error;
  173. if (_.current_layout_section() == kLayoutFunctionDefinitions) {
  174. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  175. FunctionDecl::kFunctionDeclDefinition))
  176. return error;
  177. }
  178. } break;
  179. case spv::Op::OpFunctionParameter:
  180. if (_.in_function_body() == false) {
  181. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  182. << "Function parameter instructions must be in a "
  183. "function body";
  184. }
  185. if (_.current_function().block_count() != 0) {
  186. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  187. << "Function parameters must only appear immediately after "
  188. "the function definition";
  189. }
  190. if (auto error = _.current_function().RegisterFunctionParameter(
  191. inst->id(), inst->type_id()))
  192. return error;
  193. break;
  194. case spv::Op::OpFunctionEnd:
  195. if (_.in_function_body() == false) {
  196. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  197. << "Function end instructions must be in a function body";
  198. }
  199. if (_.in_block()) {
  200. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  201. << "Function end cannot be called in blocks";
  202. }
  203. if (_.current_function().block_count() == 0 &&
  204. _.current_layout_section() == kLayoutFunctionDefinitions) {
  205. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  206. << "Function declarations must appear before "
  207. "function definitions.";
  208. }
  209. if (_.current_layout_section() == kLayoutFunctionDeclarations) {
  210. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  211. FunctionDecl::kFunctionDeclDeclaration))
  212. return error;
  213. }
  214. if (auto error = _.RegisterFunctionEnd()) return error;
  215. break;
  216. case spv::Op::OpLine:
  217. case spv::Op::OpNoLine:
  218. break;
  219. case spv::Op::OpLabel:
  220. // If the label is encountered then the current function is a
  221. // definition so set the function to a declaration and update the
  222. // module section
  223. if (_.in_function_body() == false) {
  224. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  225. << "Label instructions must be in a function body";
  226. }
  227. if (_.in_block()) {
  228. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  229. << "A block must end with a branch instruction.";
  230. }
  231. break;
  232. case spv::Op::OpExtInst:
  233. if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
  234. const uint32_t ext_inst_index = inst->word(4);
  235. bool local_debug_info = false;
  236. if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
  237. const OpenCLDebugInfo100Instructions ext_inst_key =
  238. OpenCLDebugInfo100Instructions(ext_inst_index);
  239. if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
  240. ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
  241. ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
  242. ext_inst_key == OpenCLDebugInfo100DebugValue) {
  243. local_debug_info = true;
  244. }
  245. } else if (inst->ext_inst_type() ==
  246. SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
  247. const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
  248. NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
  249. if (ext_inst_key == NonSemanticShaderDebugInfo100DebugScope ||
  250. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoScope ||
  251. ext_inst_key == NonSemanticShaderDebugInfo100DebugDeclare ||
  252. ext_inst_key == NonSemanticShaderDebugInfo100DebugValue ||
  253. ext_inst_key == NonSemanticShaderDebugInfo100DebugLine ||
  254. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoLine ||
  255. ext_inst_key ==
  256. NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
  257. local_debug_info = true;
  258. }
  259. } else {
  260. const DebugInfoInstructions ext_inst_key =
  261. DebugInfoInstructions(ext_inst_index);
  262. if (ext_inst_key == DebugInfoDebugScope ||
  263. ext_inst_key == DebugInfoDebugNoScope ||
  264. ext_inst_key == DebugInfoDebugDeclare ||
  265. ext_inst_key == DebugInfoDebugValue) {
  266. local_debug_info = true;
  267. }
  268. }
  269. if (local_debug_info) {
  270. if (_.in_function_body() == false) {
  271. // DebugScope, DebugNoScope, DebugDeclare, DebugValue must
  272. // appear in a function body.
  273. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  274. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  275. << "of debug info extension must appear in a function "
  276. << "body";
  277. }
  278. } else {
  279. // Debug info extinst opcodes other than DebugScope, DebugNoScope,
  280. // DebugDeclare, DebugValue must be placed between section 9 (types,
  281. // constants, global variables) and section 10 (function
  282. // declarations).
  283. if (_.current_layout_section() < kLayoutTypes ||
  284. _.current_layout_section() >= kLayoutFunctionDeclarations) {
  285. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  286. << "Debug info extension instructions other than "
  287. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  288. << "must appear between section 9 (types, constants, "
  289. << "global variables) and section 10 (function "
  290. << "declarations)";
  291. }
  292. }
  293. } else if (spvExtInstIsNonSemantic(inst->ext_inst_type())) {
  294. // non-semantic extinst opcodes are allowed beginning in the types
  295. // section, but must either be placed outside a function declaration,
  296. // or inside a block.
  297. if (_.current_layout_section() < kLayoutTypes) {
  298. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  299. << "Non-semantic OpExtInst must not appear before types "
  300. << "section";
  301. } else if (_.in_function_body() && _.in_block() == false) {
  302. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  303. << "Non-semantic OpExtInst within function definition must "
  304. "appear in a block";
  305. }
  306. } else {
  307. // otherwise they must be used in a block
  308. if (_.in_block() == false) {
  309. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  310. << spvOpcodeString(opcode) << " must appear in a block";
  311. }
  312. }
  313. break;
  314. default:
  315. if (_.current_layout_section() == kLayoutFunctionDeclarations &&
  316. _.in_function_body()) {
  317. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  318. << "A function must begin with a label";
  319. } else {
  320. if (_.in_block() == false) {
  321. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  322. << spvOpcodeString(opcode) << " must appear in a block";
  323. }
  324. }
  325. break;
  326. }
  327. } else {
  328. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  329. << spvOpcodeString(opcode)
  330. << " cannot appear in a function declaration";
  331. }
  332. return SPV_SUCCESS;
  333. }
  334. } // namespace
  335. // TODO(umar): Check linkage capabilities for function declarations
  336. // TODO(umar): Better error messages
  337. // NOTE: This function does not handle CFG related validation
  338. // Performs logical layout validation. See Section 2.4
  339. spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
  340. const spv::Op opcode = inst->opcode();
  341. switch (_.current_layout_section()) {
  342. case kLayoutCapabilities:
  343. case kLayoutExtensions:
  344. case kLayoutExtInstImport:
  345. case kLayoutMemoryModel:
  346. case kLayoutSamplerImageAddressMode:
  347. case kLayoutEntryPoint:
  348. case kLayoutExecutionMode:
  349. case kLayoutDebug1:
  350. case kLayoutDebug2:
  351. case kLayoutDebug3:
  352. case kLayoutAnnotations:
  353. case kLayoutTypes:
  354. if (auto error = ModuleScopedInstructions(_, inst, opcode)) return error;
  355. break;
  356. case kLayoutFunctionDeclarations:
  357. case kLayoutFunctionDefinitions:
  358. if (auto error = FunctionScopedInstructions(_, inst, opcode)) {
  359. return error;
  360. }
  361. break;
  362. }
  363. return SPV_SUCCESS;
  364. }
  365. } // namespace val
  366. } // namespace spvtools