SPIRVEmitter.h 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. //===------- SPIRVEmitter.h - SPIR-V Binary Code Emitter --------*- 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. // This file defines a SPIR-V emitter class that takes in HLSL AST and emits
  10. // SPIR-V binary words.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_LIB_SPIRV_SPIRVEMITTER_H
  14. #define LLVM_CLANG_LIB_SPIRV_SPIRVEMITTER_H
  15. #include <stack>
  16. #include <string>
  17. #include <utility>
  18. #include <vector>
  19. #include "dxc/HLSL/DxilShaderModel.h"
  20. #include "dxc/HlslIntrinsicOp.h"
  21. #include "spirv/unified1/GLSL.std.450.h"
  22. #include "clang/AST/AST.h"
  23. #include "clang/AST/ASTConsumer.h"
  24. #include "clang/AST/ASTContext.h"
  25. #include "clang/Basic/Diagnostic.h"
  26. #include "clang/Frontend/CompilerInstance.h"
  27. #include "clang/SPIRV/EmitSPIRVOptions.h"
  28. #include "clang/SPIRV/FeatureManager.h"
  29. #include "clang/SPIRV/ModuleBuilder.h"
  30. #include "llvm/ADT/STLExtras.h"
  31. #include "llvm/ADT/SetVector.h"
  32. #include "DeclResultIdMapper.h"
  33. #include "SpirvEvalInfo.h"
  34. #include "TypeTranslator.h"
  35. namespace clang {
  36. namespace spirv {
  37. /// SPIR-V emitter class. It consumes the HLSL AST and emits SPIR-V words.
  38. ///
  39. /// This class only overrides the HandleTranslationUnit() method; Traversing
  40. /// through the AST is done manually instead of using ASTConsumer's harness.
  41. class SPIRVEmitter : public ASTConsumer {
  42. public:
  43. SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options);
  44. void HandleTranslationUnit(ASTContext &context) override;
  45. ASTContext &getASTContext() { return astContext; }
  46. ModuleBuilder &getModuleBuilder() { return theBuilder; }
  47. TypeTranslator &getTypeTranslator() { return typeTranslator; }
  48. DiagnosticsEngine &getDiagnosticsEngine() { return diags; }
  49. void doDecl(const Decl *decl);
  50. void doStmt(const Stmt *stmt, llvm::ArrayRef<const Attr *> attrs = {});
  51. SpirvEvalInfo doExpr(const Expr *expr);
  52. /// Processes the given expression and emits SPIR-V instructions. If the
  53. /// result is a GLValue, does an additional load.
  54. ///
  55. /// This method is useful for cases where ImplicitCastExpr (LValueToRValue) is
  56. /// missing when using an lvalue as rvalue in the AST, e.g., DeclRefExpr will
  57. /// not be wrapped in ImplicitCastExpr (LValueToRValue) when appearing in
  58. /// HLSLVectorElementExpr since the generated HLSLVectorElementExpr itself can
  59. /// be lvalue or rvalue.
  60. SpirvEvalInfo loadIfGLValue(const Expr *expr);
  61. /// Casts the given value from fromType to toType. fromType and toType should
  62. /// both be scalar or vector types of the same size.
  63. uint32_t castToType(uint32_t value, QualType fromType, QualType toType,
  64. SourceLocation);
  65. private:
  66. void doFunctionDecl(const FunctionDecl *decl);
  67. void doVarDecl(const VarDecl *decl);
  68. void doRecordDecl(const RecordDecl *decl);
  69. void doHLSLBufferDecl(const HLSLBufferDecl *decl);
  70. void doBreakStmt(const BreakStmt *stmt);
  71. void doDiscardStmt(const DiscardStmt *stmt);
  72. inline void doDeclStmt(const DeclStmt *stmt);
  73. void doForStmt(const ForStmt *, llvm::ArrayRef<const Attr *> attrs = {});
  74. void doIfStmt(const IfStmt *ifStmt, llvm::ArrayRef<const Attr *> attrs = {});
  75. void doReturnStmt(const ReturnStmt *stmt);
  76. void doSwitchStmt(const SwitchStmt *stmt,
  77. llvm::ArrayRef<const Attr *> attrs = {});
  78. void doWhileStmt(const WhileStmt *, llvm::ArrayRef<const Attr *> attrs = {});
  79. void doDoStmt(const DoStmt *, llvm::ArrayRef<const Attr *> attrs = {});
  80. void doContinueStmt(const ContinueStmt *);
  81. SpirvEvalInfo doArraySubscriptExpr(const ArraySubscriptExpr *expr);
  82. SpirvEvalInfo doBinaryOperator(const BinaryOperator *expr);
  83. SpirvEvalInfo doCallExpr(const CallExpr *callExpr);
  84. SpirvEvalInfo doCastExpr(const CastExpr *expr);
  85. SpirvEvalInfo doCompoundAssignOperator(const CompoundAssignOperator *expr);
  86. SpirvEvalInfo doConditionalOperator(const ConditionalOperator *expr);
  87. SpirvEvalInfo doCXXMemberCallExpr(const CXXMemberCallExpr *expr);
  88. SpirvEvalInfo doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr);
  89. SpirvEvalInfo doDeclRefExpr(const DeclRefExpr *expr);
  90. SpirvEvalInfo doExtMatrixElementExpr(const ExtMatrixElementExpr *expr);
  91. SpirvEvalInfo doHLSLVectorElementExpr(const HLSLVectorElementExpr *expr);
  92. SpirvEvalInfo doInitListExpr(const InitListExpr *expr);
  93. SpirvEvalInfo doMemberExpr(const MemberExpr *expr);
  94. SpirvEvalInfo doUnaryOperator(const UnaryOperator *expr);
  95. /// Overload with pre computed SpirvEvalInfo.
  96. ///
  97. /// The given expr will not be evaluated again.
  98. SpirvEvalInfo loadIfGLValue(const Expr *expr, SpirvEvalInfo info);
  99. /// Loads the pointer of the aliased-to-variable if the given expression is a
  100. /// DeclRefExpr referencing an alias variable. See DeclResultIdMapper for
  101. /// more explanation regarding this.
  102. ///
  103. /// Note: legalization specific code
  104. SpirvEvalInfo loadIfAliasVarRef(const Expr *expr);
  105. /// Loads the pointer of the aliased-to-variable and ajusts aliasVarInfo
  106. /// accordingly if aliasVarExpr is referencing an alias variable. Returns true
  107. /// if aliasVarInfo is changed, false otherwise.
  108. ///
  109. /// Note: legalization specific code
  110. bool loadIfAliasVarRef(const Expr *aliasVarExpr, SpirvEvalInfo &aliasVarInfo);
  111. private:
  112. /// Translates the given frontend binary operator into its SPIR-V equivalent
  113. /// taking consideration of the operand type.
  114. spv::Op translateOp(BinaryOperator::Opcode op, QualType type);
  115. spv::Op translateWaveOp(hlsl::IntrinsicOp op, QualType type, SourceLocation);
  116. /// Generates SPIR-V instructions for the given normal (non-intrinsic and
  117. /// non-operator) standalone or member function call.
  118. SpirvEvalInfo processCall(const CallExpr *expr);
  119. /// Generates the necessary instructions for assigning rhs to lhs. If lhsPtr
  120. /// is not zero, it will be used as the pointer from lhs instead of evaluating
  121. /// lhs again.
  122. SpirvEvalInfo processAssignment(const Expr *lhs, const SpirvEvalInfo &rhs,
  123. bool isCompoundAssignment,
  124. SpirvEvalInfo lhsPtr = 0);
  125. /// Generates SPIR-V instructions to store rhsVal into lhsPtr. This will be
  126. /// recursive if lhsValType is a composite type. rhsExpr will be used as a
  127. /// reference to adjust the CodeGen if not nullptr.
  128. void storeValue(const SpirvEvalInfo &lhsPtr, const SpirvEvalInfo &rhsVal,
  129. QualType lhsValType);
  130. /// Decomposes and reconstructs the given srcVal of the given valType to meet
  131. /// the requirements of the dstLR layout rule.
  132. uint32_t reconstructValue(const SpirvEvalInfo &srcVal, QualType valType,
  133. LayoutRule dstLR);
  134. /// Generates the necessary instructions for conducting the given binary
  135. /// operation on lhs and rhs.
  136. ///
  137. /// computationType is the type for LHS and RHS when doing computation, while
  138. /// resultType is the type of the whole binary operation. They can be
  139. /// different for compound assignments like <some-int-value> *=
  140. /// <some-float-value>, where computationType is float and resultType is int.
  141. ///
  142. /// If lhsResultId is not nullptr, the evaluated pointer from lhs during the
  143. /// process will be written into it. If mandateGenOpcode is not spv::Op::Max,
  144. /// it will used as the SPIR-V opcode instead of deducing from Clang frontend
  145. /// opcode.
  146. SpirvEvalInfo processBinaryOp(const Expr *lhs, const Expr *rhs,
  147. BinaryOperatorKind opcode,
  148. QualType computationType, QualType resultType,
  149. SourceRange, SpirvEvalInfo *lhsInfo = nullptr,
  150. spv::Op mandateGenOpcode = spv::Op::Max);
  151. /// Generates SPIR-V instructions to initialize the given variable once.
  152. void initOnce(QualType varType, std::string varName, uint32_t varPtr,
  153. const Expr *varInit);
  154. /// Returns true if the given expression will be translated into a vector
  155. /// shuffle instruction in SPIR-V.
  156. ///
  157. /// We emit a vector shuffle instruction iff
  158. /// * We are not selecting only one element from the vector (OpAccessChain
  159. /// or OpCompositeExtract for such case);
  160. /// * We are not selecting all elements in their original order (essentially
  161. /// the original vector, no shuffling needed).
  162. bool isVectorShuffle(const Expr *expr);
  163. /// \brief Returns true if the given CXXOperatorCallExpr is indexing into a
  164. /// Buffer/RWBuffer/Texture/RWTexture using operator[].
  165. /// On success, writes the base buffer into *base if base is not nullptr, and
  166. /// writes the index into *index if index is not nullptr.
  167. bool isBufferTextureIndexing(const CXXOperatorCallExpr *,
  168. const Expr **base = nullptr,
  169. const Expr **index = nullptr);
  170. /// \brief Returns true if the given CXXOperatorCallExpr is the .mips[][]
  171. /// access into a Texture or .sample[][] access into Texture2DMS(Array). On
  172. /// success, writes base texture object into *base if base is not nullptr,
  173. /// writes the index into *index if index is not nullptr, and writes the mip
  174. /// level (lod) to *lod if lod is not nullptr.
  175. bool isTextureMipsSampleIndexing(const CXXOperatorCallExpr *indexExpr,
  176. const Expr **base = nullptr,
  177. const Expr **index = nullptr,
  178. const Expr **lod = nullptr);
  179. /// Condenses a sequence of HLSLVectorElementExpr starting from the given
  180. /// expr into one. Writes the original base into *basePtr and the condensed
  181. /// accessor into *flattenedAccessor.
  182. void condenseVectorElementExpr(
  183. const HLSLVectorElementExpr *expr, const Expr **basePtr,
  184. hlsl::VectorMemberAccessPositions *flattenedAccessor);
  185. /// Generates necessary SPIR-V instructions to create a vector splat out of
  186. /// the given scalarExpr. The generated vector will have the same element
  187. /// type as scalarExpr and of the given size. If resultIsConstant is not
  188. /// nullptr, writes true to it if the generated instruction is a constant.
  189. SpirvEvalInfo createVectorSplat(const Expr *scalarExpr, uint32_t size);
  190. /// Splits the given vector into the last element and the rest (as a new
  191. /// vector).
  192. void splitVecLastElement(QualType vecType, uint32_t vec, uint32_t *residual,
  193. uint32_t *lastElement);
  194. /// Translates a floatN * float multiplication into SPIR-V instructions and
  195. /// returns the <result-id>. Returns 0 if the given binary operation is not
  196. /// floatN * float.
  197. SpirvEvalInfo tryToGenFloatVectorScale(const BinaryOperator *expr);
  198. /// Translates a floatMxN * float multiplication into SPIR-V instructions and
  199. /// returns the <result-id>. Returns 0 if the given binary operation is not
  200. /// floatMxN * float.
  201. SpirvEvalInfo tryToGenFloatMatrixScale(const BinaryOperator *expr);
  202. /// Tries to emit instructions for assigning to the given vector element
  203. /// accessing expression. Returns 0 if the trial fails and no instructions
  204. /// are generated.
  205. SpirvEvalInfo tryToAssignToVectorElements(const Expr *lhs,
  206. const SpirvEvalInfo &rhs);
  207. /// Tries to emit instructions for assigning to the given matrix element
  208. /// accessing expression. Returns 0 if the trial fails and no instructions
  209. /// are generated.
  210. SpirvEvalInfo tryToAssignToMatrixElements(const Expr *lhs,
  211. const SpirvEvalInfo &rhs);
  212. /// Tries to emit instructions for assigning to the given RWBuffer/RWTexture
  213. /// object. Returns 0 if the trial fails and no instructions are generated.
  214. SpirvEvalInfo tryToAssignToRWBufferRWTexture(const Expr *lhs,
  215. const SpirvEvalInfo &rhs);
  216. /// Processes each vector within the given matrix by calling actOnEachVector.
  217. /// matrixVal should be the loaded value of the matrix. actOnEachVector takes
  218. /// three parameters for the current vector: the index, the <type-id>, and
  219. /// the value. It returns the <result-id> of the processed vector.
  220. SpirvEvalInfo processEachVectorInMatrix(
  221. const Expr *matrix, const uint32_t matrixVal,
  222. llvm::function_ref<uint32_t(uint32_t, uint32_t, uint32_t)>
  223. actOnEachVector);
  224. /// Translates the given varDecl into a spec constant.
  225. void createSpecConstant(const VarDecl *varDecl);
  226. /// Generates the necessary instructions for conducting the given binary
  227. /// operation on lhs and rhs.
  228. ///
  229. /// This method expects that both lhs and rhs are SPIR-V acceptable matrices.
  230. SpirvEvalInfo processMatrixBinaryOp(const Expr *lhs, const Expr *rhs,
  231. const BinaryOperatorKind opcode,
  232. SourceRange);
  233. /// Creates a temporary local variable in the current function of the given
  234. /// varType and varName. Initializes the variable with the given initValue.
  235. /// Returns the <result-id> of the variable.
  236. uint32_t SPIRVEmitter::createTemporaryVar(QualType varType,
  237. llvm::StringRef varName,
  238. const SpirvEvalInfo &initValue);
  239. /// Collects all indices (SPIR-V constant values) from consecutive MemberExprs
  240. /// or ArraySubscriptExprs or operator[] calls and writes into indices.
  241. /// Returns the real base. If rawIndex is set to true, the indices collected
  242. /// will not be turned into SPIR-V constant values, and the base returned can
  243. /// be nullptr, which means some indices are not constant.
  244. const Expr *
  245. collectArrayStructIndices(const Expr *expr,
  246. llvm::SmallVectorImpl<uint32_t> *indices,
  247. bool rawIndex = false);
  248. /// Creates an access chain to index into the given SPIR-V evaluation result
  249. /// and overwrites and returns the new SPIR-V evaluation result.
  250. SpirvEvalInfo &
  251. turnIntoElementPtr(SpirvEvalInfo &info, QualType elemType,
  252. const llvm::SmallVector<uint32_t, 4> &indices);
  253. private:
  254. /// Validates that vk::* attributes are used correctly and returns false if
  255. /// errors are found.
  256. bool validateVKAttributes(const NamedDecl *decl);
  257. private:
  258. /// Converts the given value from the bitwidth of 'fromType' to the bitwidth
  259. /// of 'toType'. If the two have the same bitwidth, returns the value itself.
  260. /// If resultType is not nullptr, the resulting value's type will be written
  261. /// to resultType. Panics if the given types are not scalar or vector of
  262. /// float/integer type.
  263. uint32_t convertBitwidth(uint32_t value, QualType fromType, QualType toType,
  264. uint32_t *resultType = nullptr);
  265. /// Processes the given expr, casts the result into the given bool (vector)
  266. /// type and returns the <result-id> of the casted value.
  267. uint32_t castToBool(uint32_t value, QualType fromType, QualType toType);
  268. /// Processes the given expr, casts the result into the given integer (vector)
  269. /// type and returns the <result-id> of the casted value.
  270. uint32_t castToInt(uint32_t value, QualType fromType, QualType toType,
  271. SourceLocation);
  272. /// Processes the given expr, casts the result into the given float (vector)
  273. /// type and returns the <result-id> of the casted value.
  274. uint32_t castToFloat(uint32_t value, QualType fromType, QualType toType,
  275. SourceLocation);
  276. private:
  277. /// Processes HLSL instrinsic functions.
  278. SpirvEvalInfo processIntrinsicCallExpr(const CallExpr *);
  279. /// Processes the 'clip' intrinsic function. Discards the current pixel if the
  280. /// specified value is less than zero.
  281. uint32_t processIntrinsicClip(const CallExpr *);
  282. /// Processes the 'dst' intrinsic function.
  283. uint32_t processIntrinsicDst(const CallExpr *);
  284. /// Processes the 'clamp' intrinsic function.
  285. uint32_t processIntrinsicClamp(const CallExpr *);
  286. /// Processes the 'frexp' intrinsic function.
  287. uint32_t processIntrinsicFrexp(const CallExpr *);
  288. /// Processes the 'ldexp' intrinsic function.
  289. uint32_t processIntrinsicLdexp(const CallExpr *);
  290. /// Processes the 'D3DCOLORtoUBYTE4' intrinsic function.
  291. uint32_t processD3DCOLORtoUBYTE4(const CallExpr *);
  292. /// Processes the 'lit' intrinsic function.
  293. uint32_t processIntrinsicLit(const CallExpr *);
  294. /// Processes the 'GroupMemoryBarrier', 'GroupMemoryBarrierWithGroupSync',
  295. /// 'DeviceMemoryBarrier', 'DeviceMemoryBarrierWithGroupSync',
  296. /// 'AllMemoryBarrier', and 'AllMemoryBarrierWithGroupSync' intrinsic
  297. /// functions.
  298. uint32_t processIntrinsicMemoryBarrier(const CallExpr *, bool isDevice,
  299. bool groupSync, bool isAllBarrier);
  300. /// Processes the 'modf' intrinsic function.
  301. uint32_t processIntrinsicModf(const CallExpr *);
  302. /// Processes the 'msad4' intrinsic function.
  303. uint32_t processIntrinsicMsad4(const CallExpr *);
  304. /// Processes the 'mul' intrinsic function.
  305. uint32_t processIntrinsicMul(const CallExpr *);
  306. /// Transposes a non-floating point matrix and returns the result-id of the
  307. /// transpose.
  308. uint32_t processNonFpMatrixTranspose(QualType matType, uint32_t matId);
  309. /// Processes the dot product of two non-floating point vectors. The SPIR-V
  310. /// OpDot only accepts float vectors. Assumes that the two vectors are of the
  311. /// same size and have the same element type (elemType).
  312. uint32_t processNonFpDot(uint32_t vec1Id, uint32_t vec2Id, uint32_t vecSize,
  313. QualType elemType);
  314. /// Processes the multiplication of a *non-floating point* matrix by a scalar.
  315. /// Assumes that the matrix element type and the scalar type are the same.
  316. uint32_t processNonFpScalarTimesMatrix(QualType scalarType, uint32_t scalarId,
  317. QualType matType, uint32_t matId);
  318. /// Processes the multiplication of a *non-floating point* matrix by a vector.
  319. /// Assumes the matrix element type and the vector element type are the same.
  320. /// Notice that the vector in this case is a "row vector" and will be
  321. /// multiplied by the matrix columns (dot product). As a result, the given
  322. /// matrix must be transposed in order to easily get each column. If
  323. /// 'matTransposeId' is non-zero, it will be used as the transpose matrix
  324. /// result-id; otherwise the function will perform the transpose itself.
  325. uint32_t processNonFpVectorTimesMatrix(QualType vecType, uint32_t vecId,
  326. QualType matType, uint32_t matId,
  327. uint32_t matTransposeId = 0);
  328. /// Processes the multiplication of a vector by a *non-floating point* matrix.
  329. /// Assumes the matrix element type and the vector element type are the same.
  330. uint32_t processNonFpMatrixTimesVector(QualType matType, uint32_t matId,
  331. QualType vecType, uint32_t vecId);
  332. /// Processes a non-floating point matrix multiplication. Assumes that the
  333. /// number of columns in lhs matrix is the same as number of rows in the rhs
  334. /// matrix. Also assumes that the two matrices have the same element type.
  335. uint32_t processNonFpMatrixTimesMatrix(QualType lhsType, uint32_t lhsId,
  336. QualType rhsType, uint32_t rhsId);
  337. /// Processes the 'dot' intrinsic function.
  338. uint32_t processIntrinsicDot(const CallExpr *);
  339. /// Processes the 'log10' intrinsic function.
  340. uint32_t processIntrinsicLog10(const CallExpr *);
  341. /// Processes the 'all' and 'any' intrinsic functions.
  342. uint32_t processIntrinsicAllOrAny(const CallExpr *, spv::Op);
  343. /// Processes the 'asfloat', 'asint', and 'asuint' intrinsic functions.
  344. uint32_t processIntrinsicAsType(const CallExpr *);
  345. /// Processes the 'saturate' intrinsic function.
  346. uint32_t processIntrinsicSaturate(const CallExpr *);
  347. /// Processes the 'sincos' intrinsic function.
  348. uint32_t processIntrinsicSinCos(const CallExpr *);
  349. /// Processes the 'isFinite' intrinsic function.
  350. uint32_t processIntrinsicIsFinite(const CallExpr *);
  351. /// Processes the 'rcp' intrinsic function.
  352. uint32_t processIntrinsicRcp(const CallExpr *);
  353. /// Processes the 'sign' intrinsic function for float types.
  354. /// The FSign instruction in the GLSL instruction set returns a floating point
  355. /// result. The HLSL sign function, however, returns an integer. An extra
  356. /// casting from float to integer is therefore performed by this method.
  357. uint32_t processIntrinsicFloatSign(const CallExpr *);
  358. /// Processes the 'f16to32' intrinsic function.
  359. uint32_t processIntrinsicF16ToF32(const CallExpr *);
  360. /// Processes the 'f32tof16' intrinsic function.
  361. uint32_t processIntrinsicF32ToF16(const CallExpr *);
  362. /// Processes the given intrinsic function call using the given GLSL
  363. /// extended instruction. If the given instruction cannot operate on matrices,
  364. /// it performs the instruction on each row of the matrix and uses composite
  365. /// construction to generate the resulting matrix.
  366. uint32_t processIntrinsicUsingGLSLInst(const CallExpr *, GLSLstd450 instr,
  367. bool canOperateOnMatrix);
  368. /// Processes the given intrinsic function call using the given SPIR-V
  369. /// instruction. If the given instruction cannot operate on matrices, it
  370. /// performs the instruction on each row of the matrix and uses composite
  371. /// construction to generate the resulting matrix.
  372. uint32_t processIntrinsicUsingSpirvInst(const CallExpr *, spv::Op,
  373. bool canOperateOnMatrix);
  374. /// Processes the given intrinsic member call.
  375. SpirvEvalInfo processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
  376. hlsl::IntrinsicOp opcode);
  377. /// Processes Interlocked* intrinsic functions.
  378. uint32_t processIntrinsicInterlockedMethod(const CallExpr *,
  379. hlsl::IntrinsicOp);
  380. /// Processes SM6.0 wave query intrinsic calls.
  381. uint32_t processWaveQuery(const CallExpr *, spv::Op opcode);
  382. /// Processes SM6.0 wave vote intrinsic calls.
  383. uint32_t processWaveVote(const CallExpr *, spv::Op opcode);
  384. /// Processes SM6.0 wave reduction or scan/prefix intrinsic calls.
  385. uint32_t processWaveReductionOrPrefix(const CallExpr *, spv::Op op,
  386. spv::GroupOperation groupOp);
  387. /// Processes SM6.0 wave broadcast intrinsic calls.
  388. uint32_t processWaveBroadcast(const CallExpr *);
  389. /// Processes SM6.0 quad-wide shuffle.
  390. uint32_t processWaveQuadWideShuffle(const CallExpr *, hlsl::IntrinsicOp op);
  391. private:
  392. /// Returns the <result-id> for constant value 0 of the given type.
  393. uint32_t getValueZero(QualType type);
  394. /// Returns the <result-id> for a constant zero vector of the given size and
  395. /// element type.
  396. uint32_t getVecValueZero(QualType elemType, uint32_t size);
  397. /// Returns the <result-id> for constant value 1 of the given type.
  398. uint32_t getValueOne(QualType type);
  399. /// Returns the <result-id> for a constant one vector of the given size and
  400. /// element type.
  401. uint32_t getVecValueOne(QualType elemType, uint32_t size);
  402. /// Returns the <result-id> for a constant one (vector) having the same
  403. /// element type as the given matrix type.
  404. ///
  405. /// If a 1x1 matrix is given, the returned value one will be a scalar;
  406. /// if a Mx1 or 1xN matrix is given, the returned value one will be a
  407. /// vector of size M or N; if a MxN matrix is given, the returned value
  408. /// one will be a vector of size N.
  409. uint32_t getMatElemValueOne(QualType type);
  410. /// Returns a SPIR-V constant equal to the bitwdith of the given type minus
  411. /// one. The returned constant has the same component count and bitwidth as
  412. /// the given type.
  413. uint32_t getMaskForBitwidthValue(QualType type);
  414. private:
  415. /// \brief Performs a FlatConversion implicit cast. Fills an instance of the
  416. /// given type with initializer <result-id>. The initializer is of type
  417. /// initType.
  418. uint32_t processFlatConversion(const QualType type, const QualType initType,
  419. uint32_t initId, SourceLocation);
  420. private:
  421. /// Translates the given frontend APValue into its SPIR-V equivalent for the
  422. /// given targetType.
  423. uint32_t translateAPValue(const APValue &value, const QualType targetType);
  424. /// Translates the given frontend APInt into its SPIR-V equivalent for the
  425. /// given targetType.
  426. uint32_t translateAPInt(const llvm::APInt &intValue, QualType targetType);
  427. /// Translates the given frontend APFloat into its SPIR-V equivalent for the
  428. /// given targetType.
  429. uint32_t translateAPFloat(llvm::APFloat floatValue, QualType targetType);
  430. /// Tries to evaluate the given Expr as a constant and returns the <result-id>
  431. /// if success. Otherwise, returns 0.
  432. uint32_t tryToEvaluateAsConst(const Expr *expr);
  433. /// Tries to evaluate the given APFloat as a 32-bit float. If the evaluation
  434. /// can be performed without loss, it returns the <result-id> of the SPIR-V
  435. /// constant for that value. Returns zero otherwise.
  436. uint32_t tryToEvaluateAsFloat32(const llvm::APFloat &);
  437. /// Tries to evaluate the given APInt as a 32-bit integer. If the evaluation
  438. /// can be performed without loss, it returns the <result-id> of the SPIR-V
  439. /// constant for that value.
  440. uint32_t tryToEvaluateAsInt32(const llvm::APInt &, bool isSigned);
  441. /// Returns true iff the given expression is a literal integer that cannot be
  442. /// represented in a 32-bit integer type or a literal float that cannot be
  443. /// represented in a 32-bit float type without losing info. Returns false
  444. /// otherwise.
  445. bool isLiteralLargerThan32Bits(const Expr *expr);
  446. private:
  447. /// Translates the given HLSL loop attribute into SPIR-V loop control mask.
  448. /// Emits an error if the given attribute is not a loop attribute.
  449. spv::LoopControlMask translateLoopAttribute(const Stmt *, const Attr &);
  450. static spv::ExecutionModel
  451. getSpirvShaderStage(const hlsl::ShaderModel &model);
  452. void AddRequiredCapabilitiesForShaderModel();
  453. /// \brief Adds necessary execution modes for the hull/domain shaders based on
  454. /// the HLSL attributes of the entry point function.
  455. /// In the case of hull shaders, also writes the number of output control
  456. /// points to *numOutputControlPoints. Returns true on success, and false on
  457. /// failure.
  458. bool processTessellationShaderAttributes(const FunctionDecl *entryFunction,
  459. uint32_t *numOutputControlPoints);
  460. /// \brief Adds necessary execution modes for the geometry shader based on the
  461. /// HLSL attributes of the entry point function. Also writes the array size of
  462. /// the input, which depends on the primitive type, to *arraySize.
  463. bool processGeometryShaderAttributes(const FunctionDecl *entryFunction,
  464. uint32_t *arraySize);
  465. /// \brief Adds necessary execution modes for the pixel shader based on the
  466. /// HLSL attributes of the entry point function.
  467. void processPixelShaderAttributes(const FunctionDecl *decl);
  468. /// \brief Adds necessary execution modes for the compute shader based on the
  469. /// HLSL attributes of the entry point function.
  470. void processComputeShaderAttributes(const FunctionDecl *entryFunction);
  471. /// \brief Emits a wrapper function for the entry function and returns true
  472. /// on success.
  473. ///
  474. /// The wrapper function loads the values of all stage input variables and
  475. /// creates composites as expected by the source code entry function. It then
  476. /// calls the source code entry point and writes out stage output variables
  477. /// by extracting sub-values from the return value. In this way, we can handle
  478. /// the source code entry point as a normal function.
  479. ///
  480. /// The wrapper function is also responsible for initializing global static
  481. /// variables for some cases.
  482. bool emitEntryFunctionWrapper(const FunctionDecl *entryFunction,
  483. uint32_t entryFuncId);
  484. /// \brief Performs the following operations for the Hull shader:
  485. /// * Creates an output variable which is an Array containing results for all
  486. /// control points.
  487. ///
  488. /// * If the Patch Constant Function (PCF) takes the Hull main entry function
  489. /// results (OutputPatch), it creates a temporary function-scope variable that
  490. /// is then passed to the PCF.
  491. ///
  492. /// * Adds a control barrier (OpControlBarrier) to ensure all invocations are
  493. /// done before PCF is called.
  494. ///
  495. /// * Prepares the necessary parameters to pass to the PCF (Can be one or more
  496. /// of InputPatch, OutputPatch, PrimitiveId).
  497. ///
  498. /// * The execution thread with ControlPointId (invocationID) of 0 calls the
  499. /// PCF. e.g. if(id == 0) pcf();
  500. ///
  501. /// * Gathers the results of the PCF and assigns them to stage output
  502. /// variables.
  503. ///
  504. /// The method panics if it is called for any shader kind other than Hull
  505. /// shaders.
  506. bool processHSEntryPointOutputAndPCF(const FunctionDecl *hullMainFuncDecl,
  507. uint32_t retType, uint32_t retVal,
  508. uint32_t numOutputControlPoints,
  509. uint32_t outputControlPointId,
  510. uint32_t primitiveId, uint32_t viewId,
  511. uint32_t hullMainInputPatch);
  512. private:
  513. /// \brief Returns true iff *all* the case values in the given switch
  514. /// statement are integer literals. In such cases OpSwitch can be used to
  515. /// represent the switch statement.
  516. /// We only care about the case values to be compared with the selector. They
  517. /// may appear in the top level CaseStmt or be nested in a CompoundStmt.Fall
  518. /// through cases will result in the second situation.
  519. bool allSwitchCasesAreIntegerLiterals(const Stmt *root);
  520. /// \brief Recursively discovers all CaseStmt and DefaultStmt under the
  521. /// sub-tree of the given root. Recursively goes down the tree iff it finds a
  522. /// CaseStmt, DefaultStmt, or CompoundStmt. It does not recurse on other
  523. /// statement types. For each discovered case, a basic block is created and
  524. /// registered within the module, and added as a successor to the current
  525. /// active basic block.
  526. ///
  527. /// Writes a vector of (integer, basic block label) pairs for all cases to the
  528. /// given 'targets' argument. If a DefaultStmt is found, it also returns the
  529. /// label for the default basic block through the defaultBB parameter. This
  530. /// method panics if it finds a case value that is not an integer literal.
  531. void discoverAllCaseStmtInSwitchStmt(
  532. const Stmt *root, uint32_t *defaultBB,
  533. std::vector<std::pair<uint32_t, uint32_t>> *targets);
  534. /// Flattens structured AST of the given switch statement into a vector of AST
  535. /// nodes and stores into flatSwitch.
  536. ///
  537. /// The AST for a switch statement may look arbitrarily different based on
  538. /// several factors such as placement of cases, placement of breaks, placement
  539. /// of braces, and fallthrough cases.
  540. ///
  541. /// A CaseStmt for instance is the child node of a CompoundStmt for
  542. /// regular cases and it is the child node of another CaseStmt for fallthrough
  543. /// cases.
  544. ///
  545. /// A BreakStmt for instance could be the child node of a CompoundStmt
  546. /// for regular cases, or the child node of a CaseStmt for some fallthrough
  547. /// cases.
  548. ///
  549. /// This method flattens the AST representation of a switch statement to make
  550. /// it easier to process for translation.
  551. /// For example:
  552. ///
  553. /// switch(a) {
  554. /// case 1:
  555. /// <Stmt1>
  556. /// case 2:
  557. /// <Stmt2>
  558. /// break;
  559. /// case 3:
  560. /// case 4:
  561. /// <Stmt4>
  562. /// break;
  563. /// deafult:
  564. /// <Stmt5>
  565. /// }
  566. ///
  567. /// is flattened to the following vector:
  568. ///
  569. /// +-----+-----+-----+-----+-----+-----+-----+-----+-----+-------+-----+
  570. /// |Case1|Stmt1|Case2|Stmt2|Break|Case3|Case4|Stmt4|Break|Default|Stmt5|
  571. /// +-----+-----+-----+-----+-----+-----+-----+-----+-----+-------+-----+
  572. ///
  573. void flattenSwitchStmtAST(const Stmt *root,
  574. std::vector<const Stmt *> *flatSwitch);
  575. void processCaseStmtOrDefaultStmt(const Stmt *stmt);
  576. void processSwitchStmtUsingSpirvOpSwitch(const SwitchStmt *switchStmt);
  577. /// Translates a switch statement into SPIR-V conditional branches.
  578. ///
  579. /// This is done by constructing AST if statements out of the cases using the
  580. /// following pattern:
  581. /// if { ... } else if { ... } else if { ... } else { ... }
  582. /// And then calling the SPIR-V codegen methods for these if statements.
  583. ///
  584. /// Each case comparison is turned into an if statement, and the "then" body
  585. /// of the if statement will be the body of the case.
  586. /// If a default statements exists, it becomes the body of the "else"
  587. /// statement.
  588. void processSwitchStmtUsingIfStmts(const SwitchStmt *switchStmt);
  589. private:
  590. /// Handles the offset argument in the given method call at the given argument
  591. /// index. Panics if the argument at the given index does not exist. Writes
  592. /// the <result-id> to either *constOffset or *varOffset, depending on the
  593. /// constantness of the offset.
  594. void handleOffsetInMethodCall(const CXXMemberCallExpr *expr, uint32_t index,
  595. uint32_t *constOffset, uint32_t *varOffset);
  596. /// \brief Processes .Load() method call for Buffer/RWBuffer and texture
  597. /// objects.
  598. SpirvEvalInfo processBufferTextureLoad(const CXXMemberCallExpr *);
  599. /// \brief Loads one element from the given Buffer/RWBuffer/Texture object at
  600. /// the given location. The type of the loaded element matches the type in the
  601. /// declaration for the Buffer/Texture object.
  602. /// If residencyCodeId is not zero, the SPIR-V instruction for storing the
  603. /// resulting residency code will also be emitted.
  604. SpirvEvalInfo processBufferTextureLoad(const Expr *object, uint32_t location,
  605. uint32_t constOffset,
  606. uint32_t varOffset, uint32_t lod,
  607. uint32_t residencyCode);
  608. /// \brief Processes .Sample() and .Gather() method calls for texture objects.
  609. uint32_t processTextureSampleGather(const CXXMemberCallExpr *expr,
  610. bool isSample);
  611. /// \brief Processes .SampleBias() and .SampleLevel() method calls for texture
  612. /// objects.
  613. uint32_t processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
  614. bool isBias);
  615. /// \brief Processes .SampleGrad() method call for texture objects.
  616. uint32_t processTextureSampleGrad(const CXXMemberCallExpr *expr);
  617. /// \brief Processes .SampleCmp() or .SampleCmpLevelZero() method call for
  618. /// texture objects.
  619. uint32_t processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
  620. bool isCmp);
  621. /// \brief Handles .Gather{|Cmp}{Red|Green|Blue|Alpha}() calls on texture
  622. /// types.
  623. uint32_t processTextureGatherRGBACmpRGBA(const CXXMemberCallExpr *expr,
  624. bool isCmp, uint32_t component);
  625. /// \brief Handles .GatherCmp() calls on texture types.
  626. uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);
  627. /// \brief Returns the calculated level-of-detail (a single float value) for
  628. /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
  629. uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr);
  630. /// \brief Processes the .GetDimensions() call on supported objects.
  631. uint32_t processGetDimensions(const CXXMemberCallExpr *);
  632. /// \brief Queries the given (RW)Buffer/(RW)Texture image in the given expr
  633. /// for the requested information. Based on the dimension of the image, the
  634. /// following info can be queried: width, height, depth, number of mipmap
  635. /// levels.
  636. uint32_t processBufferTextureGetDimensions(const CXXMemberCallExpr *);
  637. /// \brief Generates an OpAccessChain instruction for the given
  638. /// (RW)StructuredBuffer.Load() method call.
  639. SpirvEvalInfo processStructuredBufferLoad(const CXXMemberCallExpr *expr);
  640. /// \brief Increments or decrements the counter for RW/Append/Consume
  641. /// structured buffer. If loadObject is true, the object upon which the call
  642. /// is made will be evaluated and translated into SPIR-V.
  643. uint32_t incDecRWACSBufferCounter(const CXXMemberCallExpr *call, bool isInc,
  644. bool loadObject = true);
  645. /// Assigns the counter variable associated with srcExpr to the one associated
  646. /// with dstDecl if the dstDecl is an internal RW/Append/Consume structured
  647. /// buffer. Returns false if there is no associated counter variable for
  648. /// srcExpr or dstDecl.
  649. ///
  650. /// Note: legalization specific code
  651. bool tryToAssignCounterVar(const DeclaratorDecl *dstDecl,
  652. const Expr *srcExpr);
  653. bool tryToAssignCounterVar(const Expr *dstExpr, const Expr *srcExpr);
  654. /// Returns the counter variable's information associated with the entity
  655. /// represented by the given decl.
  656. ///
  657. /// This method only handles final alias structured buffers, which means
  658. /// AssocCounter#1 and AssocCounter#2.
  659. const CounterIdAliasPair *getFinalACSBufferCounter(const Expr *expr);
  660. /// This method handles AssocCounter#3 and AssocCounter#4.
  661. const CounterVarFields *
  662. getIntermediateACSBufferCounter(const Expr *expr,
  663. llvm::SmallVector<uint32_t, 4> *indices);
  664. /// Gets or creates an ImplicitParamDecl to represent the implicit object
  665. /// parameter of the given method.
  666. const ImplicitParamDecl *
  667. getOrCreateDeclForMethodObject(const CXXMethodDecl *method);
  668. /// \brief Loads numWords 32-bit unsigned integers or stores numWords 32-bit
  669. /// unsigned integers (based on the doStore parameter) to the given
  670. /// ByteAddressBuffer. Loading is allowed from a ByteAddressBuffer or
  671. /// RWByteAddressBuffer. Storing is allowed only to RWByteAddressBuffer.
  672. /// Panics if it is not the case.
  673. SpirvEvalInfo processByteAddressBufferLoadStore(const CXXMemberCallExpr *,
  674. uint32_t numWords,
  675. bool doStore);
  676. /// \brief Processes the GetDimensions intrinsic function call on a
  677. /// (RW)ByteAddressBuffer by querying the image in the given expr.
  678. uint32_t processByteAddressBufferStructuredBufferGetDimensions(
  679. const CXXMemberCallExpr *);
  680. /// \brief Processes the Interlocked* intrinsic function call on a
  681. /// RWByteAddressBuffer.
  682. uint32_t processRWByteAddressBufferAtomicMethods(hlsl::IntrinsicOp opcode,
  683. const CXXMemberCallExpr *);
  684. /// \brief Processes the GetSamplePosition intrinsic method call on a
  685. /// Texture2DMS(Array).
  686. uint32_t processGetSamplePosition(const CXXMemberCallExpr *);
  687. /// \brief Processes the SubpassLoad intrinsic function call on a
  688. /// SubpassInput(MS).
  689. SpirvEvalInfo processSubpassLoad(const CXXMemberCallExpr *);
  690. /// \brief Generates SPIR-V instructions for the .Append()/.Consume() call on
  691. /// the given {Append|Consume}StructuredBuffer. Returns the <result-id> of
  692. /// the loaded value for .Consume; returns zero for .Append().
  693. SpirvEvalInfo processACSBufferAppendConsume(const CXXMemberCallExpr *expr);
  694. /// \brief Generates SPIR-V instructions to emit the current vertex in GS.
  695. uint32_t processStreamOutputAppend(const CXXMemberCallExpr *expr);
  696. /// \brief Generates SPIR-V instructions to end emitting the current
  697. /// primitive in GS.
  698. uint32_t processStreamOutputRestart(const CXXMemberCallExpr *expr);
  699. /// \brief Emulates GetSamplePosition() for standard sample settings, i.e.,
  700. /// with 1, 2, 4, 8, or 16 samples. Returns float2(0) for other cases.
  701. uint32_t emitGetSamplePosition(uint32_t sampleCount, uint32_t sampleIndex);
  702. private:
  703. /// \brief Takes a vector of size 4, and returns a vector of size 1 or 2 or 3
  704. /// or 4. Creates a CompositeExtract or VectorShuffle instruction to extract
  705. /// a scalar or smaller vector from the beginning of the input vector if
  706. /// necessary. Assumes that 'fromId' is the <result-id> of a vector of size 4.
  707. /// Panics if the target vector size is not 1, 2, 3, or 4.
  708. uint32_t extractVecFromVec4(uint32_t fromId, uint32_t targetVecSize,
  709. uint32_t targetElemTypeId);
  710. /// \brief Creates SPIR-V instructions for sampling the given image.
  711. /// It utilizes the ModuleBuilder's createImageSample and it ensures that the
  712. /// returned type is handled correctly.
  713. /// HLSL image sampling methods may return a scalar, vec1, vec2, vec3, or
  714. /// vec4. But non-Dref image sampling instructions in SPIR-V must always
  715. /// return a vec4. As a result, an extra processing step is necessary.
  716. uint32_t createImageSample(QualType retType, uint32_t imageType,
  717. uint32_t image, uint32_t sampler,
  718. uint32_t coordinate, uint32_t compareVal,
  719. uint32_t bias, uint32_t lod,
  720. std::pair<uint32_t, uint32_t> grad,
  721. uint32_t constOffset, uint32_t varOffset,
  722. uint32_t constOffsets, uint32_t sample,
  723. uint32_t minLod, uint32_t residencyCodeId);
  724. private:
  725. /// \brief Wrapper method to create a fatal error message and report it
  726. /// in the diagnostic engine associated with this consumer.
  727. template <unsigned N>
  728. DiagnosticBuilder emitFatalError(const char (&message)[N],
  729. SourceLocation loc) {
  730. const auto diagId =
  731. diags.getCustomDiagID(clang::DiagnosticsEngine::Fatal, message);
  732. return diags.Report(loc, diagId);
  733. }
  734. /// \brief Wrapper method to create an error message and report it
  735. /// in the diagnostic engine associated with this consumer.
  736. template <unsigned N>
  737. DiagnosticBuilder emitError(const char (&message)[N], SourceLocation loc) {
  738. const auto diagId =
  739. diags.getCustomDiagID(clang::DiagnosticsEngine::Error, message);
  740. return diags.Report(loc, diagId);
  741. }
  742. /// \brief Wrapper method to create a warning message and report it
  743. /// in the diagnostic engine associated with this consumer
  744. template <unsigned N>
  745. DiagnosticBuilder emitWarning(const char (&message)[N], SourceLocation loc) {
  746. const auto diagId =
  747. diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, message);
  748. return diags.Report(loc, diagId);
  749. }
  750. /// \brief Wrapper method to create a note message and report it
  751. /// in the diagnostic engine associated with this consumer
  752. template <unsigned N>
  753. DiagnosticBuilder emitNote(const char (&message)[N], SourceLocation loc) {
  754. const auto diagId =
  755. diags.getCustomDiagID(clang::DiagnosticsEngine::Note, message);
  756. return diags.Report(loc, diagId);
  757. }
  758. private:
  759. CompilerInstance &theCompilerInstance;
  760. ASTContext &astContext;
  761. DiagnosticsEngine &diags;
  762. const EmitSPIRVOptions &spirvOptions;
  763. /// Entry function name and shader stage. Both of them are derived from the
  764. /// command line and should be const.
  765. const llvm::StringRef entryFunctionName;
  766. const hlsl::ShaderModel &shaderModel;
  767. SPIRVContext theContext;
  768. FeatureManager featureManager;
  769. ModuleBuilder theBuilder;
  770. TypeTranslator typeTranslator;
  771. DeclResultIdMapper declIdMapper;
  772. /// A queue of decls reachable from the entry function. Decls inserted into
  773. /// this queue will persist to avoid duplicated translations. And we'd like
  774. /// a deterministic order of iterating the queue for finding the next decl
  775. /// to translate. So we need SetVector here.
  776. llvm::SetVector<const DeclaratorDecl *> workQueue;
  777. /// <result-id> for the entry function. Initially it is zero and will be reset
  778. /// when starting to translate the entry function.
  779. uint32_t entryFunctionId;
  780. /// The current function under traversal.
  781. const FunctionDecl *curFunction;
  782. /// The SPIR-V function parameter for the current this object.
  783. uint32_t curThis;
  784. /// The source location of a push constant block we have previously seen.
  785. /// Invalid means no push constant blocks defined thus far.
  786. SourceLocation seenPushConstantAt;
  787. /// Indicates whether the current emitter is in specialization constant mode:
  788. /// all 32-bit scalar constants will be translated into OpSpecConstant.
  789. bool isSpecConstantMode;
  790. /// Whether the translated SPIR-V binary needs legalization.
  791. ///
  792. /// The following cases will require legalization:
  793. ///
  794. /// 1. Opaque types (textures, samplers) within structs
  795. /// 2. Structured buffer aliasing
  796. /// 3. Using SPIR-V instructions not allowed in the currect shader stage
  797. ///
  798. /// This covers the first and third case.
  799. ///
  800. /// If this is true, SPIRV-Tools legalization passes will be executed after
  801. /// the translation to legalize the generated SPIR-V binary.
  802. ///
  803. /// Note: legalization specific code
  804. bool needsLegalization;
  805. /// Mapping from methods to the decls to represent their implicit object
  806. /// parameters
  807. ///
  808. /// We need this map because that we need to update the associated counters on
  809. /// the implicit object when invoking method calls. The ImplicitParamDecl
  810. /// mapped to serves as a key to find the associated counters in
  811. /// DeclResultIdMapper.
  812. ///
  813. /// Note: legalization specific code
  814. llvm::DenseMap<const CXXMethodDecl *, const ImplicitParamDecl *> thisDecls;
  815. /// Global variables that should be initialized once at the begining of the
  816. /// entry function.
  817. llvm::SmallVector<const VarDecl *, 4> toInitGloalVars;
  818. /// For loops, while loops, and switch statements may encounter "break"
  819. /// statements that alter their control flow. At any point the break statement
  820. /// is observed, the control flow jumps to the inner-most scope's merge block.
  821. /// For instance: the break in the following example should cause a branch to
  822. /// the SwitchMergeBB, not ForLoopMergeBB:
  823. /// for (...) {
  824. /// switch(...) {
  825. /// case 1: break;
  826. /// }
  827. /// <--- SwitchMergeBB
  828. /// }
  829. /// <---- ForLoopMergeBB
  830. /// This stack keeps track of the basic blocks to which branching could occur.
  831. std::stack<uint32_t> breakStack;
  832. /// Loops (do, while, for) may encounter "continue" statements that alter
  833. /// their control flow. At any point the continue statement is observed, the
  834. /// control flow jumps to the inner-most scope's continue block.
  835. /// This stack keeps track of the basic blocks to which such branching could
  836. /// occur.
  837. std::stack<uint32_t> continueStack;
  838. /// Maps a given statement to the basic block that is associated with it.
  839. llvm::DenseMap<const Stmt *, uint32_t> stmtBasicBlock;
  840. /// This is the Patch Constant Function. This function is not explicitly
  841. /// called from the entry point function.
  842. FunctionDecl *patchConstFunc;
  843. };
  844. void SPIRVEmitter::doDeclStmt(const DeclStmt *declStmt) {
  845. for (auto *decl : declStmt->decls())
  846. doDecl(decl);
  847. }
  848. } // end namespace spirv
  849. } // end namespace clang
  850. #endif