SpirvBuilder.cpp 50 KB

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