validate_layout.cpp 14 KB

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