spirv_cross_parsed_ir.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. /*
  2. * Copyright 2018-2021 Arm Limited
  3. * SPDX-License-Identifier: Apache-2.0 OR MIT
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /*
  18. * At your option, you may choose to accept this material under either:
  19. * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
  20. * 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
  21. */
  22. #include "spirv_cross_parsed_ir.hpp"
  23. #include <algorithm>
  24. #include <assert.h>
  25. using namespace std;
  26. using namespace spv;
  27. namespace SPIRV_CROSS_NAMESPACE
  28. {
  29. ParsedIR::ParsedIR()
  30. {
  31. // If we move ParsedIR, we need to make sure the pointer stays fixed since the child Variant objects consume a pointer to this group,
  32. // so need an extra pointer here.
  33. pool_group.reset(new ObjectPoolGroup);
  34. pool_group->pools[TypeType].reset(new ObjectPool<SPIRType>);
  35. pool_group->pools[TypeVariable].reset(new ObjectPool<SPIRVariable>);
  36. pool_group->pools[TypeConstant].reset(new ObjectPool<SPIRConstant>);
  37. pool_group->pools[TypeFunction].reset(new ObjectPool<SPIRFunction>);
  38. pool_group->pools[TypeFunctionPrototype].reset(new ObjectPool<SPIRFunctionPrototype>);
  39. pool_group->pools[TypeBlock].reset(new ObjectPool<SPIRBlock>);
  40. pool_group->pools[TypeExtension].reset(new ObjectPool<SPIRExtension>);
  41. pool_group->pools[TypeExpression].reset(new ObjectPool<SPIRExpression>);
  42. pool_group->pools[TypeConstantOp].reset(new ObjectPool<SPIRConstantOp>);
  43. pool_group->pools[TypeCombinedImageSampler].reset(new ObjectPool<SPIRCombinedImageSampler>);
  44. pool_group->pools[TypeAccessChain].reset(new ObjectPool<SPIRAccessChain>);
  45. pool_group->pools[TypeUndef].reset(new ObjectPool<SPIRUndef>);
  46. pool_group->pools[TypeString].reset(new ObjectPool<SPIRString>);
  47. }
  48. // Should have been default-implemented, but need this on MSVC 2013.
  49. ParsedIR::ParsedIR(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
  50. {
  51. *this = std::move(other);
  52. }
  53. ParsedIR &ParsedIR::operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
  54. {
  55. if (this != &other)
  56. {
  57. pool_group = std::move(other.pool_group);
  58. spirv = std::move(other.spirv);
  59. meta = std::move(other.meta);
  60. for (int i = 0; i < TypeCount; i++)
  61. ids_for_type[i] = std::move(other.ids_for_type[i]);
  62. ids_for_constant_undef_or_type = std::move(other.ids_for_constant_undef_or_type);
  63. ids_for_constant_or_variable = std::move(other.ids_for_constant_or_variable);
  64. declared_capabilities = std::move(other.declared_capabilities);
  65. declared_extensions = std::move(other.declared_extensions);
  66. block_meta = std::move(other.block_meta);
  67. continue_block_to_loop_header = std::move(other.continue_block_to_loop_header);
  68. entry_points = std::move(other.entry_points);
  69. ids = std::move(other.ids);
  70. addressing_model = other.addressing_model;
  71. memory_model = other.memory_model;
  72. default_entry_point = other.default_entry_point;
  73. source = other.source;
  74. loop_iteration_depth_hard = other.loop_iteration_depth_hard;
  75. loop_iteration_depth_soft = other.loop_iteration_depth_soft;
  76. meta_needing_name_fixup = std::move(other.meta_needing_name_fixup);
  77. load_type_width = std::move(other.load_type_width);
  78. }
  79. return *this;
  80. }
  81. ParsedIR::ParsedIR(const ParsedIR &other)
  82. : ParsedIR()
  83. {
  84. *this = other;
  85. }
  86. ParsedIR &ParsedIR::operator=(const ParsedIR &other)
  87. {
  88. if (this != &other)
  89. {
  90. spirv = other.spirv;
  91. meta = other.meta;
  92. for (int i = 0; i < TypeCount; i++)
  93. ids_for_type[i] = other.ids_for_type[i];
  94. ids_for_constant_undef_or_type = other.ids_for_constant_undef_or_type;
  95. ids_for_constant_or_variable = other.ids_for_constant_or_variable;
  96. declared_capabilities = other.declared_capabilities;
  97. declared_extensions = other.declared_extensions;
  98. block_meta = other.block_meta;
  99. continue_block_to_loop_header = other.continue_block_to_loop_header;
  100. entry_points = other.entry_points;
  101. default_entry_point = other.default_entry_point;
  102. source = other.source;
  103. loop_iteration_depth_hard = other.loop_iteration_depth_hard;
  104. loop_iteration_depth_soft = other.loop_iteration_depth_soft;
  105. addressing_model = other.addressing_model;
  106. memory_model = other.memory_model;
  107. meta_needing_name_fixup = other.meta_needing_name_fixup;
  108. load_type_width = other.load_type_width;
  109. // Very deliberate copying of IDs. There is no default copy constructor, nor a simple default constructor.
  110. // Construct object first so we have the correct allocator set-up, then we can copy object into our new pool group.
  111. ids.clear();
  112. ids.reserve(other.ids.size());
  113. for (size_t i = 0; i < other.ids.size(); i++)
  114. {
  115. ids.emplace_back(pool_group.get());
  116. ids.back() = other.ids[i];
  117. }
  118. }
  119. return *this;
  120. }
  121. void ParsedIR::set_id_bounds(uint32_t bounds)
  122. {
  123. ids.reserve(bounds);
  124. while (ids.size() < bounds)
  125. ids.emplace_back(pool_group.get());
  126. block_meta.resize(bounds);
  127. }
  128. // Roll our own versions of these functions to avoid potential locale shenanigans.
  129. static bool is_alpha(char c)
  130. {
  131. return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
  132. }
  133. static bool is_numeric(char c)
  134. {
  135. return c >= '0' && c <= '9';
  136. }
  137. static bool is_alphanumeric(char c)
  138. {
  139. return is_alpha(c) || is_numeric(c);
  140. }
  141. static bool is_valid_identifier(const string &name)
  142. {
  143. if (name.empty())
  144. return true;
  145. if (is_numeric(name[0]))
  146. return false;
  147. for (auto c : name)
  148. if (!is_alphanumeric(c) && c != '_')
  149. return false;
  150. bool saw_underscore = false;
  151. // Two underscores in a row is not a valid identifier either.
  152. // Technically reserved, but it's easier to treat it as invalid.
  153. for (auto c : name)
  154. {
  155. bool is_underscore = c == '_';
  156. if (is_underscore && saw_underscore)
  157. return false;
  158. saw_underscore = is_underscore;
  159. }
  160. return true;
  161. }
  162. static bool is_reserved_prefix(const string &name)
  163. {
  164. // Generic reserved identifiers used by the implementation.
  165. return name.compare(0, 3, "gl_", 3) == 0 ||
  166. // Ignore this case for now, might rewrite internal code to always use spv prefix.
  167. //name.compare(0, 11, "SPIRV_Cross", 11) == 0 ||
  168. name.compare(0, 3, "spv", 3) == 0;
  169. }
  170. static bool is_reserved_identifier(const string &name, bool member, bool allow_reserved_prefixes)
  171. {
  172. if (!allow_reserved_prefixes && is_reserved_prefix(name))
  173. return true;
  174. if (member)
  175. {
  176. // Reserved member identifiers come in one form:
  177. // _m[0-9]+$.
  178. if (name.size() < 3)
  179. return false;
  180. if (name.compare(0, 2, "_m", 2) != 0)
  181. return false;
  182. size_t index = 2;
  183. while (index < name.size() && is_numeric(name[index]))
  184. index++;
  185. return index == name.size();
  186. }
  187. else
  188. {
  189. // Reserved non-member identifiers come in two forms:
  190. // _[0-9]+$, used for temporaries which map directly to a SPIR-V ID.
  191. // _[0-9]+_, used for auxillary temporaries which derived from a SPIR-V ID.
  192. if (name.size() < 2)
  193. return false;
  194. if (name[0] != '_' || !is_numeric(name[1]))
  195. return false;
  196. size_t index = 2;
  197. while (index < name.size() && is_numeric(name[index]))
  198. index++;
  199. return index == name.size() || (index < name.size() && name[index] == '_');
  200. }
  201. }
  202. bool ParsedIR::is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes)
  203. {
  204. return is_reserved_identifier(str, false, allow_reserved_prefixes);
  205. }
  206. uint32_t ParsedIR::get_spirv_version() const
  207. {
  208. return spirv[1];
  209. }
  210. static string make_unreserved_identifier(const string &name)
  211. {
  212. if (is_reserved_prefix(name))
  213. return "_RESERVED_IDENTIFIER_FIXUP_" + name;
  214. else
  215. return "_RESERVED_IDENTIFIER_FIXUP" + name;
  216. }
  217. void ParsedIR::sanitize_underscores(std::string &str)
  218. {
  219. // Compact adjacent underscores to make it valid.
  220. auto dst = str.begin();
  221. auto src = dst;
  222. bool saw_underscore = false;
  223. while (src != str.end())
  224. {
  225. bool is_underscore = *src == '_';
  226. if (saw_underscore && is_underscore)
  227. {
  228. src++;
  229. }
  230. else
  231. {
  232. if (dst != src)
  233. *dst = *src;
  234. dst++;
  235. src++;
  236. saw_underscore = is_underscore;
  237. }
  238. }
  239. str.erase(dst, str.end());
  240. }
  241. static string ensure_valid_identifier(const string &name)
  242. {
  243. // Functions in glslangValidator are mangled with name(<mangled> stuff.
  244. // Normally, we would never see '(' in any legal identifiers, so just strip them out.
  245. auto str = name.substr(0, name.find('('));
  246. if (str.empty())
  247. return str;
  248. if (is_numeric(str[0]))
  249. str[0] = '_';
  250. for (auto &c : str)
  251. if (!is_alphanumeric(c) && c != '_')
  252. c = '_';
  253. ParsedIR::sanitize_underscores(str);
  254. return str;
  255. }
  256. const string &ParsedIR::get_name(ID id) const
  257. {
  258. auto *m = find_meta(id);
  259. if (m)
  260. return m->decoration.alias;
  261. else
  262. return empty_string;
  263. }
  264. const string &ParsedIR::get_member_name(TypeID id, uint32_t index) const
  265. {
  266. auto *m = find_meta(id);
  267. if (m)
  268. {
  269. if (index >= m->members.size())
  270. return empty_string;
  271. return m->members[index].alias;
  272. }
  273. else
  274. return empty_string;
  275. }
  276. void ParsedIR::sanitize_identifier(std::string &name, bool member, bool allow_reserved_prefixes)
  277. {
  278. if (!is_valid_identifier(name))
  279. name = ensure_valid_identifier(name);
  280. if (is_reserved_identifier(name, member, allow_reserved_prefixes))
  281. name = make_unreserved_identifier(name);
  282. }
  283. void ParsedIR::fixup_reserved_names()
  284. {
  285. for (uint32_t id : meta_needing_name_fixup)
  286. {
  287. // Don't rename remapped variables like 'gl_LastFragDepthARM'.
  288. if (ids[id].get_type() == TypeVariable && get<SPIRVariable>(id).remapped_variable)
  289. continue;
  290. auto &m = meta[id];
  291. sanitize_identifier(m.decoration.alias, false, false);
  292. for (auto &memb : m.members)
  293. sanitize_identifier(memb.alias, true, false);
  294. }
  295. meta_needing_name_fixup.clear();
  296. }
  297. void ParsedIR::set_name(ID id, const string &name)
  298. {
  299. auto &m = meta[id];
  300. m.decoration.alias = name;
  301. if (!is_valid_identifier(name) || is_reserved_identifier(name, false, false))
  302. meta_needing_name_fixup.insert(id);
  303. }
  304. void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name)
  305. {
  306. auto &m = meta[id];
  307. m.members.resize(max(m.members.size(), size_t(index) + 1));
  308. m.members[index].alias = name;
  309. if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false))
  310. meta_needing_name_fixup.insert(id);
  311. }
  312. void ParsedIR::set_decoration_string(ID id, Decoration decoration, const string &argument)
  313. {
  314. auto &dec = meta[id].decoration;
  315. dec.decoration_flags.set(decoration);
  316. switch (decoration)
  317. {
  318. case DecorationHlslSemanticGOOGLE:
  319. dec.hlsl_semantic = argument;
  320. break;
  321. case DecorationUserTypeGOOGLE:
  322. dec.user_type = argument;
  323. break;
  324. default:
  325. break;
  326. }
  327. }
  328. void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument)
  329. {
  330. auto &dec = meta[id].decoration;
  331. dec.decoration_flags.set(decoration);
  332. switch (decoration)
  333. {
  334. case DecorationBuiltIn:
  335. dec.builtin = true;
  336. dec.builtin_type = static_cast<BuiltIn>(argument);
  337. break;
  338. case DecorationLocation:
  339. dec.location = argument;
  340. break;
  341. case DecorationComponent:
  342. dec.component = argument;
  343. break;
  344. case DecorationOffset:
  345. dec.offset = argument;
  346. break;
  347. case DecorationXfbBuffer:
  348. dec.xfb_buffer = argument;
  349. break;
  350. case DecorationXfbStride:
  351. dec.xfb_stride = argument;
  352. break;
  353. case DecorationStream:
  354. dec.stream = argument;
  355. break;
  356. case DecorationArrayStride:
  357. dec.array_stride = argument;
  358. break;
  359. case DecorationMatrixStride:
  360. dec.matrix_stride = argument;
  361. break;
  362. case DecorationBinding:
  363. dec.binding = argument;
  364. break;
  365. case DecorationDescriptorSet:
  366. dec.set = argument;
  367. break;
  368. case DecorationInputAttachmentIndex:
  369. dec.input_attachment = argument;
  370. break;
  371. case DecorationSpecId:
  372. dec.spec_id = argument;
  373. break;
  374. case DecorationIndex:
  375. dec.index = argument;
  376. break;
  377. case DecorationHlslCounterBufferGOOGLE:
  378. meta[id].hlsl_magic_counter_buffer = argument;
  379. meta[argument].hlsl_is_magic_counter_buffer = true;
  380. break;
  381. case DecorationFPRoundingMode:
  382. dec.fp_rounding_mode = static_cast<FPRoundingMode>(argument);
  383. break;
  384. default:
  385. break;
  386. }
  387. }
  388. void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decoration, uint32_t argument)
  389. {
  390. auto &m = meta[id];
  391. m.members.resize(max(m.members.size(), size_t(index) + 1));
  392. auto &dec = m.members[index];
  393. dec.decoration_flags.set(decoration);
  394. switch (decoration)
  395. {
  396. case DecorationBuiltIn:
  397. dec.builtin = true;
  398. dec.builtin_type = static_cast<BuiltIn>(argument);
  399. break;
  400. case DecorationLocation:
  401. dec.location = argument;
  402. break;
  403. case DecorationComponent:
  404. dec.component = argument;
  405. break;
  406. case DecorationBinding:
  407. dec.binding = argument;
  408. break;
  409. case DecorationOffset:
  410. dec.offset = argument;
  411. break;
  412. case DecorationXfbBuffer:
  413. dec.xfb_buffer = argument;
  414. break;
  415. case DecorationXfbStride:
  416. dec.xfb_stride = argument;
  417. break;
  418. case DecorationStream:
  419. dec.stream = argument;
  420. break;
  421. case DecorationSpecId:
  422. dec.spec_id = argument;
  423. break;
  424. case DecorationMatrixStride:
  425. dec.matrix_stride = argument;
  426. break;
  427. case DecorationIndex:
  428. dec.index = argument;
  429. break;
  430. default:
  431. break;
  432. }
  433. }
  434. // Recursively marks any constants referenced by the specified constant instruction as being used
  435. // as an array length. The id must be a constant instruction (SPIRConstant or SPIRConstantOp).
  436. void ParsedIR::mark_used_as_array_length(ID id)
  437. {
  438. switch (ids[id].get_type())
  439. {
  440. case TypeConstant:
  441. get<SPIRConstant>(id).is_used_as_array_length = true;
  442. break;
  443. case TypeConstantOp:
  444. {
  445. auto &cop = get<SPIRConstantOp>(id);
  446. if (cop.opcode == OpCompositeExtract)
  447. mark_used_as_array_length(cop.arguments[0]);
  448. else if (cop.opcode == OpCompositeInsert)
  449. {
  450. mark_used_as_array_length(cop.arguments[0]);
  451. mark_used_as_array_length(cop.arguments[1]);
  452. }
  453. else
  454. for (uint32_t arg_id : cop.arguments)
  455. mark_used_as_array_length(arg_id);
  456. break;
  457. }
  458. case TypeUndef:
  459. break;
  460. default:
  461. assert(0);
  462. }
  463. }
  464. Bitset ParsedIR::get_buffer_block_type_flags(const SPIRType &type) const
  465. {
  466. if (type.member_types.empty())
  467. return {};
  468. Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
  469. for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
  470. all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
  471. return all_members_flags;
  472. }
  473. Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
  474. {
  475. auto &type = get<SPIRType>(var.basetype);
  476. assert(type.basetype == SPIRType::Struct);
  477. // Some flags like non-writable, non-readable are actually found
  478. // as member decorations. If all members have a decoration set, propagate
  479. // the decoration up as a regular variable decoration.
  480. Bitset base_flags;
  481. auto *m = find_meta(var.self);
  482. if (m)
  483. base_flags = m->decoration.decoration_flags;
  484. if (type.member_types.empty())
  485. return base_flags;
  486. auto all_members_flags = get_buffer_block_type_flags(type);
  487. base_flags.merge_or(all_members_flags);
  488. return base_flags;
  489. }
  490. const Bitset &ParsedIR::get_member_decoration_bitset(TypeID id, uint32_t index) const
  491. {
  492. auto *m = find_meta(id);
  493. if (m)
  494. {
  495. if (index >= m->members.size())
  496. return cleared_bitset;
  497. return m->members[index].decoration_flags;
  498. }
  499. else
  500. return cleared_bitset;
  501. }
  502. bool ParsedIR::has_decoration(ID id, Decoration decoration) const
  503. {
  504. return get_decoration_bitset(id).get(decoration);
  505. }
  506. uint32_t ParsedIR::get_decoration(ID id, Decoration decoration) const
  507. {
  508. auto *m = find_meta(id);
  509. if (!m)
  510. return 0;
  511. auto &dec = m->decoration;
  512. if (!dec.decoration_flags.get(decoration))
  513. return 0;
  514. switch (decoration)
  515. {
  516. case DecorationBuiltIn:
  517. return dec.builtin_type;
  518. case DecorationLocation:
  519. return dec.location;
  520. case DecorationComponent:
  521. return dec.component;
  522. case DecorationOffset:
  523. return dec.offset;
  524. case DecorationXfbBuffer:
  525. return dec.xfb_buffer;
  526. case DecorationXfbStride:
  527. return dec.xfb_stride;
  528. case DecorationStream:
  529. return dec.stream;
  530. case DecorationBinding:
  531. return dec.binding;
  532. case DecorationDescriptorSet:
  533. return dec.set;
  534. case DecorationInputAttachmentIndex:
  535. return dec.input_attachment;
  536. case DecorationSpecId:
  537. return dec.spec_id;
  538. case DecorationArrayStride:
  539. return dec.array_stride;
  540. case DecorationMatrixStride:
  541. return dec.matrix_stride;
  542. case DecorationIndex:
  543. return dec.index;
  544. case DecorationFPRoundingMode:
  545. return dec.fp_rounding_mode;
  546. default:
  547. return 1;
  548. }
  549. }
  550. const string &ParsedIR::get_decoration_string(ID id, Decoration decoration) const
  551. {
  552. auto *m = find_meta(id);
  553. if (!m)
  554. return empty_string;
  555. auto &dec = m->decoration;
  556. if (!dec.decoration_flags.get(decoration))
  557. return empty_string;
  558. switch (decoration)
  559. {
  560. case DecorationHlslSemanticGOOGLE:
  561. return dec.hlsl_semantic;
  562. case DecorationUserTypeGOOGLE:
  563. return dec.user_type;
  564. default:
  565. return empty_string;
  566. }
  567. }
  568. void ParsedIR::unset_decoration(ID id, Decoration decoration)
  569. {
  570. auto &dec = meta[id].decoration;
  571. dec.decoration_flags.clear(decoration);
  572. switch (decoration)
  573. {
  574. case DecorationBuiltIn:
  575. dec.builtin = false;
  576. break;
  577. case DecorationLocation:
  578. dec.location = 0;
  579. break;
  580. case DecorationComponent:
  581. dec.component = 0;
  582. break;
  583. case DecorationOffset:
  584. dec.offset = 0;
  585. break;
  586. case DecorationXfbBuffer:
  587. dec.xfb_buffer = 0;
  588. break;
  589. case DecorationXfbStride:
  590. dec.xfb_stride = 0;
  591. break;
  592. case DecorationStream:
  593. dec.stream = 0;
  594. break;
  595. case DecorationBinding:
  596. dec.binding = 0;
  597. break;
  598. case DecorationDescriptorSet:
  599. dec.set = 0;
  600. break;
  601. case DecorationInputAttachmentIndex:
  602. dec.input_attachment = 0;
  603. break;
  604. case DecorationSpecId:
  605. dec.spec_id = 0;
  606. break;
  607. case DecorationHlslSemanticGOOGLE:
  608. dec.hlsl_semantic.clear();
  609. break;
  610. case DecorationFPRoundingMode:
  611. dec.fp_rounding_mode = FPRoundingModeMax;
  612. break;
  613. case DecorationHlslCounterBufferGOOGLE:
  614. {
  615. auto &counter = meta[id].hlsl_magic_counter_buffer;
  616. if (counter)
  617. {
  618. meta[counter].hlsl_is_magic_counter_buffer = false;
  619. counter = 0;
  620. }
  621. break;
  622. }
  623. default:
  624. break;
  625. }
  626. }
  627. bool ParsedIR::has_member_decoration(TypeID id, uint32_t index, Decoration decoration) const
  628. {
  629. return get_member_decoration_bitset(id, index).get(decoration);
  630. }
  631. uint32_t ParsedIR::get_member_decoration(TypeID id, uint32_t index, Decoration decoration) const
  632. {
  633. auto *m = find_meta(id);
  634. if (!m)
  635. return 0;
  636. if (index >= m->members.size())
  637. return 0;
  638. auto &dec = m->members[index];
  639. if (!dec.decoration_flags.get(decoration))
  640. return 0;
  641. switch (decoration)
  642. {
  643. case DecorationBuiltIn:
  644. return dec.builtin_type;
  645. case DecorationLocation:
  646. return dec.location;
  647. case DecorationComponent:
  648. return dec.component;
  649. case DecorationBinding:
  650. return dec.binding;
  651. case DecorationOffset:
  652. return dec.offset;
  653. case DecorationXfbBuffer:
  654. return dec.xfb_buffer;
  655. case DecorationXfbStride:
  656. return dec.xfb_stride;
  657. case DecorationStream:
  658. return dec.stream;
  659. case DecorationSpecId:
  660. return dec.spec_id;
  661. case DecorationMatrixStride:
  662. return dec.matrix_stride;
  663. case DecorationIndex:
  664. return dec.index;
  665. default:
  666. return 1;
  667. }
  668. }
  669. const Bitset &ParsedIR::get_decoration_bitset(ID id) const
  670. {
  671. auto *m = find_meta(id);
  672. if (m)
  673. {
  674. auto &dec = m->decoration;
  675. return dec.decoration_flags;
  676. }
  677. else
  678. return cleared_bitset;
  679. }
  680. void ParsedIR::set_member_decoration_string(TypeID id, uint32_t index, Decoration decoration, const string &argument)
  681. {
  682. auto &m = meta[id];
  683. m.members.resize(max(m.members.size(), size_t(index) + 1));
  684. auto &dec = meta[id].members[index];
  685. dec.decoration_flags.set(decoration);
  686. switch (decoration)
  687. {
  688. case DecorationHlslSemanticGOOGLE:
  689. dec.hlsl_semantic = argument;
  690. break;
  691. default:
  692. break;
  693. }
  694. }
  695. const string &ParsedIR::get_member_decoration_string(TypeID id, uint32_t index, Decoration decoration) const
  696. {
  697. auto *m = find_meta(id);
  698. if (m)
  699. {
  700. if (!has_member_decoration(id, index, decoration))
  701. return empty_string;
  702. auto &dec = m->members[index];
  703. switch (decoration)
  704. {
  705. case DecorationHlslSemanticGOOGLE:
  706. return dec.hlsl_semantic;
  707. default:
  708. return empty_string;
  709. }
  710. }
  711. else
  712. return empty_string;
  713. }
  714. void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration decoration)
  715. {
  716. auto &m = meta[id];
  717. if (index >= m.members.size())
  718. return;
  719. auto &dec = m.members[index];
  720. dec.decoration_flags.clear(decoration);
  721. switch (decoration)
  722. {
  723. case DecorationBuiltIn:
  724. dec.builtin = false;
  725. break;
  726. case DecorationLocation:
  727. dec.location = 0;
  728. break;
  729. case DecorationComponent:
  730. dec.component = 0;
  731. break;
  732. case DecorationOffset:
  733. dec.offset = 0;
  734. break;
  735. case DecorationXfbBuffer:
  736. dec.xfb_buffer = 0;
  737. break;
  738. case DecorationXfbStride:
  739. dec.xfb_stride = 0;
  740. break;
  741. case DecorationStream:
  742. dec.stream = 0;
  743. break;
  744. case DecorationSpecId:
  745. dec.spec_id = 0;
  746. break;
  747. case DecorationHlslSemanticGOOGLE:
  748. dec.hlsl_semantic.clear();
  749. break;
  750. default:
  751. break;
  752. }
  753. }
  754. uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount)
  755. {
  756. auto curr_bound = ids.size();
  757. auto new_bound = curr_bound + incr_amount;
  758. ids.reserve(ids.size() + incr_amount);
  759. for (uint32_t i = 0; i < incr_amount; i++)
  760. ids.emplace_back(pool_group.get());
  761. block_meta.resize(new_bound);
  762. return uint32_t(curr_bound);
  763. }
  764. void ParsedIR::remove_typed_id(Types type, ID id)
  765. {
  766. auto &type_ids = ids_for_type[type];
  767. type_ids.erase(remove(begin(type_ids), end(type_ids), id), end(type_ids));
  768. }
  769. void ParsedIR::reset_all_of_type(Types type)
  770. {
  771. for (auto &id : ids_for_type[type])
  772. if (ids[id].get_type() == type)
  773. ids[id].reset();
  774. ids_for_type[type].clear();
  775. }
  776. void ParsedIR::add_typed_id(Types type, ID id)
  777. {
  778. if (loop_iteration_depth_hard != 0)
  779. SPIRV_CROSS_THROW("Cannot add typed ID while looping over it.");
  780. if (loop_iteration_depth_soft != 0)
  781. {
  782. if (!ids[id].empty())
  783. SPIRV_CROSS_THROW("Cannot override IDs when loop is soft locked.");
  784. return;
  785. }
  786. if (ids[id].empty() || ids[id].get_type() != type)
  787. {
  788. switch (type)
  789. {
  790. case TypeConstant:
  791. ids_for_constant_or_variable.push_back(id);
  792. ids_for_constant_undef_or_type.push_back(id);
  793. break;
  794. case TypeVariable:
  795. ids_for_constant_or_variable.push_back(id);
  796. break;
  797. case TypeType:
  798. case TypeConstantOp:
  799. case TypeUndef:
  800. ids_for_constant_undef_or_type.push_back(id);
  801. break;
  802. default:
  803. break;
  804. }
  805. }
  806. if (ids[id].empty())
  807. {
  808. ids_for_type[type].push_back(id);
  809. }
  810. else if (ids[id].get_type() != type)
  811. {
  812. remove_typed_id(ids[id].get_type(), id);
  813. ids_for_type[type].push_back(id);
  814. }
  815. }
  816. const Meta *ParsedIR::find_meta(ID id) const
  817. {
  818. auto itr = meta.find(id);
  819. if (itr != end(meta))
  820. return &itr->second;
  821. else
  822. return nullptr;
  823. }
  824. Meta *ParsedIR::find_meta(ID id)
  825. {
  826. auto itr = meta.find(id);
  827. if (itr != end(meta))
  828. return &itr->second;
  829. else
  830. return nullptr;
  831. }
  832. ParsedIR::LoopLock ParsedIR::create_loop_hard_lock() const
  833. {
  834. return ParsedIR::LoopLock(&loop_iteration_depth_hard);
  835. }
  836. ParsedIR::LoopLock ParsedIR::create_loop_soft_lock() const
  837. {
  838. return ParsedIR::LoopLock(&loop_iteration_depth_soft);
  839. }
  840. ParsedIR::LoopLock::~LoopLock()
  841. {
  842. if (lock)
  843. (*lock)--;
  844. }
  845. ParsedIR::LoopLock::LoopLock(uint32_t *lock_)
  846. : lock(lock_)
  847. {
  848. if (lock)
  849. (*lock)++;
  850. }
  851. ParsedIR::LoopLock::LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
  852. {
  853. *this = std::move(other);
  854. }
  855. ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
  856. {
  857. if (lock)
  858. (*lock)--;
  859. lock = other.lock;
  860. other.lock = nullptr;
  861. return *this;
  862. }
  863. void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set)
  864. {
  865. auto &constant_type = get<SPIRType>(type);
  866. if (constant_type.pointer)
  867. {
  868. if (add_to_typed_id_set)
  869. add_typed_id(TypeConstant, id);
  870. auto &constant = variant_set<SPIRConstant>(ids[id], type);
  871. constant.self = id;
  872. constant.make_null(constant_type);
  873. }
  874. else if (!constant_type.array.empty())
  875. {
  876. assert(constant_type.parent_type);
  877. uint32_t parent_id = increase_bound_by(1);
  878. make_constant_null(parent_id, constant_type.parent_type, add_to_typed_id_set);
  879. if (!constant_type.array_size_literal.back())
  880. SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
  881. SmallVector<uint32_t> elements(constant_type.array.back());
  882. for (uint32_t i = 0; i < constant_type.array.back(); i++)
  883. elements[i] = parent_id;
  884. if (add_to_typed_id_set)
  885. add_typed_id(TypeConstant, id);
  886. variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
  887. }
  888. else if (!constant_type.member_types.empty())
  889. {
  890. uint32_t member_ids = increase_bound_by(uint32_t(constant_type.member_types.size()));
  891. SmallVector<uint32_t> elements(constant_type.member_types.size());
  892. for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
  893. {
  894. make_constant_null(member_ids + i, constant_type.member_types[i], add_to_typed_id_set);
  895. elements[i] = member_ids + i;
  896. }
  897. if (add_to_typed_id_set)
  898. add_typed_id(TypeConstant, id);
  899. variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
  900. }
  901. else
  902. {
  903. if (add_to_typed_id_set)
  904. add_typed_id(TypeConstant, id);
  905. auto &constant = variant_set<SPIRConstant>(ids[id], type);
  906. constant.self = id;
  907. constant.make_null(constant_type);
  908. }
  909. }
  910. } // namespace SPIRV_CROSS_NAMESPACE