SpirvBuilder.cpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518
  1. //===--- SpirvBuilder.cpp - SPIR-V Builder Implementation --------*- C++ -*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/SPIRV/SpirvBuilder.h"
  10. #include "CapabilityVisitor.h"
  11. #include "DebugTypeVisitor.h"
  12. #include "EmitVisitor.h"
  13. #include "LiteralTypeVisitor.h"
  14. #include "LowerTypeVisitor.h"
  15. #include "NonUniformVisitor.h"
  16. #include "PreciseVisitor.h"
  17. #include "RelaxedPrecisionVisitor.h"
  18. #include "RemoveBufferBlockVisitor.h"
  19. #include "SortDebugInfoVisitor.h"
  20. #include "clang/SPIRV/AstTypeProbe.h"
  21. namespace clang {
  22. namespace spirv {
  23. SpirvBuilder::SpirvBuilder(ASTContext &ac, SpirvContext &ctx,
  24. const SpirvCodeGenOptions &opt)
  25. : astContext(ac), context(ctx), mod(llvm::make_unique<SpirvModule>()),
  26. function(nullptr), moduleInit(nullptr), moduleInitInsertPoint(nullptr),
  27. spirvOptions(opt), builtinVars(), debugNone(nullptr),
  28. nullDebugExpr(nullptr), stringLiterals() {}
  29. SpirvFunction *SpirvBuilder::createSpirvFunction(QualType returnType,
  30. SourceLocation loc,
  31. llvm::StringRef name,
  32. bool isPrecise,
  33. bool isNoInline) {
  34. auto *fn =
  35. new (context) SpirvFunction(returnType, loc, name, isPrecise, isNoInline);
  36. mod->addFunction(fn);
  37. return fn;
  38. }
  39. SpirvFunction *SpirvBuilder::beginFunction(QualType returnType,
  40. SourceLocation loc,
  41. llvm::StringRef funcName,
  42. bool isPrecise, bool isNoInline,
  43. SpirvFunction *func) {
  44. assert(!function && "found nested function");
  45. if (func) {
  46. function = func;
  47. function->setAstReturnType(returnType);
  48. function->setSourceLocation(loc);
  49. function->setFunctionName(funcName);
  50. function->setPrecise(isPrecise);
  51. function->setNoInline(isNoInline);
  52. } else {
  53. function =
  54. createSpirvFunction(returnType, loc, funcName, isPrecise, isNoInline);
  55. }
  56. return function;
  57. }
  58. SpirvFunctionParameter *SpirvBuilder::addFnParam(QualType ptrType,
  59. bool isPrecise,
  60. SourceLocation loc,
  61. llvm::StringRef name) {
  62. assert(function && "found detached parameter");
  63. SpirvFunctionParameter *param = nullptr;
  64. if (isBindlessOpaqueArray(ptrType)) {
  65. // If it is a bindless array of an opaque type, we have to use
  66. // a pointer to a pointer of the runtime array.
  67. param = new (context) SpirvFunctionParameter(
  68. context.getPointerType(ptrType, spv::StorageClass::UniformConstant),
  69. isPrecise, loc);
  70. } else {
  71. param = new (context) SpirvFunctionParameter(ptrType, isPrecise, loc);
  72. }
  73. param->setStorageClass(spv::StorageClass::Function);
  74. param->setDebugName(name);
  75. function->addParameter(param);
  76. return param;
  77. }
  78. SpirvVariable *SpirvBuilder::addFnVar(QualType valueType, SourceLocation loc,
  79. llvm::StringRef name, bool isPrecise,
  80. SpirvInstruction *init) {
  81. assert(function && "found detached local variable");
  82. SpirvVariable *var = nullptr;
  83. if (isBindlessOpaqueArray(valueType)) {
  84. // If it is a bindless array of an opaque type, we have to use
  85. // a pointer to a pointer of the runtime array.
  86. var = new (context) SpirvVariable(
  87. context.getPointerType(valueType, spv::StorageClass::UniformConstant),
  88. loc, spv::StorageClass::Function, isPrecise, init);
  89. } else {
  90. var = new (context) SpirvVariable(
  91. valueType, loc, spv::StorageClass::Function, isPrecise, init);
  92. }
  93. var->setDebugName(name);
  94. function->addVariable(var);
  95. return var;
  96. }
  97. void SpirvBuilder::endFunction() {
  98. assert(function && "no active function");
  99. mod->addFunctionToListOfSortedModuleFunctions(function);
  100. function = nullptr;
  101. insertPoint = nullptr;
  102. }
  103. SpirvBasicBlock *SpirvBuilder::createBasicBlock(llvm::StringRef name) {
  104. assert(function && "found detached basic block");
  105. auto *bb = new (context) SpirvBasicBlock(name);
  106. function->addBasicBlock(bb);
  107. if (auto *scope = context.getCurrentLexicalScope())
  108. bb->setDebugScope(new (context) SpirvDebugScope(scope));
  109. return bb;
  110. }
  111. SpirvDebugScope *SpirvBuilder::createDebugScope(SpirvDebugInstruction *scope) {
  112. assert(insertPoint && "null insert point");
  113. auto *dbgScope = new (context) SpirvDebugScope(scope);
  114. insertPoint->addInstruction(dbgScope);
  115. return dbgScope;
  116. }
  117. void SpirvBuilder::addSuccessor(SpirvBasicBlock *successorBB) {
  118. assert(insertPoint && "null insert point");
  119. insertPoint->addSuccessor(successorBB);
  120. }
  121. void SpirvBuilder::setMergeTarget(SpirvBasicBlock *mergeLabel) {
  122. assert(insertPoint && "null insert point");
  123. insertPoint->setMergeTarget(mergeLabel);
  124. }
  125. void SpirvBuilder::setContinueTarget(SpirvBasicBlock *continueLabel) {
  126. assert(insertPoint && "null insert point");
  127. insertPoint->setContinueTarget(continueLabel);
  128. }
  129. SpirvCompositeConstruct *SpirvBuilder::createCompositeConstruct(
  130. QualType resultType, llvm::ArrayRef<SpirvInstruction *> constituents,
  131. SourceLocation loc) {
  132. assert(insertPoint && "null insert point");
  133. auto *instruction =
  134. new (context) SpirvCompositeConstruct(resultType, loc, constituents);
  135. insertPoint->addInstruction(instruction);
  136. if (!constituents.empty()) {
  137. instruction->setLayoutRule(constituents[0]->getLayoutRule());
  138. }
  139. return instruction;
  140. }
  141. SpirvCompositeExtract *SpirvBuilder::createCompositeExtract(
  142. QualType resultType, SpirvInstruction *composite,
  143. llvm::ArrayRef<uint32_t> indexes, SourceLocation loc) {
  144. assert(insertPoint && "null insert point");
  145. auto *instruction =
  146. new (context) SpirvCompositeExtract(resultType, loc, composite, indexes);
  147. instruction->setRValue();
  148. insertPoint->addInstruction(instruction);
  149. return instruction;
  150. }
  151. SpirvCompositeInsert *SpirvBuilder::createCompositeInsert(
  152. QualType resultType, SpirvInstruction *composite,
  153. llvm::ArrayRef<uint32_t> indices, SpirvInstruction *object,
  154. SourceLocation loc) {
  155. assert(insertPoint && "null insert point");
  156. auto *instruction = new (context)
  157. SpirvCompositeInsert(resultType, loc, composite, object, indices);
  158. insertPoint->addInstruction(instruction);
  159. return instruction;
  160. }
  161. SpirvVectorShuffle *SpirvBuilder::createVectorShuffle(
  162. QualType resultType, SpirvInstruction *vector1, SpirvInstruction *vector2,
  163. llvm::ArrayRef<uint32_t> selectors, SourceLocation loc) {
  164. assert(insertPoint && "null insert point");
  165. auto *instruction = new (context)
  166. SpirvVectorShuffle(resultType, loc, vector1, vector2, selectors);
  167. instruction->setRValue();
  168. insertPoint->addInstruction(instruction);
  169. return instruction;
  170. }
  171. SpirvLoad *SpirvBuilder::createLoad(QualType resultType,
  172. SpirvInstruction *pointer,
  173. SourceLocation loc) {
  174. assert(insertPoint && "null insert point");
  175. auto *instruction = new (context) SpirvLoad(resultType, loc, pointer);
  176. instruction->setStorageClass(pointer->getStorageClass());
  177. instruction->setLayoutRule(pointer->getLayoutRule());
  178. instruction->setRValue(true);
  179. if (pointer->containsAliasComponent() &&
  180. isAKindOfStructuredOrByteBuffer(resultType)) {
  181. instruction->setStorageClass(spv::StorageClass::Uniform);
  182. // Now it is a pointer to the global resource, which is lvalue.
  183. instruction->setRValue(false);
  184. // Set to false to indicate that we've performed dereference over the
  185. // pointer-to-pointer and now should fallback to the normal path
  186. instruction->setContainsAliasComponent(false);
  187. }
  188. insertPoint->addInstruction(instruction);
  189. return instruction;
  190. }
  191. SpirvCopyObject *SpirvBuilder::createCopyObject(QualType resultType,
  192. SpirvInstruction *pointer,
  193. SourceLocation loc) {
  194. assert(insertPoint && "null insert point");
  195. auto *instruction = new (context) SpirvCopyObject(resultType, loc, pointer);
  196. instruction->setStorageClass(pointer->getStorageClass());
  197. instruction->setLayoutRule(pointer->getLayoutRule());
  198. // The result of OpCopyObject is always an rvalue.
  199. instruction->setRValue(true);
  200. insertPoint->addInstruction(instruction);
  201. return instruction;
  202. }
  203. SpirvLoad *SpirvBuilder::createLoad(const SpirvType *resultType,
  204. SpirvInstruction *pointer,
  205. SourceLocation loc) {
  206. assert(insertPoint && "null insert point");
  207. auto *instruction = new (context) SpirvLoad(/*QualType*/ {}, loc, pointer);
  208. instruction->setResultType(resultType);
  209. instruction->setStorageClass(pointer->getStorageClass());
  210. // Special case for legalization. We could have point-to-pointer types.
  211. // For example:
  212. //
  213. // %var = OpVariable %_ptr_Private__ptr_Uniform_type_X Private
  214. // %1 = OpLoad %_ptr_Uniform_type_X %var
  215. //
  216. // Loading from %var should result in Uniform storage class, not Private.
  217. if (const auto *ptrType = dyn_cast<SpirvPointerType>(resultType)) {
  218. instruction->setStorageClass(ptrType->getStorageClass());
  219. }
  220. instruction->setLayoutRule(pointer->getLayoutRule());
  221. instruction->setRValue(true);
  222. insertPoint->addInstruction(instruction);
  223. return instruction;
  224. }
  225. void SpirvBuilder::createStore(SpirvInstruction *address,
  226. SpirvInstruction *value, SourceLocation loc) {
  227. assert(insertPoint && "null insert point");
  228. auto *instruction = new (context) SpirvStore(loc, address, value);
  229. insertPoint->addInstruction(instruction);
  230. }
  231. SpirvFunctionCall *
  232. SpirvBuilder::createFunctionCall(QualType returnType, SpirvFunction *func,
  233. llvm::ArrayRef<SpirvInstruction *> params,
  234. SourceLocation loc) {
  235. assert(insertPoint && "null insert point");
  236. auto *instruction =
  237. new (context) SpirvFunctionCall(returnType, loc, func, params);
  238. instruction->setRValue(func->isRValue());
  239. instruction->setContainsAliasComponent(func->constainsAliasComponent());
  240. if (func->constainsAliasComponent() &&
  241. isAKindOfStructuredOrByteBuffer(returnType)) {
  242. instruction->setStorageClass(spv::StorageClass::Uniform);
  243. // Now it is a pointer to the global resource, which is lvalue.
  244. instruction->setRValue(false);
  245. // Set to false to indicate that we've performed dereference over the
  246. // pointer-to-pointer and now should fallback to the normal path
  247. instruction->setContainsAliasComponent(false);
  248. }
  249. insertPoint->addInstruction(instruction);
  250. return instruction;
  251. }
  252. SpirvAccessChain *SpirvBuilder::createAccessChain(
  253. const SpirvType *resultType, SpirvInstruction *base,
  254. llvm::ArrayRef<SpirvInstruction *> indexes, SourceLocation loc) {
  255. assert(insertPoint && "null insert point");
  256. auto *instruction =
  257. new (context) SpirvAccessChain(/*QualType*/ {}, loc, base, indexes);
  258. instruction->setResultType(resultType);
  259. instruction->setStorageClass(base->getStorageClass());
  260. instruction->setLayoutRule(base->getLayoutRule());
  261. instruction->setContainsAliasComponent(base->containsAliasComponent());
  262. // If doing an access chain into a structured or byte address buffer, make
  263. // sure the layout rule is sBufferLayoutRule.
  264. if (base->hasAstResultType() &&
  265. isAKindOfStructuredOrByteBuffer(base->getAstResultType()))
  266. instruction->setLayoutRule(spirvOptions.sBufferLayoutRule);
  267. insertPoint->addInstruction(instruction);
  268. return instruction;
  269. }
  270. SpirvAccessChain *
  271. SpirvBuilder::createAccessChain(QualType resultType, SpirvInstruction *base,
  272. llvm::ArrayRef<SpirvInstruction *> indexes,
  273. SourceLocation loc) {
  274. assert(insertPoint && "null insert point");
  275. auto *instruction =
  276. new (context) SpirvAccessChain(resultType, loc, base, indexes);
  277. instruction->setStorageClass(base->getStorageClass());
  278. instruction->setLayoutRule(base->getLayoutRule());
  279. instruction->setContainsAliasComponent(base->containsAliasComponent());
  280. // If doing an access chain into a structured or byte address buffer, make
  281. // sure the layout rule is sBufferLayoutRule.
  282. if (base->hasAstResultType() &&
  283. isAKindOfStructuredOrByteBuffer(base->getAstResultType()))
  284. instruction->setLayoutRule(spirvOptions.sBufferLayoutRule);
  285. insertPoint->addInstruction(instruction);
  286. return instruction;
  287. }
  288. SpirvUnaryOp *SpirvBuilder::createUnaryOp(spv::Op op, QualType resultType,
  289. SpirvInstruction *operand,
  290. SourceLocation loc) {
  291. assert(insertPoint && "null insert point");
  292. auto *instruction = new (context) SpirvUnaryOp(op, resultType, loc, operand);
  293. insertPoint->addInstruction(instruction);
  294. return instruction;
  295. }
  296. SpirvBinaryOp *SpirvBuilder::createBinaryOp(spv::Op op, QualType resultType,
  297. SpirvInstruction *lhs,
  298. SpirvInstruction *rhs,
  299. SourceLocation loc) {
  300. assert(insertPoint && "null insert point");
  301. auto *instruction =
  302. new (context) SpirvBinaryOp(op, resultType, loc, lhs, rhs);
  303. insertPoint->addInstruction(instruction);
  304. return instruction;
  305. }
  306. SpirvSpecConstantBinaryOp *SpirvBuilder::createSpecConstantBinaryOp(
  307. spv::Op op, QualType resultType, SpirvInstruction *lhs,
  308. SpirvInstruction *rhs, SourceLocation loc) {
  309. assert(insertPoint && "null insert point");
  310. auto *instruction =
  311. new (context) SpirvSpecConstantBinaryOp(op, resultType, loc, lhs, rhs);
  312. insertPoint->addInstruction(instruction);
  313. return instruction;
  314. }
  315. SpirvNonUniformElect *SpirvBuilder::createGroupNonUniformElect(
  316. spv::Op op, QualType resultType, spv::Scope execScope, SourceLocation loc) {
  317. assert(insertPoint && "null insert point");
  318. auto *instruction =
  319. new (context) SpirvNonUniformElect(resultType, loc, execScope);
  320. insertPoint->addInstruction(instruction);
  321. return instruction;
  322. }
  323. SpirvNonUniformUnaryOp *SpirvBuilder::createGroupNonUniformUnaryOp(
  324. SourceLocation loc, spv::Op op, QualType resultType, spv::Scope execScope,
  325. SpirvInstruction *operand, llvm::Optional<spv::GroupOperation> groupOp) {
  326. assert(insertPoint && "null insert point");
  327. auto *instruction = new (context)
  328. SpirvNonUniformUnaryOp(op, resultType, loc, execScope, groupOp, operand);
  329. insertPoint->addInstruction(instruction);
  330. return instruction;
  331. }
  332. SpirvNonUniformBinaryOp *SpirvBuilder::createGroupNonUniformBinaryOp(
  333. spv::Op op, QualType resultType, spv::Scope execScope,
  334. SpirvInstruction *operand1, SpirvInstruction *operand2,
  335. SourceLocation loc) {
  336. assert(insertPoint && "null insert point");
  337. auto *instruction = new (context) SpirvNonUniformBinaryOp(
  338. op, resultType, loc, execScope, operand1, operand2);
  339. insertPoint->addInstruction(instruction);
  340. return instruction;
  341. }
  342. SpirvAtomic *SpirvBuilder::createAtomicOp(
  343. spv::Op opcode, QualType resultType, SpirvInstruction *originalValuePtr,
  344. spv::Scope scope, spv::MemorySemanticsMask memorySemantics,
  345. SpirvInstruction *valueToOp, SourceLocation loc) {
  346. assert(insertPoint && "null insert point");
  347. auto *instruction =
  348. new (context) SpirvAtomic(opcode, resultType, loc, originalValuePtr,
  349. scope, memorySemantics, valueToOp);
  350. insertPoint->addInstruction(instruction);
  351. return instruction;
  352. }
  353. SpirvAtomic *SpirvBuilder::createAtomicCompareExchange(
  354. QualType resultType, SpirvInstruction *originalValuePtr, spv::Scope scope,
  355. spv::MemorySemanticsMask equalMemorySemantics,
  356. spv::MemorySemanticsMask unequalMemorySemantics,
  357. SpirvInstruction *valueToOp, SpirvInstruction *comparator,
  358. SourceLocation loc) {
  359. assert(insertPoint && "null insert point");
  360. auto *instruction = new (context)
  361. SpirvAtomic(spv::Op::OpAtomicCompareExchange, resultType, loc,
  362. originalValuePtr, scope, equalMemorySemantics,
  363. unequalMemorySemantics, valueToOp, comparator);
  364. insertPoint->addInstruction(instruction);
  365. return instruction;
  366. }
  367. SpirvSampledImage *SpirvBuilder::createSampledImage(QualType imageType,
  368. SpirvInstruction *image,
  369. SpirvInstruction *sampler,
  370. SourceLocation loc) {
  371. assert(insertPoint && "null insert point");
  372. auto *sampledImage =
  373. new (context) SpirvSampledImage(imageType, loc, image, sampler);
  374. insertPoint->addInstruction(sampledImage);
  375. return sampledImage;
  376. }
  377. SpirvImageTexelPointer *SpirvBuilder::createImageTexelPointer(
  378. QualType resultType, SpirvInstruction *image, SpirvInstruction *coordinate,
  379. SpirvInstruction *sample, SourceLocation loc) {
  380. assert(insertPoint && "null insert point");
  381. auto *instruction = new (context)
  382. SpirvImageTexelPointer(resultType, loc, image, coordinate, sample);
  383. insertPoint->addInstruction(instruction);
  384. return instruction;
  385. }
  386. spv::ImageOperandsMask SpirvBuilder::composeImageOperandsMask(
  387. SpirvInstruction *bias, SpirvInstruction *lod,
  388. const std::pair<SpirvInstruction *, SpirvInstruction *> &grad,
  389. SpirvInstruction *constOffset, SpirvInstruction *varOffset,
  390. SpirvInstruction *constOffsets, SpirvInstruction *sample,
  391. SpirvInstruction *minLod) {
  392. using spv::ImageOperandsMask;
  393. // SPIR-V Image Operands from least significant bit to most significant bit
  394. // Bias, Lod, Grad, ConstOffset, Offset, ConstOffsets, Sample, MinLod
  395. auto mask = ImageOperandsMask::MaskNone;
  396. if (bias) {
  397. mask = mask | ImageOperandsMask::Bias;
  398. }
  399. if (lod) {
  400. mask = mask | ImageOperandsMask::Lod;
  401. }
  402. if (grad.first && grad.second) {
  403. mask = mask | ImageOperandsMask::Grad;
  404. }
  405. if (constOffset) {
  406. mask = mask | ImageOperandsMask::ConstOffset;
  407. }
  408. if (varOffset) {
  409. mask = mask | ImageOperandsMask::Offset;
  410. }
  411. if (constOffsets) {
  412. mask = mask | ImageOperandsMask::ConstOffsets;
  413. }
  414. if (sample) {
  415. mask = mask | ImageOperandsMask::Sample;
  416. }
  417. if (minLod) {
  418. mask = mask | ImageOperandsMask::MinLod;
  419. }
  420. return mask;
  421. }
  422. SpirvInstruction *SpirvBuilder::createImageSample(
  423. QualType texelType, QualType imageType, SpirvInstruction *image,
  424. SpirvInstruction *sampler, SpirvInstruction *coordinate,
  425. SpirvInstruction *compareVal, SpirvInstruction *bias, SpirvInstruction *lod,
  426. std::pair<SpirvInstruction *, SpirvInstruction *> grad,
  427. SpirvInstruction *constOffset, SpirvInstruction *varOffset,
  428. SpirvInstruction *constOffsets, SpirvInstruction *sample,
  429. SpirvInstruction *minLod, SpirvInstruction *residencyCode,
  430. SourceLocation loc) {
  431. assert(insertPoint && "null insert point");
  432. // The Lod and Grad image operands requires explicit-lod instructions.
  433. // Otherwise we use implicit-lod instructions.
  434. const bool isExplicit = lod || (grad.first && grad.second);
  435. const bool isSparse = (residencyCode != nullptr);
  436. spv::Op op = spv::Op::Max;
  437. if (compareVal) {
  438. op = isExplicit ? (isSparse ? spv::Op::OpImageSparseSampleDrefExplicitLod
  439. : spv::Op::OpImageSampleDrefExplicitLod)
  440. : (isSparse ? spv::Op::OpImageSparseSampleDrefImplicitLod
  441. : spv::Op::OpImageSampleDrefImplicitLod);
  442. } else {
  443. op = isExplicit ? (isSparse ? spv::Op::OpImageSparseSampleExplicitLod
  444. : spv::Op::OpImageSampleExplicitLod)
  445. : (isSparse ? spv::Op::OpImageSparseSampleImplicitLod
  446. : spv::Op::OpImageSampleImplicitLod);
  447. }
  448. // minLod is only valid with Implicit instructions and Grad instructions.
  449. // This means that we cannot have Lod and minLod together because Lod requires
  450. // explicit insturctions. So either lod or minLod or both must be zero.
  451. assert(lod == nullptr || minLod == nullptr);
  452. // An OpSampledImage is required to do the image sampling.
  453. auto *sampledImage = createSampledImage(imageType, image, sampler, loc);
  454. const auto mask = composeImageOperandsMask(
  455. bias, lod, grad, constOffset, varOffset, constOffsets, sample, minLod);
  456. auto *imageSampleInst = new (context)
  457. SpirvImageOp(op, texelType, loc, sampledImage, coordinate, mask,
  458. compareVal, bias, lod, grad.first, grad.second, constOffset,
  459. varOffset, constOffsets, sample, minLod);
  460. insertPoint->addInstruction(imageSampleInst);
  461. if (isSparse) {
  462. // Write the Residency Code
  463. const auto status = createCompositeExtract(astContext.UnsignedIntTy,
  464. imageSampleInst, {0}, loc);
  465. createStore(residencyCode, status, loc);
  466. // Extract the real result from the struct
  467. return createCompositeExtract(texelType, imageSampleInst, {1}, loc);
  468. }
  469. return imageSampleInst;
  470. }
  471. SpirvInstruction *SpirvBuilder::createImageFetchOrRead(
  472. bool doImageFetch, QualType texelType, QualType imageType,
  473. SpirvInstruction *image, SpirvInstruction *coordinate,
  474. SpirvInstruction *lod, SpirvInstruction *constOffset,
  475. SpirvInstruction *varOffset, SpirvInstruction *constOffsets,
  476. SpirvInstruction *sample, SpirvInstruction *residencyCode,
  477. SourceLocation loc) {
  478. assert(insertPoint && "null insert point");
  479. const auto mask = composeImageOperandsMask(
  480. /*bias*/ nullptr, lod, std::make_pair(nullptr, nullptr), constOffset,
  481. varOffset, constOffsets, sample, /*minLod*/ nullptr);
  482. const bool isSparse = (residencyCode != nullptr);
  483. spv::Op op =
  484. doImageFetch
  485. ? (isSparse ? spv::Op::OpImageSparseFetch : spv::Op::OpImageFetch)
  486. : (isSparse ? spv::Op::OpImageSparseRead : spv::Op::OpImageRead);
  487. auto *fetchOrReadInst = new (context) SpirvImageOp(
  488. op, texelType, loc, image, coordinate, mask,
  489. /*dref*/ nullptr, /*bias*/ nullptr, lod, /*gradDx*/ nullptr,
  490. /*gradDy*/ nullptr, constOffset, varOffset, constOffsets, sample);
  491. insertPoint->addInstruction(fetchOrReadInst);
  492. if (isSparse) {
  493. // Write the Residency Code
  494. const auto status = createCompositeExtract(astContext.UnsignedIntTy,
  495. fetchOrReadInst, {0}, loc);
  496. createStore(residencyCode, status, loc);
  497. // Extract the real result from the struct
  498. return createCompositeExtract(texelType, fetchOrReadInst, {1}, loc);
  499. }
  500. return fetchOrReadInst;
  501. }
  502. void SpirvBuilder::createImageWrite(QualType imageType, SpirvInstruction *image,
  503. SpirvInstruction *coord,
  504. SpirvInstruction *texel,
  505. SourceLocation loc) {
  506. assert(insertPoint && "null insert point");
  507. auto *writeInst = new (context) SpirvImageOp(
  508. spv::Op::OpImageWrite, imageType, loc, image, coord,
  509. spv::ImageOperandsMask::MaskNone,
  510. /*dref*/ nullptr, /*bias*/ nullptr, /*lod*/ nullptr, /*gradDx*/ nullptr,
  511. /*gradDy*/ nullptr, /*constOffset*/ nullptr, /*varOffset*/ nullptr,
  512. /*constOffsets*/ nullptr, /*sample*/ nullptr, /*minLod*/ nullptr,
  513. /*component*/ nullptr, texel);
  514. insertPoint->addInstruction(writeInst);
  515. }
  516. SpirvInstruction *SpirvBuilder::createImageGather(
  517. QualType texelType, QualType imageType, SpirvInstruction *image,
  518. SpirvInstruction *sampler, SpirvInstruction *coordinate,
  519. SpirvInstruction *component, SpirvInstruction *compareVal,
  520. SpirvInstruction *constOffset, SpirvInstruction *varOffset,
  521. SpirvInstruction *constOffsets, SpirvInstruction *sample,
  522. SpirvInstruction *residencyCode, SourceLocation loc) {
  523. assert(insertPoint && "null insert point");
  524. // An OpSampledImage is required to do the image sampling.
  525. auto *sampledImage = createSampledImage(imageType, image, sampler, loc);
  526. // TODO: Update ImageGather to accept minLod if necessary.
  527. const auto mask = composeImageOperandsMask(
  528. /*bias*/ nullptr, /*lod*/ nullptr, std::make_pair(nullptr, nullptr),
  529. constOffset, varOffset, constOffsets, sample, /*minLod*/ nullptr);
  530. spv::Op op = compareVal ? (residencyCode ? spv::Op::OpImageSparseDrefGather
  531. : spv::Op::OpImageDrefGather)
  532. : (residencyCode ? spv::Op::OpImageSparseGather
  533. : spv::Op::OpImageGather);
  534. // Note: OpImageSparseDrefGather and OpImageDrefGather do not take the
  535. // component parameter.
  536. if (compareVal)
  537. component = nullptr;
  538. auto *imageInstruction = new (context) SpirvImageOp(
  539. op, texelType, loc, sampledImage, coordinate, mask, compareVal,
  540. /*bias*/ nullptr, /*lod*/ nullptr, /*gradDx*/ nullptr,
  541. /*gradDy*/ nullptr, constOffset, varOffset, constOffsets, sample,
  542. /*minLod*/ nullptr, component);
  543. insertPoint->addInstruction(imageInstruction);
  544. if (residencyCode) {
  545. // Write the Residency Code
  546. const auto status = createCompositeExtract(astContext.UnsignedIntTy,
  547. imageInstruction, {0}, loc);
  548. createStore(residencyCode, status, loc);
  549. // Extract the real result from the struct
  550. return createCompositeExtract(texelType, imageInstruction, {1}, loc);
  551. }
  552. return imageInstruction;
  553. }
  554. SpirvImageSparseTexelsResident *
  555. SpirvBuilder::createImageSparseTexelsResident(SpirvInstruction *residentCode,
  556. SourceLocation loc) {
  557. assert(insertPoint && "null insert point");
  558. auto *inst = new (context)
  559. SpirvImageSparseTexelsResident(astContext.BoolTy, loc, residentCode);
  560. insertPoint->addInstruction(inst);
  561. return inst;
  562. }
  563. SpirvImageQuery *SpirvBuilder::createImageQuery(spv::Op opcode,
  564. QualType resultType,
  565. SourceLocation loc,
  566. SpirvInstruction *image,
  567. SpirvInstruction *lod) {
  568. assert(insertPoint && "null insert point");
  569. SpirvInstruction *lodParam = nullptr;
  570. SpirvInstruction *coordinateParam = nullptr;
  571. if (opcode == spv::Op::OpImageQuerySizeLod)
  572. lodParam = lod;
  573. if (opcode == spv::Op::OpImageQueryLod)
  574. coordinateParam = lod;
  575. auto *inst = new (context) SpirvImageQuery(opcode, resultType, loc, image,
  576. lodParam, coordinateParam);
  577. insertPoint->addInstruction(inst);
  578. return inst;
  579. }
  580. SpirvSelect *SpirvBuilder::createSelect(QualType resultType,
  581. SpirvInstruction *condition,
  582. SpirvInstruction *trueValue,
  583. SpirvInstruction *falseValue,
  584. SourceLocation loc) {
  585. assert(insertPoint && "null insert point");
  586. auto *inst = new (context)
  587. SpirvSelect(resultType, loc, condition, trueValue, falseValue);
  588. insertPoint->addInstruction(inst);
  589. return inst;
  590. }
  591. void SpirvBuilder::createSwitch(
  592. SpirvBasicBlock *mergeLabel, SpirvInstruction *selector,
  593. SpirvBasicBlock *defaultLabel,
  594. llvm::ArrayRef<std::pair<uint32_t, SpirvBasicBlock *>> target,
  595. SourceLocation loc) {
  596. assert(insertPoint && "null insert point");
  597. // Create the OpSelectioMerege.
  598. auto *selectionMerge = new (context)
  599. SpirvSelectionMerge(loc, mergeLabel, spv::SelectionControlMask::MaskNone);
  600. insertPoint->addInstruction(selectionMerge);
  601. // Create the OpSwitch.
  602. auto *switchInst =
  603. new (context) SpirvSwitch(loc, selector, defaultLabel, target);
  604. insertPoint->addInstruction(switchInst);
  605. }
  606. void SpirvBuilder::createKill(SourceLocation loc) {
  607. assert(insertPoint && "null insert point");
  608. auto *kill = new (context) SpirvKill(loc);
  609. insertPoint->addInstruction(kill);
  610. }
  611. void SpirvBuilder::createBranch(SpirvBasicBlock *targetLabel,
  612. SourceLocation loc, SpirvBasicBlock *mergeBB,
  613. SpirvBasicBlock *continueBB,
  614. spv::LoopControlMask loopControl) {
  615. assert(insertPoint && "null insert point");
  616. if (mergeBB && continueBB) {
  617. auto *loopMerge =
  618. new (context) SpirvLoopMerge(loc, mergeBB, continueBB, loopControl);
  619. insertPoint->addInstruction(loopMerge);
  620. }
  621. auto *branch = new (context) SpirvBranch(loc, targetLabel);
  622. insertPoint->addInstruction(branch);
  623. }
  624. void SpirvBuilder::createConditionalBranch(
  625. SpirvInstruction *condition, SpirvBasicBlock *trueLabel,
  626. SpirvBasicBlock *falseLabel, SourceLocation loc,
  627. SpirvBasicBlock *mergeLabel, SpirvBasicBlock *continueLabel,
  628. spv::SelectionControlMask selectionControl,
  629. spv::LoopControlMask loopControl) {
  630. assert(insertPoint && "null insert point");
  631. if (mergeLabel) {
  632. if (continueLabel) {
  633. auto *loopMerge = new (context)
  634. SpirvLoopMerge(loc, mergeLabel, continueLabel, loopControl);
  635. insertPoint->addInstruction(loopMerge);
  636. } else {
  637. auto *selectionMerge =
  638. new (context) SpirvSelectionMerge(loc, mergeLabel, selectionControl);
  639. insertPoint->addInstruction(selectionMerge);
  640. }
  641. }
  642. auto *branchConditional = new (context)
  643. SpirvBranchConditional(loc, condition, trueLabel, falseLabel);
  644. insertPoint->addInstruction(branchConditional);
  645. }
  646. void SpirvBuilder::createReturn(SourceLocation loc) {
  647. assert(insertPoint && "null insert point");
  648. insertPoint->addInstruction(new (context) SpirvReturn(loc));
  649. }
  650. void SpirvBuilder::createReturnValue(SpirvInstruction *value,
  651. SourceLocation loc) {
  652. assert(insertPoint && "null insert point");
  653. insertPoint->addInstruction(new (context) SpirvReturn(loc, value));
  654. }
  655. SpirvInstruction *
  656. SpirvBuilder::createGLSLExtInst(QualType resultType, GLSLstd450 inst,
  657. llvm::ArrayRef<SpirvInstruction *> operands,
  658. SourceLocation loc) {
  659. assert(insertPoint && "null insert point");
  660. auto *extInst = new (context) SpirvExtInst(
  661. resultType, loc, getExtInstSet("GLSL.std.450"), inst, operands);
  662. insertPoint->addInstruction(extInst);
  663. return extInst;
  664. }
  665. SpirvInstruction *
  666. SpirvBuilder::createGLSLExtInst(const SpirvType *resultType, GLSLstd450 inst,
  667. llvm::ArrayRef<SpirvInstruction *> operands,
  668. SourceLocation loc) {
  669. assert(insertPoint && "null insert point");
  670. auto *extInst = new (context) SpirvExtInst(
  671. /*QualType*/ {}, loc, getExtInstSet("GLSL.std.450"), inst, operands);
  672. extInst->setResultType(resultType);
  673. insertPoint->addInstruction(extInst);
  674. return extInst;
  675. }
  676. SpirvInstruction *SpirvBuilder::createNonSemanticDebugPrintfExtInst(
  677. QualType resultType, NonSemanticDebugPrintfInstructions instId,
  678. llvm::ArrayRef<SpirvInstruction *> operands, SourceLocation loc) {
  679. assert(insertPoint && "null insert point");
  680. auto *extInst = new (context)
  681. SpirvExtInst(resultType, loc, getExtInstSet("NonSemantic.DebugPrintf"),
  682. instId, operands);
  683. insertPoint->addInstruction(extInst);
  684. return extInst;
  685. }
  686. void SpirvBuilder::createBarrier(spv::Scope memoryScope,
  687. spv::MemorySemanticsMask memorySemantics,
  688. llvm::Optional<spv::Scope> exec,
  689. SourceLocation loc) {
  690. assert(insertPoint && "null insert point");
  691. SpirvBarrier *barrier =
  692. new (context) SpirvBarrier(loc, memoryScope, memorySemantics, exec);
  693. insertPoint->addInstruction(barrier);
  694. }
  695. SpirvBitFieldInsert *SpirvBuilder::createBitFieldInsert(
  696. QualType resultType, SpirvInstruction *base, SpirvInstruction *insert,
  697. SpirvInstruction *offset, SpirvInstruction *count, SourceLocation loc) {
  698. assert(insertPoint && "null insert point");
  699. auto *inst = new (context)
  700. SpirvBitFieldInsert(resultType, loc, base, insert, offset, count);
  701. insertPoint->addInstruction(inst);
  702. return inst;
  703. }
  704. SpirvBitFieldExtract *SpirvBuilder::createBitFieldExtract(
  705. QualType resultType, SpirvInstruction *base, SpirvInstruction *offset,
  706. SpirvInstruction *count, bool isSigned, SourceLocation loc) {
  707. assert(insertPoint && "null insert point");
  708. auto *inst = new (context)
  709. SpirvBitFieldExtract(resultType, loc, base, offset, count, isSigned);
  710. insertPoint->addInstruction(inst);
  711. return inst;
  712. }
  713. void SpirvBuilder::createEmitVertex(SourceLocation loc) {
  714. assert(insertPoint && "null insert point");
  715. auto *inst = new (context) SpirvEmitVertex(loc);
  716. insertPoint->addInstruction(inst);
  717. }
  718. void SpirvBuilder::createEndPrimitive(SourceLocation loc) {
  719. assert(insertPoint && "null insert point");
  720. auto *inst = new (context) SpirvEndPrimitive(loc);
  721. insertPoint->addInstruction(inst);
  722. }
  723. SpirvArrayLength *SpirvBuilder::createArrayLength(QualType resultType,
  724. SourceLocation loc,
  725. SpirvInstruction *structure,
  726. uint32_t arrayMember) {
  727. assert(insertPoint && "null insert point");
  728. auto *inst =
  729. new (context) SpirvArrayLength(resultType, loc, structure, arrayMember);
  730. insertPoint->addInstruction(inst);
  731. return inst;
  732. }
  733. SpirvInstruction *
  734. SpirvBuilder::createRayTracingOpsNV(spv::Op opcode, QualType resultType,
  735. ArrayRef<SpirvInstruction *> operands,
  736. SourceLocation loc) {
  737. assert(insertPoint && "null insert point");
  738. auto *inst =
  739. new (context) SpirvRayTracingOpNV(resultType, opcode, operands, loc);
  740. insertPoint->addInstruction(inst);
  741. return inst;
  742. }
  743. SpirvInstruction *
  744. SpirvBuilder::createDemoteToHelperInvocationEXT(SourceLocation loc) {
  745. assert(insertPoint && "null insert point");
  746. auto *inst = new (context) SpirvDemoteToHelperInvocationEXT(loc);
  747. insertPoint->addInstruction(inst);
  748. return inst;
  749. }
  750. SpirvDebugSource *SpirvBuilder::createDebugSource(llvm::StringRef file,
  751. llvm::StringRef text) {
  752. auto *inst = new (context) SpirvDebugSource(file, text);
  753. mod->addDebugInfo(inst);
  754. return inst;
  755. }
  756. SpirvDebugCompilationUnit *
  757. SpirvBuilder::createDebugCompilationUnit(SpirvDebugSource *source) {
  758. auto *inst = new (context) SpirvDebugCompilationUnit(
  759. /*version*/ 1, /*DWARF version*/ 4, source);
  760. mod->addDebugInfo(inst);
  761. return inst;
  762. }
  763. SpirvDebugLexicalBlock *
  764. SpirvBuilder::createDebugLexicalBlock(SpirvDebugSource *source, uint32_t line,
  765. uint32_t column,
  766. SpirvDebugInstruction *parent) {
  767. assert(insertPoint && "null insert point");
  768. auto *inst =
  769. new (context) SpirvDebugLexicalBlock(source, line, column, parent);
  770. mod->addDebugInfo(inst);
  771. return inst;
  772. }
  773. SpirvDebugLocalVariable *SpirvBuilder::createDebugLocalVariable(
  774. QualType debugQualType, llvm::StringRef varName, SpirvDebugSource *src,
  775. uint32_t line, uint32_t column, SpirvDebugInstruction *parentScope,
  776. uint32_t flags, llvm::Optional<uint32_t> argNumber) {
  777. auto *inst = new (context) SpirvDebugLocalVariable(
  778. debugQualType, varName, src, line, column, parentScope, flags, argNumber);
  779. mod->addDebugInfo(inst);
  780. return inst;
  781. }
  782. SpirvDebugGlobalVariable *SpirvBuilder::createDebugGlobalVariable(
  783. QualType debugType, llvm::StringRef varName, SpirvDebugSource *src,
  784. uint32_t line, uint32_t column, SpirvDebugInstruction *parentScope,
  785. llvm::StringRef linkageName, SpirvVariable *var, uint32_t flags,
  786. llvm::Optional<SpirvInstruction *> staticMemberDebugType) {
  787. auto *inst = new (context) SpirvDebugGlobalVariable(
  788. debugType, varName, src, line, column, parentScope, linkageName, var,
  789. flags, staticMemberDebugType);
  790. mod->addDebugInfo(inst);
  791. return inst;
  792. }
  793. SpirvDebugInfoNone *SpirvBuilder::getOrCreateDebugInfoNone() {
  794. if (debugNone)
  795. return debugNone;
  796. debugNone = new (context) SpirvDebugInfoNone();
  797. mod->addDebugInfo(debugNone);
  798. return debugNone;
  799. }
  800. SpirvDebugExpression *SpirvBuilder::getOrCreateNullDebugExpression() {
  801. if (nullDebugExpr)
  802. return nullDebugExpr;
  803. nullDebugExpr = new (context) SpirvDebugExpression();
  804. mod->addDebugInfo(nullDebugExpr);
  805. return nullDebugExpr;
  806. }
  807. SpirvDebugDeclare *SpirvBuilder::createDebugDeclare(
  808. SpirvDebugLocalVariable *dbgVar, SpirvInstruction *var,
  809. llvm::Optional<SpirvDebugExpression *> dbgExpr) {
  810. auto *decl = new (context)
  811. SpirvDebugDeclare(dbgVar, var,
  812. dbgExpr.hasValue() ? dbgExpr.getValue()
  813. : getOrCreateNullDebugExpression());
  814. if (isa<SpirvFunctionParameter>(var)) {
  815. assert(function && "found detached parameter");
  816. function->addParameterDebugDeclare(decl);
  817. } else {
  818. assert(insertPoint && "null insert point");
  819. insertPoint->addInstruction(decl);
  820. }
  821. return decl;
  822. }
  823. SpirvDebugFunction *SpirvBuilder::createDebugFunction(
  824. const FunctionDecl *decl, llvm::StringRef name, SpirvDebugSource *src,
  825. uint32_t line, uint32_t column, SpirvDebugInstruction *parentScope,
  826. llvm::StringRef linkageName, uint32_t flags, uint32_t scopeLine,
  827. SpirvFunction *fn) {
  828. auto *inst = new (context) SpirvDebugFunction(
  829. name, src, line, column, parentScope, linkageName, flags, scopeLine, fn);
  830. mod->addDebugInfo(inst);
  831. context.registerDebugFunctionForDecl(decl, inst);
  832. return inst;
  833. }
  834. SpirvInstruction *
  835. SpirvBuilder::createRayQueryOpsKHR(spv::Op opcode, QualType resultType,
  836. ArrayRef<SpirvInstruction *> operands,
  837. bool cullFlags, SourceLocation loc) {
  838. assert(insertPoint && "null insert point");
  839. auto *inst = new (context)
  840. SpirvRayQueryOpKHR(resultType, opcode, operands, cullFlags, loc);
  841. insertPoint->addInstruction(inst);
  842. return inst;
  843. }
  844. SpirvInstruction *SpirvBuilder::createReadClock(SpirvInstruction *scope,
  845. SourceLocation loc) {
  846. assert(insertPoint && "null insert point");
  847. assert(scope->getAstResultType()->isIntegerType());
  848. auto *inst =
  849. new (context) SpirvReadClock(astContext.UnsignedLongLongTy, scope, loc);
  850. insertPoint->addInstruction(inst);
  851. return inst;
  852. }
  853. void SpirvBuilder::createRaytracingTerminateKHR(spv::Op opcode,
  854. SourceLocation loc) {
  855. assert(insertPoint && "null insert point");
  856. auto *inst = new (context) SpirvRayTracingTerminateOpKHR(opcode, loc);
  857. insertPoint->addInstruction(inst);
  858. }
  859. void SpirvBuilder::createCopyArrayInFxcCTBufferToClone(
  860. const ArrayType *fxcCTBufferArrTy, SpirvInstruction *fxcCTBuffer,
  861. const SpirvType *cloneType, SpirvInstruction *clone, SourceLocation loc) {
  862. const SpirvPointerType *cloneElemPtrTy = nullptr;
  863. const SpirvPointerType *fxcCTBufferElemPtrTy = nullptr;
  864. if (auto *cloneArrTy = dyn_cast<ArrayType>(cloneType)) {
  865. assert(fxcCTBufferArrTy->getElementCount() ==
  866. cloneArrTy->getElementCount());
  867. cloneElemPtrTy = context.getPointerType(cloneArrTy->getElementType(),
  868. clone->getStorageClass());
  869. fxcCTBufferElemPtrTy = context.getPointerType(
  870. fxcCTBufferArrTy->getElementType(), fxcCTBuffer->getStorageClass());
  871. } else if (auto *cloneVecTy = dyn_cast<VectorType>(cloneType)) {
  872. // float1xN must be float[N] for CTBuffer data filling but it should be
  873. // used as a vector of N floats in SPIR-V instructions.
  874. assert(fxcCTBufferArrTy->getElementCount() ==
  875. cloneVecTy->getElementCount());
  876. cloneElemPtrTy = context.getPointerType(cloneVecTy->getElementType(),
  877. clone->getStorageClass());
  878. fxcCTBufferElemPtrTy = context.getPointerType(
  879. fxcCTBufferArrTy->getElementType(), fxcCTBuffer->getStorageClass());
  880. } else {
  881. llvm_unreachable("Unexpected destination type");
  882. }
  883. for (uint32_t i = 0; i < fxcCTBufferArrTy->getElementCount(); ++i) {
  884. auto *ptrToFxcCTBufferElem = createAccessChain(
  885. fxcCTBufferElemPtrTy, fxcCTBuffer,
  886. {getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, i))}, loc);
  887. context.addToInstructionsWithLoweredType(ptrToFxcCTBufferElem);
  888. auto *ptrToCloneElem = createAccessChain(
  889. cloneElemPtrTy, clone,
  890. {getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, i))}, loc);
  891. context.addToInstructionsWithLoweredType(ptrToCloneElem);
  892. createCopyInstructionsFromFxcCTBufferToClone(ptrToFxcCTBufferElem,
  893. ptrToCloneElem);
  894. }
  895. }
  896. void SpirvBuilder::createCopyStructInFxcCTBufferToClone(
  897. const StructType *fxcCTBufferStructTy, SpirvInstruction *fxcCTBuffer,
  898. const SpirvType *cloneType, SpirvInstruction *clone, SourceLocation loc) {
  899. if (auto *cloneStructTy = dyn_cast<StructType>(cloneType)) {
  900. auto fxcCTBufferFields = fxcCTBufferStructTy->getFields();
  901. auto cloneFields = cloneStructTy->getFields();
  902. assert(fxcCTBufferFields.size() == cloneFields.size());
  903. for (uint32_t i = 0; i < fxcCTBufferFields.size(); ++i) {
  904. auto *fxcCTBufferElemPtrTy = context.getPointerType(
  905. fxcCTBufferFields[i].type, fxcCTBuffer->getStorageClass());
  906. auto *ptrToFxcCTBufferElem = createAccessChain(
  907. fxcCTBufferElemPtrTy, fxcCTBuffer,
  908. {getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, i))}, loc);
  909. context.addToInstructionsWithLoweredType(ptrToFxcCTBufferElem);
  910. auto *cloneElemPtrTy =
  911. context.getPointerType(cloneFields[i].type, clone->getStorageClass());
  912. auto *ptrToCloneElem = createAccessChain(
  913. cloneElemPtrTy, clone,
  914. {getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, i))}, loc);
  915. context.addToInstructionsWithLoweredType(ptrToCloneElem);
  916. createCopyInstructionsFromFxcCTBufferToClone(ptrToFxcCTBufferElem,
  917. ptrToCloneElem);
  918. }
  919. } else {
  920. llvm_unreachable("Unexpected destination type");
  921. }
  922. }
  923. void SpirvBuilder::createCopyInstructionsFromFxcCTBufferToClone(
  924. SpirvInstruction *fxcCTBuffer, SpirvInstruction *clone) {
  925. assert(clone != nullptr && fxcCTBuffer != nullptr);
  926. assert(clone->getResultType() != nullptr &&
  927. fxcCTBuffer->getResultType() != nullptr);
  928. assert(fxcCTBuffer->getLayoutRule() == SpirvLayoutRule::FxcCTBuffer &&
  929. clone->getLayoutRule() == SpirvLayoutRule::Void);
  930. auto *clonePtrType = dyn_cast<SpirvPointerType>(clone->getResultType());
  931. auto *fxcCTBufferPtrType =
  932. dyn_cast<SpirvPointerType>(fxcCTBuffer->getResultType());
  933. assert(clonePtrType != nullptr && fxcCTBufferPtrType != nullptr);
  934. auto *cloneType = clonePtrType->getPointeeType();
  935. auto *fxcCTBufferType = fxcCTBufferPtrType->getPointeeType();
  936. assert(cloneType != nullptr && fxcCTBufferType != nullptr);
  937. auto loc = fxcCTBuffer->getSourceLocation();
  938. if (auto *fxcCTBufferArrTy = dyn_cast<ArrayType>(fxcCTBufferType)) {
  939. createCopyArrayInFxcCTBufferToClone(fxcCTBufferArrTy, fxcCTBuffer,
  940. cloneType, clone, loc);
  941. } else if (auto *fxcCTBufferStructTy =
  942. dyn_cast<StructType>(fxcCTBufferType)) {
  943. createCopyStructInFxcCTBufferToClone(fxcCTBufferStructTy, fxcCTBuffer,
  944. cloneType, clone, loc);
  945. } else if (fxcCTBufferType->getKind() == SpirvType::TK_Bool ||
  946. fxcCTBufferType->getKind() == SpirvType::TK_Integer ||
  947. fxcCTBufferType->getKind() == SpirvType::TK_Float ||
  948. fxcCTBufferType->getKind() == SpirvType::TK_Vector ||
  949. fxcCTBufferType->getKind() == SpirvType::TK_Matrix) {
  950. auto *load = createLoad(fxcCTBufferType, fxcCTBuffer, loc);
  951. context.addToInstructionsWithLoweredType(load);
  952. createStore(clone, load, loc);
  953. } else {
  954. llvm_unreachable(
  955. "We expect only composite types are accessed with indexes");
  956. }
  957. }
  958. void SpirvBuilder::switchInsertPointToModuleInit() {
  959. if (moduleInitInsertPoint == nullptr) {
  960. moduleInit = createSpirvFunction(astContext.VoidTy, SourceLocation(),
  961. "module.init", false);
  962. moduleInitInsertPoint = new (context) SpirvBasicBlock("module.init.bb");
  963. moduleInit->addBasicBlock(moduleInitInsertPoint);
  964. }
  965. assert(moduleInitInsertPoint && "null module init insert point");
  966. insertPoint = moduleInitInsertPoint;
  967. }
  968. SpirvVariable *SpirvBuilder::createCloneVarForFxcCTBuffer(
  969. QualType astType, const SpirvType *spvType, SpirvInstruction *var) {
  970. SpirvVariable *clone = nullptr;
  971. if (astType != QualType({})) {
  972. clone =
  973. addModuleVar(astType, spv::StorageClass::Private, var->isPrecise(),
  974. var->getDebugName(), llvm::None, var->getSourceLocation());
  975. } else {
  976. if (const auto *ty = dyn_cast<StructType>(spvType)) {
  977. spvType = context.getStructType(ty->getFields(), ty->getName(),
  978. ty->isReadOnly(),
  979. StructInterfaceType::InternalStorage);
  980. } else if (const auto *ty = dyn_cast<HybridStructType>(spvType)) {
  981. spvType = context.getHybridStructType(
  982. ty->getFields(), ty->getName(), ty->isReadOnly(),
  983. StructInterfaceType::InternalStorage);
  984. }
  985. clone =
  986. addModuleVar(spvType, spv::StorageClass::Private, var->isPrecise(),
  987. var->getDebugName(), llvm::None, var->getSourceLocation());
  988. }
  989. clone->setLayoutRule(SpirvLayoutRule::Void);
  990. return clone;
  991. }
  992. SpirvInstruction *
  993. SpirvBuilder::initializeCloneVarForFxcCTBuffer(SpirvInstruction *instr) {
  994. assert(instr);
  995. if (instr == nullptr)
  996. return nullptr;
  997. if (instr->getLayoutRule() != SpirvLayoutRule::FxcCTBuffer)
  998. return nullptr;
  999. SpirvVariable *var = dyn_cast<SpirvVariable>(instr);
  1000. if (var == nullptr)
  1001. return nullptr;
  1002. // If we already generated a clone for the given CTBuffer, return it.
  1003. auto cloneItr = fxcCTBufferToClone.find(var);
  1004. if (cloneItr != fxcCTBufferToClone.end())
  1005. return cloneItr->second;
  1006. auto astType = var->getAstResultType();
  1007. const auto *spvType = var->getResultType();
  1008. LowerTypeVisitor lowerTypeVisitor(astContext, context, spirvOptions);
  1009. lowerTypeVisitor.visitInstruction(var);
  1010. context.addToInstructionsWithLoweredType(instr);
  1011. if (!lowerTypeVisitor.useSpvArrayForHlslMat1xN()) {
  1012. return nullptr;
  1013. }
  1014. auto *oldInsertPoint = insertPoint;
  1015. switchInsertPointToModuleInit();
  1016. SpirvVariable *clone = createCloneVarForFxcCTBuffer(astType, spvType, var);
  1017. lowerTypeVisitor.visitInstruction(clone);
  1018. context.addToInstructionsWithLoweredType(clone);
  1019. createCopyInstructionsFromFxcCTBufferToClone(var, clone);
  1020. fxcCTBufferToClone[var] = clone;
  1021. insertPoint = oldInsertPoint;
  1022. return clone;
  1023. }
  1024. void SpirvBuilder::addModuleProcessed(llvm::StringRef process) {
  1025. mod->addModuleProcessed(new (context) SpirvModuleProcessed({}, process));
  1026. }
  1027. SpirvExtInstImport *SpirvBuilder::getExtInstSet(llvm::StringRef extName) {
  1028. SpirvExtInstImport *set = mod->getExtInstSet(extName);
  1029. if (!set) {
  1030. // The extended instruction set is likely required for several different
  1031. // reasons. We can't pinpoint the source location for one specific function.
  1032. set = new (context) SpirvExtInstImport(/*SourceLocation*/ {}, extName);
  1033. mod->addExtInstSet(set);
  1034. }
  1035. return set;
  1036. }
  1037. SpirvExtInstImport *SpirvBuilder::getOpenCLDebugInfoExtInstSet() {
  1038. return getExtInstSet("OpenCL.DebugInfo.100");
  1039. }
  1040. SpirvVariable *SpirvBuilder::addStageIOVar(QualType type,
  1041. spv::StorageClass storageClass,
  1042. std::string name, bool isPrecise,
  1043. SourceLocation loc) {
  1044. // Note: We store the underlying type in the variable, *not* the pointer type.
  1045. auto *var = new (context) SpirvVariable(type, loc, storageClass, isPrecise);
  1046. var->setDebugName(name);
  1047. mod->addVariable(var);
  1048. return var;
  1049. }
  1050. SpirvVariable *SpirvBuilder::addStageBuiltinVar(QualType type,
  1051. spv::StorageClass storageClass,
  1052. spv::BuiltIn builtin,
  1053. bool isPrecise,
  1054. SourceLocation loc) {
  1055. // If the built-in variable has already been added (via a built-in alias),
  1056. // return the existing variable.
  1057. auto found = std::find_if(
  1058. builtinVars.begin(), builtinVars.end(),
  1059. [storageClass, builtin](const BuiltInVarInfo &varInfo) {
  1060. return varInfo.sc == storageClass && varInfo.builtIn == builtin;
  1061. });
  1062. if (found != builtinVars.end()) {
  1063. return found->variable;
  1064. }
  1065. // Note: We store the underlying type in the variable, *not* the pointer type.
  1066. auto *var = new (context) SpirvVariable(type, loc, storageClass, isPrecise);
  1067. mod->addVariable(var);
  1068. // Decorate with the specified Builtin
  1069. auto *decor = new (context) SpirvDecoration(
  1070. loc, var, spv::Decoration::BuiltIn, {static_cast<uint32_t>(builtin)});
  1071. mod->addDecoration(decor);
  1072. // Add variable to cache.
  1073. builtinVars.emplace_back(storageClass, builtin, var);
  1074. return var;
  1075. }
  1076. SpirvVariable *
  1077. SpirvBuilder::addModuleVar(QualType type, spv::StorageClass storageClass,
  1078. bool isPrecise, llvm::StringRef name,
  1079. llvm::Optional<SpirvInstruction *> init,
  1080. SourceLocation loc) {
  1081. assert(storageClass != spv::StorageClass::Function);
  1082. // Note: We store the underlying type in the variable, *not* the pointer type.
  1083. auto *var =
  1084. new (context) SpirvVariable(type, loc, storageClass, isPrecise,
  1085. init.hasValue() ? init.getValue() : nullptr);
  1086. var->setDebugName(name);
  1087. mod->addVariable(var);
  1088. return var;
  1089. }
  1090. SpirvVariable *SpirvBuilder::addModuleVar(
  1091. const SpirvType *type, spv::StorageClass storageClass, bool isPrecise,
  1092. llvm::StringRef name, llvm::Optional<SpirvInstruction *> init,
  1093. SourceLocation loc) {
  1094. assert(storageClass != spv::StorageClass::Function);
  1095. // Note: We store the underlying type in the variable, *not* the pointer type.
  1096. auto *var =
  1097. new (context) SpirvVariable(/*QualType*/ {}, loc, storageClass, isPrecise,
  1098. init.hasValue() ? init.getValue() : nullptr);
  1099. var->setResultType(type);
  1100. var->setDebugName(name);
  1101. mod->addVariable(var);
  1102. return var;
  1103. }
  1104. void SpirvBuilder::decorateLocation(SpirvInstruction *target,
  1105. uint32_t location) {
  1106. auto *decor =
  1107. new (context) SpirvDecoration(target->getSourceLocation(), target,
  1108. spv::Decoration::Location, {location});
  1109. mod->addDecoration(decor);
  1110. }
  1111. void SpirvBuilder::decorateIndex(SpirvInstruction *target, uint32_t index,
  1112. SourceLocation srcLoc) {
  1113. auto *decor = new (context)
  1114. SpirvDecoration(srcLoc, target, spv::Decoration::Index, {index});
  1115. mod->addDecoration(decor);
  1116. }
  1117. void SpirvBuilder::decorateDSetBinding(SpirvVariable *target,
  1118. uint32_t setNumber,
  1119. uint32_t bindingNumber) {
  1120. const SourceLocation srcLoc = target->getSourceLocation();
  1121. auto *dset = new (context) SpirvDecoration(
  1122. srcLoc, target, spv::Decoration::DescriptorSet, {setNumber});
  1123. mod->addDecoration(dset);
  1124. auto *binding = new (context) SpirvDecoration(
  1125. srcLoc, target, spv::Decoration::Binding, {bindingNumber});
  1126. target->setDescriptorSetNo(setNumber);
  1127. target->setBindingNo(bindingNumber);
  1128. mod->addDecoration(binding);
  1129. }
  1130. void SpirvBuilder::decorateSpecId(SpirvInstruction *target, uint32_t specId,
  1131. SourceLocation srcLoc) {
  1132. auto *decor = new (context)
  1133. SpirvDecoration(srcLoc, target, spv::Decoration::SpecId, {specId});
  1134. mod->addDecoration(decor);
  1135. }
  1136. void SpirvBuilder::decorateInputAttachmentIndex(SpirvInstruction *target,
  1137. uint32_t indexNumber,
  1138. SourceLocation srcLoc) {
  1139. auto *decor = new (context) SpirvDecoration(
  1140. srcLoc, target, spv::Decoration::InputAttachmentIndex, {indexNumber});
  1141. mod->addDecoration(decor);
  1142. }
  1143. void SpirvBuilder::decorateCounterBuffer(SpirvInstruction *mainBuffer,
  1144. SpirvInstruction *counterBuffer,
  1145. SourceLocation srcLoc) {
  1146. if (spirvOptions.enableReflect) {
  1147. auto *decor = new (context) SpirvDecoration(
  1148. srcLoc, mainBuffer, spv::Decoration::HlslCounterBufferGOOGLE,
  1149. {counterBuffer});
  1150. mod->addDecoration(decor);
  1151. }
  1152. }
  1153. void SpirvBuilder::decorateHlslSemantic(SpirvInstruction *target,
  1154. llvm::StringRef semantic,
  1155. llvm::Optional<uint32_t> memberIdx) {
  1156. if (spirvOptions.enableReflect) {
  1157. auto *decor = new (context) SpirvDecoration(
  1158. target->getSourceLocation(), target,
  1159. spv::Decoration::HlslSemanticGOOGLE, semantic, memberIdx);
  1160. mod->addDecoration(decor);
  1161. }
  1162. }
  1163. void SpirvBuilder::decorateCentroid(SpirvInstruction *target,
  1164. SourceLocation srcLoc) {
  1165. auto *decor =
  1166. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::Centroid);
  1167. mod->addDecoration(decor);
  1168. }
  1169. void SpirvBuilder::decorateFlat(SpirvInstruction *target,
  1170. SourceLocation srcLoc) {
  1171. auto *decor =
  1172. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::Flat);
  1173. mod->addDecoration(decor);
  1174. }
  1175. void SpirvBuilder::decorateNoPerspective(SpirvInstruction *target,
  1176. SourceLocation srcLoc) {
  1177. auto *decor = new (context)
  1178. SpirvDecoration(srcLoc, target, spv::Decoration::NoPerspective);
  1179. mod->addDecoration(decor);
  1180. }
  1181. void SpirvBuilder::decorateSample(SpirvInstruction *target,
  1182. SourceLocation srcLoc) {
  1183. auto *decor =
  1184. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::Sample);
  1185. mod->addDecoration(decor);
  1186. }
  1187. void SpirvBuilder::decoratePatch(SpirvInstruction *target,
  1188. SourceLocation srcLoc) {
  1189. auto *decor =
  1190. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::Patch);
  1191. mod->addDecoration(decor);
  1192. }
  1193. void SpirvBuilder::decorateNoContraction(SpirvInstruction *target,
  1194. SourceLocation srcLoc) {
  1195. auto *decor = new (context)
  1196. SpirvDecoration(srcLoc, target, spv::Decoration::NoContraction);
  1197. mod->addDecoration(decor);
  1198. }
  1199. void SpirvBuilder::decoratePerPrimitiveNV(SpirvInstruction *target,
  1200. SourceLocation srcLoc) {
  1201. auto *decor = new (context)
  1202. SpirvDecoration(srcLoc, target, spv::Decoration::PerPrimitiveNV);
  1203. mod->addDecoration(decor);
  1204. }
  1205. void SpirvBuilder::decoratePerTaskNV(SpirvInstruction *target, uint32_t offset,
  1206. SourceLocation srcLoc) {
  1207. auto *decor =
  1208. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::PerTaskNV);
  1209. mod->addDecoration(decor);
  1210. decor = new (context)
  1211. SpirvDecoration(srcLoc, target, spv::Decoration::Offset, {offset});
  1212. mod->addDecoration(decor);
  1213. }
  1214. void SpirvBuilder::decorateCoherent(SpirvInstruction *target,
  1215. SourceLocation srcLoc) {
  1216. auto *decor =
  1217. new (context) SpirvDecoration(srcLoc, target, spv::Decoration::Coherent);
  1218. mod->addDecoration(decor);
  1219. }
  1220. SpirvConstant *SpirvBuilder::getConstantInt(QualType type, llvm::APInt value,
  1221. bool specConst) {
  1222. // We do not reuse existing constant integers. Just create a new one.
  1223. auto *intConst = new (context) SpirvConstantInteger(type, value, specConst);
  1224. mod->addConstant(intConst);
  1225. return intConst;
  1226. }
  1227. SpirvConstant *SpirvBuilder::getConstantFloat(QualType type,
  1228. llvm::APFloat value,
  1229. bool specConst) {
  1230. // We do not reuse existing constant floats. Just create a new one.
  1231. auto *floatConst = new (context) SpirvConstantFloat(type, value, specConst);
  1232. mod->addConstant(floatConst);
  1233. return floatConst;
  1234. }
  1235. SpirvConstant *SpirvBuilder::getConstantBool(bool value, bool specConst) {
  1236. // We do not care about making unique constants at this point.
  1237. auto *boolConst =
  1238. new (context) SpirvConstantBoolean(astContext.BoolTy, value, specConst);
  1239. mod->addConstant(boolConst);
  1240. return boolConst;
  1241. }
  1242. SpirvConstant *
  1243. SpirvBuilder::getConstantComposite(QualType compositeType,
  1244. llvm::ArrayRef<SpirvConstant *> constituents,
  1245. bool specConst) {
  1246. // We do not care about making unique constants at this point.
  1247. auto *compositeConst = new (context)
  1248. SpirvConstantComposite(compositeType, constituents, specConst);
  1249. mod->addConstant(compositeConst);
  1250. return compositeConst;
  1251. }
  1252. SpirvConstant *SpirvBuilder::getConstantNull(QualType type) {
  1253. // We do not care about making unique constants at this point.
  1254. auto *nullConst = new (context) SpirvConstantNull(type);
  1255. mod->addConstant(nullConst);
  1256. return nullConst;
  1257. }
  1258. SpirvString *SpirvBuilder::getString(llvm::StringRef str) {
  1259. // Reuse an existing instruction if possible.
  1260. auto iter = stringLiterals.find(str.str());
  1261. if (iter != stringLiterals.end())
  1262. return iter->second;
  1263. // Create a SpirvString instruction
  1264. auto *instr = new (context) SpirvString(/* SourceLocation */ {}, str);
  1265. instr->setRValue();
  1266. stringLiterals[str.str()] = instr;
  1267. mod->addString(instr);
  1268. return instr;
  1269. }
  1270. void SpirvBuilder::addModuleInitCallToEntryPoints() {
  1271. if (moduleInit == nullptr)
  1272. return;
  1273. for (auto *entry : mod->getEntryPoints()) {
  1274. auto *instruction = new (context)
  1275. SpirvFunctionCall(astContext.VoidTy, /* SourceLocation */ {},
  1276. moduleInit, /* params */ {});
  1277. instruction->setRValue(true);
  1278. entry->getEntryPoint()->addFirstInstruction(instruction);
  1279. }
  1280. }
  1281. void SpirvBuilder::endModuleInitFunction() {
  1282. if (moduleInitInsertPoint == nullptr ||
  1283. moduleInitInsertPoint->hasTerminator()) {
  1284. return;
  1285. }
  1286. auto *oldInsertPoint = insertPoint;
  1287. switchInsertPointToModuleInit();
  1288. createReturn(/* SourceLocation */ {});
  1289. insertPoint = oldInsertPoint;
  1290. mod->addFunctionToListOfSortedModuleFunctions(moduleInit);
  1291. }
  1292. std::vector<uint32_t> SpirvBuilder::takeModule() {
  1293. endModuleInitFunction();
  1294. addModuleInitCallToEntryPoints();
  1295. // Run necessary visitor passes first
  1296. LiteralTypeVisitor literalTypeVisitor(astContext, context, spirvOptions);
  1297. LowerTypeVisitor lowerTypeVisitor(astContext, context, spirvOptions);
  1298. CapabilityVisitor capabilityVisitor(astContext, context, spirvOptions, *this);
  1299. RelaxedPrecisionVisitor relaxedPrecisionVisitor(context, spirvOptions);
  1300. PreciseVisitor preciseVisitor(context, spirvOptions);
  1301. NonUniformVisitor nonUniformVisitor(context, spirvOptions);
  1302. RemoveBufferBlockVisitor removeBufferBlockVisitor(astContext, context,
  1303. spirvOptions);
  1304. EmitVisitor emitVisitor(astContext, context, spirvOptions);
  1305. mod->invokeVisitor(&literalTypeVisitor, true);
  1306. // Propagate NonUniform decorations
  1307. mod->invokeVisitor(&nonUniformVisitor);
  1308. // Lower types
  1309. mod->invokeVisitor(&lowerTypeVisitor);
  1310. // Generate debug types (if needed)
  1311. if (spirvOptions.debugInfoRich) {
  1312. DebugTypeVisitor debugTypeVisitor(astContext, context, spirvOptions, *this,
  1313. lowerTypeVisitor);
  1314. SortDebugInfoVisitor sortDebugInfoVisitor(context, spirvOptions);
  1315. mod->invokeVisitor(&debugTypeVisitor);
  1316. mod->invokeVisitor(&sortDebugInfoVisitor);
  1317. }
  1318. // Add necessary capabilities and extensions
  1319. mod->invokeVisitor(&capabilityVisitor);
  1320. // Propagate RelaxedPrecision decorations
  1321. mod->invokeVisitor(&relaxedPrecisionVisitor);
  1322. // Propagate NoContraction decorations
  1323. mod->invokeVisitor(&preciseVisitor, true);
  1324. // Remove BufferBlock decoration if necessary (this decoration is deprecated
  1325. // after SPIR-V 1.3).
  1326. mod->invokeVisitor(&removeBufferBlockVisitor);
  1327. // Emit SPIR-V
  1328. mod->invokeVisitor(&emitVisitor);
  1329. return emitVisitor.takeBinary();
  1330. }
  1331. } // end namespace spirv
  1332. } // end namespace clang