spirv_cross_parsed_ir.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  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 DecorationIndex:
  662. return dec.index;
  663. default:
  664. return 1;
  665. }
  666. }
  667. const Bitset &ParsedIR::get_decoration_bitset(ID id) const
  668. {
  669. auto *m = find_meta(id);
  670. if (m)
  671. {
  672. auto &dec = m->decoration;
  673. return dec.decoration_flags;
  674. }
  675. else
  676. return cleared_bitset;
  677. }
  678. void ParsedIR::set_member_decoration_string(TypeID id, uint32_t index, Decoration decoration, const string &argument)
  679. {
  680. auto &m = meta[id];
  681. m.members.resize(max(m.members.size(), size_t(index) + 1));
  682. auto &dec = meta[id].members[index];
  683. dec.decoration_flags.set(decoration);
  684. switch (decoration)
  685. {
  686. case DecorationHlslSemanticGOOGLE:
  687. dec.hlsl_semantic = argument;
  688. break;
  689. default:
  690. break;
  691. }
  692. }
  693. const string &ParsedIR::get_member_decoration_string(TypeID id, uint32_t index, Decoration decoration) const
  694. {
  695. auto *m = find_meta(id);
  696. if (m)
  697. {
  698. if (!has_member_decoration(id, index, decoration))
  699. return empty_string;
  700. auto &dec = m->members[index];
  701. switch (decoration)
  702. {
  703. case DecorationHlslSemanticGOOGLE:
  704. return dec.hlsl_semantic;
  705. default:
  706. return empty_string;
  707. }
  708. }
  709. else
  710. return empty_string;
  711. }
  712. void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration decoration)
  713. {
  714. auto &m = meta[id];
  715. if (index >= m.members.size())
  716. return;
  717. auto &dec = m.members[index];
  718. dec.decoration_flags.clear(decoration);
  719. switch (decoration)
  720. {
  721. case DecorationBuiltIn:
  722. dec.builtin = false;
  723. break;
  724. case DecorationLocation:
  725. dec.location = 0;
  726. break;
  727. case DecorationComponent:
  728. dec.component = 0;
  729. break;
  730. case DecorationOffset:
  731. dec.offset = 0;
  732. break;
  733. case DecorationXfbBuffer:
  734. dec.xfb_buffer = 0;
  735. break;
  736. case DecorationXfbStride:
  737. dec.xfb_stride = 0;
  738. break;
  739. case DecorationStream:
  740. dec.stream = 0;
  741. break;
  742. case DecorationSpecId:
  743. dec.spec_id = 0;
  744. break;
  745. case DecorationHlslSemanticGOOGLE:
  746. dec.hlsl_semantic.clear();
  747. break;
  748. default:
  749. break;
  750. }
  751. }
  752. uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount)
  753. {
  754. auto curr_bound = ids.size();
  755. auto new_bound = curr_bound + incr_amount;
  756. ids.reserve(ids.size() + incr_amount);
  757. for (uint32_t i = 0; i < incr_amount; i++)
  758. ids.emplace_back(pool_group.get());
  759. block_meta.resize(new_bound);
  760. return uint32_t(curr_bound);
  761. }
  762. void ParsedIR::remove_typed_id(Types type, ID id)
  763. {
  764. auto &type_ids = ids_for_type[type];
  765. type_ids.erase(remove(begin(type_ids), end(type_ids), id), end(type_ids));
  766. }
  767. void ParsedIR::reset_all_of_type(Types type)
  768. {
  769. for (auto &id : ids_for_type[type])
  770. if (ids[id].get_type() == type)
  771. ids[id].reset();
  772. ids_for_type[type].clear();
  773. }
  774. void ParsedIR::add_typed_id(Types type, ID id)
  775. {
  776. if (loop_iteration_depth_hard != 0)
  777. SPIRV_CROSS_THROW("Cannot add typed ID while looping over it.");
  778. if (loop_iteration_depth_soft != 0)
  779. {
  780. if (!ids[id].empty())
  781. SPIRV_CROSS_THROW("Cannot override IDs when loop is soft locked.");
  782. return;
  783. }
  784. if (ids[id].empty() || ids[id].get_type() != type)
  785. {
  786. switch (type)
  787. {
  788. case TypeConstant:
  789. ids_for_constant_or_variable.push_back(id);
  790. ids_for_constant_undef_or_type.push_back(id);
  791. break;
  792. case TypeVariable:
  793. ids_for_constant_or_variable.push_back(id);
  794. break;
  795. case TypeType:
  796. case TypeConstantOp:
  797. case TypeUndef:
  798. ids_for_constant_undef_or_type.push_back(id);
  799. break;
  800. default:
  801. break;
  802. }
  803. }
  804. if (ids[id].empty())
  805. {
  806. ids_for_type[type].push_back(id);
  807. }
  808. else if (ids[id].get_type() != type)
  809. {
  810. remove_typed_id(ids[id].get_type(), id);
  811. ids_for_type[type].push_back(id);
  812. }
  813. }
  814. const Meta *ParsedIR::find_meta(ID id) const
  815. {
  816. auto itr = meta.find(id);
  817. if (itr != end(meta))
  818. return &itr->second;
  819. else
  820. return nullptr;
  821. }
  822. Meta *ParsedIR::find_meta(ID id)
  823. {
  824. auto itr = meta.find(id);
  825. if (itr != end(meta))
  826. return &itr->second;
  827. else
  828. return nullptr;
  829. }
  830. ParsedIR::LoopLock ParsedIR::create_loop_hard_lock() const
  831. {
  832. return ParsedIR::LoopLock(&loop_iteration_depth_hard);
  833. }
  834. ParsedIR::LoopLock ParsedIR::create_loop_soft_lock() const
  835. {
  836. return ParsedIR::LoopLock(&loop_iteration_depth_soft);
  837. }
  838. ParsedIR::LoopLock::~LoopLock()
  839. {
  840. if (lock)
  841. (*lock)--;
  842. }
  843. ParsedIR::LoopLock::LoopLock(uint32_t *lock_)
  844. : lock(lock_)
  845. {
  846. if (lock)
  847. (*lock)++;
  848. }
  849. ParsedIR::LoopLock::LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
  850. {
  851. *this = std::move(other);
  852. }
  853. ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
  854. {
  855. if (lock)
  856. (*lock)--;
  857. lock = other.lock;
  858. other.lock = nullptr;
  859. return *this;
  860. }
  861. void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set)
  862. {
  863. auto &constant_type = get<SPIRType>(type);
  864. if (constant_type.pointer)
  865. {
  866. if (add_to_typed_id_set)
  867. add_typed_id(TypeConstant, id);
  868. auto &constant = variant_set<SPIRConstant>(ids[id], type);
  869. constant.self = id;
  870. constant.make_null(constant_type);
  871. }
  872. else if (!constant_type.array.empty())
  873. {
  874. assert(constant_type.parent_type);
  875. uint32_t parent_id = increase_bound_by(1);
  876. make_constant_null(parent_id, constant_type.parent_type, add_to_typed_id_set);
  877. if (!constant_type.array_size_literal.back())
  878. SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
  879. SmallVector<uint32_t> elements(constant_type.array.back());
  880. for (uint32_t i = 0; i < constant_type.array.back(); i++)
  881. elements[i] = parent_id;
  882. if (add_to_typed_id_set)
  883. add_typed_id(TypeConstant, id);
  884. variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
  885. }
  886. else if (!constant_type.member_types.empty())
  887. {
  888. uint32_t member_ids = increase_bound_by(uint32_t(constant_type.member_types.size()));
  889. SmallVector<uint32_t> elements(constant_type.member_types.size());
  890. for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
  891. {
  892. make_constant_null(member_ids + i, constant_type.member_types[i], add_to_typed_id_set);
  893. elements[i] = member_ids + i;
  894. }
  895. if (add_to_typed_id_set)
  896. add_typed_id(TypeConstant, id);
  897. variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
  898. }
  899. else
  900. {
  901. if (add_to_typed_id_set)
  902. add_typed_id(TypeConstant, id);
  903. auto &constant = variant_set<SPIRConstant>(ids[id], type);
  904. constant.self = id;
  905. constant.make_null(constant_type);
  906. }
  907. }
  908. } // namespace SPIRV_CROSS_NAMESPACE