validate_adjacency.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright (c) 2018 LunarG 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. // Validates correctness of the intra-block preconditions of SPIR-V
  15. // instructions.
  16. #include "validate.h"
  17. #include <string>
  18. #include "diagnostic.h"
  19. #include "opcode.h"
  20. #include "val/instruction.h"
  21. #include "val/validation_state.h"
  22. namespace libspirv {
  23. spv_result_t ValidateAdjacency(ValidationState_t& _) {
  24. const auto& instructions = _.ordered_instructions();
  25. for (auto i = instructions.cbegin(); i != instructions.cend(); ++i) {
  26. switch (i->opcode()) {
  27. case SpvOpPhi:
  28. if (i != instructions.cbegin()) {
  29. switch (prev(i)->opcode()) {
  30. case SpvOpLabel:
  31. case SpvOpPhi:
  32. case SpvOpLine:
  33. break;
  34. default:
  35. return _.diag(SPV_ERROR_INVALID_DATA)
  36. << "OpPhi must appear before all non-OpPhi instructions "
  37. << "(except for OpLine, which can be mixed with OpPhi).";
  38. }
  39. }
  40. break;
  41. case SpvOpLoopMerge:
  42. if (next(i) != instructions.cend()) {
  43. switch (next(i)->opcode()) {
  44. case SpvOpBranch:
  45. case SpvOpBranchConditional:
  46. break;
  47. default:
  48. return _.diag(SPV_ERROR_INVALID_DATA)
  49. << "OpLoopMerge must immediately precede either an "
  50. << "OpBranch or OpBranchConditional instruction. "
  51. << "OpLoopMerge must be the second-to-last instruction in "
  52. << "its block.";
  53. }
  54. }
  55. break;
  56. case SpvOpSelectionMerge:
  57. if (next(i) != instructions.cend()) {
  58. switch (next(i)->opcode()) {
  59. case SpvOpBranchConditional:
  60. case SpvOpSwitch:
  61. break;
  62. default:
  63. return _.diag(SPV_ERROR_INVALID_DATA)
  64. << "OpSelectionMerge must immediately precede either an "
  65. << "OpBranchConditional or OpSwitch instruction. "
  66. << "OpSelectionMerge must be the second-to-last "
  67. << "instruction in its block.";
  68. }
  69. }
  70. default:
  71. break;
  72. }
  73. }
  74. return SPV_SUCCESS;
  75. }
  76. } // namespace libspirv