validate_layout.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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, SpvOp opcode) {
  34. switch (opcode) {
  35. case SpvOpExtInst:
  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 != SpvOpMemoryModel) {
  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, SpvOp opcode) {
  148. // Make sure we advance into the function definitions when we hit
  149. // non-function declaration instructions.
  150. if (_.current_layout_section() == kLayoutFunctionDeclarations &&
  151. !_.IsOpcodeInCurrentLayoutSection(opcode)) {
  152. _.ProgressToNextLayoutSectionOrder();
  153. if (_.in_function_body()) {
  154. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  155. FunctionDecl::kFunctionDeclDefinition)) {
  156. return error;
  157. }
  158. }
  159. }
  160. if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
  161. switch (opcode) {
  162. case SpvOpFunction: {
  163. if (_.in_function_body()) {
  164. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  165. << "Cannot declare a function in a function body";
  166. }
  167. auto control_mask = inst->GetOperandAs<SpvFunctionControlMask>(2);
  168. if (auto error =
  169. _.RegisterFunction(inst->id(), inst->type_id(), control_mask,
  170. inst->GetOperandAs<uint32_t>(3)))
  171. return error;
  172. if (_.current_layout_section() == kLayoutFunctionDefinitions) {
  173. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  174. FunctionDecl::kFunctionDeclDefinition))
  175. return error;
  176. }
  177. } break;
  178. case SpvOpFunctionParameter:
  179. if (_.in_function_body() == false) {
  180. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  181. << "Function parameter instructions must be in a "
  182. "function body";
  183. }
  184. if (_.current_function().block_count() != 0) {
  185. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  186. << "Function parameters must only appear immediately after "
  187. "the function definition";
  188. }
  189. if (auto error = _.current_function().RegisterFunctionParameter(
  190. inst->id(), inst->type_id()))
  191. return error;
  192. break;
  193. case SpvOpFunctionEnd:
  194. if (_.in_function_body() == false) {
  195. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  196. << "Function end instructions must be in a function body";
  197. }
  198. if (_.in_block()) {
  199. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  200. << "Function end cannot be called in blocks";
  201. }
  202. if (_.current_function().block_count() == 0 &&
  203. _.current_layout_section() == kLayoutFunctionDefinitions) {
  204. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  205. << "Function declarations must appear before "
  206. "function definitions.";
  207. }
  208. if (_.current_layout_section() == kLayoutFunctionDeclarations) {
  209. if (auto error = _.current_function().RegisterSetFunctionDeclType(
  210. FunctionDecl::kFunctionDeclDeclaration))
  211. return error;
  212. }
  213. if (auto error = _.RegisterFunctionEnd()) return error;
  214. break;
  215. case SpvOpLine:
  216. case SpvOpNoLine:
  217. break;
  218. case SpvOpLabel:
  219. // If the label is encountered then the current function is a
  220. // definition so set the function to a declaration and update the
  221. // module section
  222. if (_.in_function_body() == false) {
  223. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  224. << "Label instructions must be in a function body";
  225. }
  226. if (_.in_block()) {
  227. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  228. << "A block must end with a branch instruction.";
  229. }
  230. break;
  231. case SpvOpExtInst:
  232. if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
  233. const uint32_t ext_inst_index = inst->word(4);
  234. bool local_debug_info = false;
  235. if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
  236. const OpenCLDebugInfo100Instructions ext_inst_key =
  237. OpenCLDebugInfo100Instructions(ext_inst_index);
  238. if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
  239. ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
  240. ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
  241. ext_inst_key == OpenCLDebugInfo100DebugValue) {
  242. local_debug_info = true;
  243. }
  244. } else if (inst->ext_inst_type() ==
  245. SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
  246. const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
  247. NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
  248. if (ext_inst_key == NonSemanticShaderDebugInfo100DebugScope ||
  249. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoScope ||
  250. ext_inst_key == NonSemanticShaderDebugInfo100DebugDeclare ||
  251. ext_inst_key == NonSemanticShaderDebugInfo100DebugValue ||
  252. ext_inst_key == NonSemanticShaderDebugInfo100DebugLine ||
  253. ext_inst_key == NonSemanticShaderDebugInfo100DebugNoLine ||
  254. ext_inst_key ==
  255. NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
  256. local_debug_info = true;
  257. }
  258. } else {
  259. const DebugInfoInstructions ext_inst_key =
  260. DebugInfoInstructions(ext_inst_index);
  261. if (ext_inst_key == DebugInfoDebugScope ||
  262. ext_inst_key == DebugInfoDebugNoScope ||
  263. ext_inst_key == DebugInfoDebugDeclare ||
  264. ext_inst_key == DebugInfoDebugValue) {
  265. local_debug_info = true;
  266. }
  267. }
  268. if (local_debug_info) {
  269. if (_.in_function_body() == false) {
  270. // DebugScope, DebugNoScope, DebugDeclare, DebugValue must
  271. // appear in a function body.
  272. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  273. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  274. << "of debug info extension must appear in a function "
  275. << "body";
  276. }
  277. } else {
  278. // Debug info extinst opcodes other than DebugScope, DebugNoScope,
  279. // DebugDeclare, DebugValue must be placed between section 9 (types,
  280. // constants, global variables) and section 10 (function
  281. // declarations).
  282. if (_.current_layout_section() < kLayoutTypes ||
  283. _.current_layout_section() >= kLayoutFunctionDeclarations) {
  284. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  285. << "Debug info extension instructions other than "
  286. << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
  287. << "must appear between section 9 (types, constants, "
  288. << "global variables) and section 10 (function "
  289. << "declarations)";
  290. }
  291. }
  292. } else if (spvExtInstIsNonSemantic(inst->ext_inst_type())) {
  293. // non-semantic extinst opcodes are allowed beginning in the types
  294. // section, but must either be placed outside a function declaration,
  295. // or inside a block.
  296. if (_.current_layout_section() < kLayoutTypes) {
  297. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  298. << "Non-semantic OpExtInst must not appear before types "
  299. << "section";
  300. } else if (_.in_function_body() && _.in_block() == false) {
  301. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  302. << "Non-semantic OpExtInst within function definition must "
  303. "appear in a block";
  304. }
  305. } else {
  306. // otherwise they must be used in a block
  307. if (_.in_block() == false) {
  308. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  309. << spvOpcodeString(opcode) << " must appear in a block";
  310. }
  311. }
  312. break;
  313. default:
  314. if (_.current_layout_section() == kLayoutFunctionDeclarations &&
  315. _.in_function_body()) {
  316. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  317. << "A function must begin with a label";
  318. } else {
  319. if (_.in_block() == false) {
  320. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  321. << spvOpcodeString(opcode) << " must appear in a block";
  322. }
  323. }
  324. break;
  325. }
  326. } else {
  327. return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
  328. << spvOpcodeString(opcode)
  329. << " cannot appear in a function declaration";
  330. }
  331. return SPV_SUCCESS;
  332. }
  333. } // namespace
  334. // TODO(umar): Check linkage capabilities for function declarations
  335. // TODO(umar): Better error messages
  336. // NOTE: This function does not handle CFG related validation
  337. // Performs logical layout validation. See Section 2.4
  338. spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
  339. const SpvOp opcode = inst->opcode();
  340. switch (_.current_layout_section()) {
  341. case kLayoutCapabilities:
  342. case kLayoutExtensions:
  343. case kLayoutExtInstImport:
  344. case kLayoutMemoryModel:
  345. case kLayoutEntryPoint:
  346. case kLayoutExecutionMode:
  347. case kLayoutDebug1:
  348. case kLayoutDebug2:
  349. case kLayoutDebug3:
  350. case kLayoutAnnotations:
  351. case kLayoutTypes:
  352. if (auto error = ModuleScopedInstructions(_, inst, opcode)) return error;
  353. break;
  354. case kLayoutFunctionDeclarations:
  355. case kLayoutFunctionDefinitions:
  356. if (auto error = FunctionScopedInstructions(_, inst, opcode)) {
  357. return error;
  358. }
  359. break;
  360. }
  361. return SPV_SUCCESS;
  362. }
  363. } // namespace val
  364. } // namespace spvtools