Browse Source

[spirv] Move constant interface to SpirvBuilder.

SpirvBuilder has a handle to the module. It is important that the API
for fetching unique constants is in SpirvBuilder so that it can
appropriately add the constants to the module.
Ehsan Nasiri 6 years ago
parent
commit
821253d482

+ 6 - 6
tools/clang/include/clang/SPIRV/EmitVisitor.h

@@ -40,11 +40,11 @@ struct SpirvLayoutRuleDenseMapInfo {
 
 
 class EmitTypeHandler {
 class EmitTypeHandler {
 public:
 public:
-  EmitTypeHandler(ASTContext &astCtx, SpirvContext &spvCtx,
+  EmitTypeHandler(ASTContext &astCtx, SpirvBuilder &builder,
                   std::vector<uint32_t> *decVec,
                   std::vector<uint32_t> *decVec,
                   std::vector<uint32_t> *typesVec,
                   std::vector<uint32_t> *typesVec,
                   const std::function<uint32_t()> &takeNextIdFn)
                   const std::function<uint32_t()> &takeNextIdFn)
-      : astContext(astCtx), spirvContext(spvCtx), annotationsBinary(decVec),
+      : astContext(astCtx), spirvBuilder(builder), annotationsBinary(decVec),
         typeConstantBinary(typesVec), takeNextIdFunction(takeNextIdFn) {
         typeConstantBinary(typesVec), takeNextIdFunction(takeNextIdFn) {
     assert(decVec);
     assert(decVec);
     assert(typesVec);
     assert(typesVec);
@@ -108,7 +108,7 @@ private:
 
 
 private:
 private:
   ASTContext &astContext;
   ASTContext &astContext;
-  SpirvContext &spirvContext;
+  SpirvBuilder &spirvBuilder;
   std::vector<uint32_t> curTypeInst;
   std::vector<uint32_t> curTypeInst;
   std::vector<uint32_t> curDecorationInst;
   std::vector<uint32_t> curDecorationInst;
   std::vector<uint32_t> *annotationsBinary;
   std::vector<uint32_t> *annotationsBinary;
@@ -143,9 +143,9 @@ public:
 
 
 public:
 public:
   EmitVisitor(ASTContext &astCtx, SpirvContext &spvCtx,
   EmitVisitor(ASTContext &astCtx, SpirvContext &spvCtx,
-              const SpirvCodeGenOptions &opts)
+              const SpirvCodeGenOptions &opts, SpirvBuilder &builder)
       : Visitor(opts, spvCtx), id(0),
       : Visitor(opts, spvCtx), id(0),
-        typeHandler(astCtx, spvCtx, &annotationsBinary, &typeConstantBinary,
+        typeHandler(astCtx, builder, &annotationsBinary, &typeConstantBinary,
                     [this]() -> uint32_t { return takeNextId(); }) {}
                     [this]() -> uint32_t { return takeNextId(); }) {}
 
 
   // Visit different SPIR-V constructs for emitting.
   // Visit different SPIR-V constructs for emitting.
@@ -264,7 +264,7 @@ private:
   // All annotation instructions: OpDecorate, OpMemberDecorate, OpGroupDecorate,
   // All annotation instructions: OpDecorate, OpMemberDecorate, OpGroupDecorate,
   // OpGroupMemberDecorate, and OpDecorationGroup.
   // OpGroupMemberDecorate, and OpDecorationGroup.
   std::vector<uint32_t> annotationsBinary;
   std::vector<uint32_t> annotationsBinary;
-  // All OpLine instructions
+  // All type and constant instructions
   std::vector<uint32_t> typeConstantBinary;
   std::vector<uint32_t> typeConstantBinary;
   // All other instructions
   // All other instructions
   std::vector<uint32_t> mainBinary;
   std::vector<uint32_t> mainBinary;

+ 3 - 91
tools/clang/include/clang/SPIRV/SPIRVContext.h

@@ -159,6 +159,9 @@ struct QualTypeDenseMapInfo {
 /// context is deleted. Therefore, this context should outlive the usages of the
 /// context is deleted. Therefore, this context should outlive the usages of the
 /// the SPIR-V entities allocated in memory.
 /// the SPIR-V entities allocated in memory.
 class SpirvContext {
 class SpirvContext {
+  friend class SpirvBuilder;
+  friend class EmitTypeHandler;
+
 public:
 public:
   SpirvContext();
   SpirvContext();
   ~SpirvContext() = default;
   ~SpirvContext() = default;
@@ -227,85 +230,6 @@ public:
   const StructType *getByteAddressBufferType(bool isWritable);
   const StructType *getByteAddressBufferType(bool isWritable);
   const StructType *getACSBufferCounterType();
   const StructType *getACSBufferCounterType();
 
 
-  SpirvConstant *getConstantUint16(uint16_t value, bool specConst = false);
-  SpirvConstant *getConstantInt16(int16_t value, bool specConst = false);
-  SpirvConstant *getConstantUint32(uint32_t value, bool specConst = false);
-  SpirvConstant *getConstantInt32(int32_t value, bool specConst = false);
-  SpirvConstant *getConstantUint64(uint64_t value, bool specConst = false);
-  SpirvConstant *getConstantInt64(int64_t value, bool specConst = false);
-  SpirvConstant *getConstantFloat16(uint16_t value, bool specConst = false);
-  SpirvConstant *getConstantFloat32(float value, bool specConst = false);
-  SpirvConstant *getConstantFloat64(double value, bool specConst = false);
-  SpirvConstant *getConstantBool(bool value, bool specConst = false);
-  SpirvConstant *
-  getConstantComposite(QualType compositeType,
-                       llvm::ArrayRef<SpirvConstant *> constituents,
-                       bool specConst = false);
-
-  SpirvConstant *getConstantNull(const SpirvType *);
-  SpirvConstant *getConstantNull(QualType);
-
-private:
-  template <class T>
-  SpirvConstant *getConstantInt(T value, bool isSigned, uint32_t bitwidth,
-                                bool specConst) {
-    const IntegerType *intType =
-        isSigned ? getSIntType(bitwidth) : getUIntType(bitwidth);
-    SpirvConstantInteger tempConstant(intType, value, specConst);
-
-    auto found =
-        std::find_if(integerConstants.begin(), integerConstants.end(),
-                     [&tempConstant](SpirvConstantInteger *cachedConstant) {
-                       return tempConstant == *cachedConstant;
-                     });
-
-    if (found != integerConstants.end())
-      return *found;
-
-    // Couldn't find the constant. Create one.
-    auto *intConst = new (this) SpirvConstantInteger(intType, value, specConst);
-    integerConstants.push_back(intConst);
-    return intConst;
-  }
-
-  template <class T>
-  SpirvConstant *getConstantFloat(T value, uint32_t bitwidth, bool specConst) {
-    const FloatType *floatType = getFloatType(bitwidth);
-    SpirvConstantFloat tempConstant(floatType, value, specConst);
-
-    auto found =
-        std::find_if(floatConstants.begin(), floatConstants.end(),
-                     [&tempConstant](SpirvConstantFloat *cachedConstant) {
-                       return tempConstant == *cachedConstant;
-                     });
-
-    if (found != floatConstants.end())
-      return *found;
-
-    // Couldn't find the constant. Create one.
-    auto *floatConst =
-        new (this) SpirvConstantFloat(floatType, value, specConst);
-    floatConstants.push_back(floatConst);
-    return floatConst;
-  }
-
-  template <class T> SpirvConstant *getConstantNullOfType(T type) {
-    SpirvConstantNull tempConstant(type);
-    auto found =
-        std::find_if(nullConstants.begin(), nullConstants.end(),
-                     [&tempConstant](SpirvConstantNull *cachedConstant) {
-                       return tempConstant == *cachedConstant;
-                     });
-
-    if (found != nullConstants.end())
-      return *found;
-
-    // Couldn't find the constant. Create one.
-    auto *nullConst = new (this) SpirvConstantNull(type);
-    nullConstants.push_back(nullConst);
-    return nullConst;
-  }
-
 private:
 private:
   /// \brief The allocator used to create SPIR-V entity objects.
   /// \brief The allocator used to create SPIR-V entity objects.
   ///
   ///
@@ -362,18 +286,6 @@ private:
 
 
   llvm::SmallVector<FunctionType *, 8> functionTypes;
   llvm::SmallVector<FunctionType *, 8> functionTypes;
   llvm::SmallVector<HybridFunctionType *, 8> hybridFunctionTypes;
   llvm::SmallVector<HybridFunctionType *, 8> hybridFunctionTypes;
-
-  // Unique constants
-  // We currently do a linear search to find an existing constant (if any). This
-  // can be done in a more efficient way if needed.
-  llvm::SmallVector<SpirvConstantComposite *, 8> compositeConstants;
-  llvm::SmallVector<SpirvConstantInteger *, 8> integerConstants;
-  llvm::SmallVector<SpirvConstantFloat *, 8> floatConstants;
-  SpirvConstantBoolean *boolTrueConstant;
-  SpirvConstantBoolean *boolFalseConstant;
-  SpirvConstantBoolean *boolTrueSpecConstant;
-  SpirvConstantBoolean *boolFalseSpecConstant;
-  llvm::SmallVector<SpirvConstantNull *, 8> nullConstants;
 };
 };
 
 
 } // end namespace spirv
 } // end namespace spirv

+ 3 - 1
tools/clang/include/clang/SPIRV/SpirvBasicBlock.h

@@ -69,7 +69,9 @@ public:
   bool hasTerminator() const;
   bool hasTerminator() const;
 
 
   /// Handle SPIR-V basic block visitors.
   /// Handle SPIR-V basic block visitors.
-  bool invokeVisitor(Visitor *);
+  /// If a basic block is the first basic block in a function, it must include
+  /// all the variable definitions of the entire function.
+  bool invokeVisitor(Visitor *, llvm::ArrayRef<SpirvVariable *> vars = {});
 
 
   /// \brief Adds the given basic block as a successsor to this basic block.
   /// \brief Adds the given basic block as a successsor to this basic block.
   void addSuccessor(SpirvBasicBlock *bb);
   void addSuccessor(SpirvBasicBlock *bb);

+ 98 - 11
tools/clang/include/clang/SPIRV/SpirvBuilder.h

@@ -66,17 +66,6 @@ public:
   SpirvFunctionParameter *addFnParam(const SpirvType *ptrType, SourceLocation,
   SpirvFunctionParameter *addFnParam(const SpirvType *ptrType, SourceLocation,
                                      llvm::StringRef name = "");
                                      llvm::StringRef name = "");
 
 
-  /// \brief Creates a SpirvFunction object and adds it to the list of module
-  /// functions. This does not change the current function under construction.
-  /// The handle can be used to create function call instructions for functions
-  /// that we have not yet been discovered in the source code.
-  /*
-  SpirvFunction *createFunction(QualType returnType,
-                                const SpirvType *functionType, SourceLocation,
-                                llvm::StringRef name = "",
-                                bool isAlias = false);
-  */
-
   /// \brief Creates a local variable of the given type in the current
   /// \brief Creates a local variable of the given type in the current
   /// function and returns it.
   /// function and returns it.
   ///
   ///
@@ -543,6 +532,26 @@ public:
   void decorateNonUniformEXT(SpirvInstruction *target,
   void decorateNonUniformEXT(SpirvInstruction *target,
                              SourceLocation srcLoc = {});
                              SourceLocation srcLoc = {});
 
 
+  /// --- Constants ---
+  /// Each of these methods can acquire a unique constant from the SpirvContext,
+  /// and add the context to the list of constants in the module.
+  SpirvConstant *getConstantUint16(uint16_t value, bool specConst = false);
+  SpirvConstant *getConstantInt16(int16_t value, bool specConst = false);
+  SpirvConstant *getConstantUint32(uint32_t value, bool specConst = false);
+  SpirvConstant *getConstantInt32(int32_t value, bool specConst = false);
+  SpirvConstant *getConstantUint64(uint64_t value, bool specConst = false);
+  SpirvConstant *getConstantInt64(int64_t value, bool specConst = false);
+  SpirvConstant *getConstantFloat16(uint16_t value, bool specConst = false);
+  SpirvConstant *getConstantFloat32(float value, bool specConst = false);
+  SpirvConstant *getConstantFloat64(double value, bool specConst = false);
+  SpirvConstant *getConstantBool(bool value, bool specConst = false);
+  SpirvConstant *
+  getConstantComposite(QualType compositeType,
+                       llvm::ArrayRef<SpirvConstant *> constituents,
+                       bool specConst = false);
+  SpirvConstant *getConstantNull(const SpirvType *);
+  SpirvConstant *getConstantNull(QualType);
+
 public:
 public:
   std::vector<uint32_t> takeModule();
   std::vector<uint32_t> takeModule();
 
 
@@ -556,6 +565,72 @@ private:
       SpirvInstruction *constOffsets, SpirvInstruction *sample,
       SpirvInstruction *constOffsets, SpirvInstruction *sample,
       SpirvInstruction *minLod);
       SpirvInstruction *minLod);
 
 
+private:
+  template <class T>
+  SpirvConstant *getConstantInt(T value, bool isSigned, uint32_t bitwidth,
+                                bool specConst) {
+    const IntegerType *intType =
+        isSigned ? context.getSIntType(bitwidth) : context.getUIntType(bitwidth);
+    SpirvConstantInteger tempConstant(intType, value, specConst);
+
+    auto found =
+        std::find_if(integerConstants.begin(), integerConstants.end(),
+                     [&tempConstant](SpirvConstantInteger *cachedConstant) {
+                       return tempConstant == *cachedConstant;
+                     });
+
+    if (found != integerConstants.end())
+      return *found;
+
+    // Couldn't find the constant. Create one.
+    auto *intConst =
+        new (context) SpirvConstantInteger(intType, value, specConst);
+    integerConstants.push_back(intConst);
+    module->addConstant(intConst);
+    return intConst;
+  }
+
+  template <class T>
+  SpirvConstant *getConstantFloat(T value, uint32_t bitwidth, bool specConst) {
+    const FloatType *floatType = context.getFloatType(bitwidth);
+    SpirvConstantFloat tempConstant(floatType, value, specConst);
+
+    auto found =
+        std::find_if(floatConstants.begin(), floatConstants.end(),
+                     [&tempConstant](SpirvConstantFloat *cachedConstant) {
+                       return tempConstant == *cachedConstant;
+                     });
+
+    if (found != floatConstants.end())
+      return *found;
+
+    // Couldn't find the constant. Create one.
+    auto *floatConst =
+        new (context) SpirvConstantFloat(floatType, value, specConst);
+    floatConstants.push_back(floatConst);
+    module->addConstant(floatConst);
+    return floatConst;
+  }
+
+  template <class T> SpirvConstant *getConstantNullOfType(T type) {
+    SpirvConstantNull tempConstant(type);
+    auto found =
+        std::find_if(nullConstants.begin(), nullConstants.end(),
+                     [&tempConstant](SpirvConstantNull *cachedConstant) {
+                       return tempConstant == *cachedConstant;
+                     });
+
+    if (found != nullConstants.end())
+      return *found;
+
+    // Couldn't find the constant. Create one.
+    auto *nullConst = new (context) SpirvConstantNull(type);
+    nullConstants.push_back(nullConst);
+    module->addConstant(nullConst);
+    return nullConst;
+  }
+
+
 private:
 private:
   ASTContext &astContext;
   ASTContext &astContext;
   SpirvContext &context; ///< From which we allocate various SPIR-V object
   SpirvContext &context; ///< From which we allocate various SPIR-V object
@@ -573,6 +648,18 @@ private:
 
 
   FeatureManager *featureManager; ///< SPIR-V version/extension manager.
   FeatureManager *featureManager; ///< SPIR-V version/extension manager.
   const SpirvCodeGenOptions &spirvOptions; ///< Command line options.
   const SpirvCodeGenOptions &spirvOptions; ///< Command line options.
+
+  // Unique constants
+  // We currently do a linear search to find an existing constant (if any). This
+  // can be done in a more efficient way if needed.
+  llvm::SmallVector<SpirvConstantComposite *, 8> compositeConstants;
+  llvm::SmallVector<SpirvConstantInteger *, 8> integerConstants;
+  llvm::SmallVector<SpirvConstantFloat *, 8> floatConstants;
+  llvm::SmallVector<SpirvConstantNull *, 8> nullConstants;
+  SpirvConstantBoolean *boolTrueConstant;
+  SpirvConstantBoolean *boolFalseConstant;
+  SpirvConstantBoolean *boolTrueSpecConstant;
+  SpirvConstantBoolean *boolFalseSpecConstant;
 };
 };
 
 
 void SpirvBuilder::requireCapability(spv::Capability cap, SourceLocation loc) {
 void SpirvBuilder::requireCapability(spv::Capability cap, SourceLocation loc) {

+ 3 - 0
tools/clang/include/clang/SPIRV/SpirvModule.h

@@ -82,6 +82,9 @@ public:
   // Adds a decoration to the module.
   // Adds a decoration to the module.
   void addDecoration(SpirvDecoration *);
   void addDecoration(SpirvDecoration *);
 
 
+  // Adds a constant to the module.
+  void addConstant(SpirvConstant *);
+
   void setShaderModelVersion(uint32_t v) { shaderModelVersion = v; }
   void setShaderModelVersion(uint32_t v) { shaderModelVersion = v; }
   void setSourceFileName(llvm::StringRef name) { sourceFileName = name; }
   void setSourceFileName(llvm::StringRef name) { sourceFileName = name; }
   void setSourceFileContent(llvm::StringRef c) { sourceFileContent = c; }
   void setSourceFileContent(llvm::StringRef c) { sourceFileContent = c; }

+ 8 - 8
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -507,7 +507,7 @@ SpirvInstruction *DeclResultIdMapper::getDeclEvalInfo(const ValueDecl *decl) {
       // used to be a pointer-to-transalted-qualtype.
       // used to be a pointer-to-transalted-qualtype.
       return spvBuilder.createAccessChain(
       return spvBuilder.createAccessChain(
           valueType, info->instr,
           valueType, info->instr,
-          {spvContext.getConstantInt32(info->indexInCTBuffer)});
+          {spvBuilder.getConstantInt32(info->indexInCTBuffer)});
     } else {
     } else {
       return *info;
       return *info;
     }
     }
@@ -1756,8 +1756,8 @@ bool DeclResultIdMapper::createStageVars(
       // represents a Boolean value where false must be exactly 0, but true can
       // represents a Boolean value where false must be exactly 0, but true can
       // be any odd (i.e. bit 0 set) non-zero value)."
       // be any odd (i.e. bit 0 set) non-zero value)."
       else if (semanticKind == hlsl::Semantic::Kind::InnerCoverage) {
       else if (semanticKind == hlsl::Semantic::Kind::InnerCoverage) {
-        const auto constOne = spvContext.getConstantUint32(1);
-        const auto constZero = spvContext.getConstantUint32(0);
+        const auto constOne = spvBuilder.getConstantUint32(1);
+        const auto constZero = spvBuilder.getConstantUint32(0);
         *value = spvBuilder.createSelect(astContext.UnsignedIntTy, *value,
         *value = spvBuilder.createSelect(astContext.UnsignedIntTy, *value,
                                          constOne, constZero);
                                          constOne, constZero);
       }
       }
@@ -1773,7 +1773,7 @@ bool DeclResultIdMapper::createStageVars(
                                                   astContext.FloatTy, x, y);
                                                   astContext.FloatTy, x, y);
         const auto z =
         const auto z =
             spvBuilder.createBinaryOp(spv::Op::OpFSub, astContext.FloatTy,
             spvBuilder.createBinaryOp(spv::Op::OpFSub, astContext.FloatTy,
-                                      spvContext.getConstantInt32(1), xy);
+                                      spvBuilder.getConstantInt32(1), xy);
         *value = spvBuilder.createCompositeConstruct(
         *value = spvBuilder.createCompositeConstruct(
             astContext.getExtVectorType(astContext.FloatTy, 3), {x, y, z});
             astContext.getExtVectorType(astContext.FloatTy, 3), {x, y, z});
       }
       }
@@ -1830,7 +1830,7 @@ bool DeclResultIdMapper::createStageVars(
           const auto ptrType = spvContext.getPointerType(
           const auto ptrType = spvContext.getPointerType(
               spvContext.getFloatType(32), spv::StorageClass::Output);
               spvContext.getFloatType(32), spv::StorageClass::Output);
           ptr = spvBuilder.createAccessChain(ptrType, varInstr,
           ptr = spvBuilder.createAccessChain(ptrType, varInstr,
-                                             {spvContext.getConstantUint32(i)});
+                                             {spvBuilder.getConstantUint32(i)});
           spvBuilder.createStore(ptr, spvBuilder.createCompositeExtract(
           spvBuilder.createStore(ptr, spvBuilder.createCompositeExtract(
                                           astContext.FloatTy, *value, {i}));
                                           astContext.FloatTy, *value, {i}));
         }
         }
@@ -1846,7 +1846,7 @@ bool DeclResultIdMapper::createStageVars(
         ptr = spvBuilder.createAccessChain(
         ptr = spvBuilder.createAccessChain(
             spvContext.getPointerType(spvContext.getFloatType(32),
             spvContext.getPointerType(spvContext.getFloatType(32),
                                       spv::StorageClass::Output),
                                       spv::StorageClass::Output),
-            varInstr, spvContext.getConstantUint32(0));
+            varInstr, spvBuilder.getConstantUint32(0));
         if (type->isArrayType()) // float[1]
         if (type->isArrayType()) // float[1]
           *value = spvBuilder.createCompositeExtract(astContext.FloatTy, *value,
           *value = spvBuilder.createCompositeExtract(astContext.FloatTy, *value,
                                                      {0});
                                                      {0});
@@ -1857,7 +1857,7 @@ bool DeclResultIdMapper::createStageVars(
       else if (semanticKind == hlsl::Semantic::Kind::Coverage) {
       else if (semanticKind == hlsl::Semantic::Kind::Coverage) {
         // Note(ehsan): used type rather than spir-v pointer to type.
         // Note(ehsan): used type rather than spir-v pointer to type.
         ptr = spvBuilder.createAccessChain(type, varInstr,
         ptr = spvBuilder.createAccessChain(type, varInstr,
-                                           spvContext.getConstantUint32(0));
+                                           spvBuilder.getConstantUint32(0));
         ptr->setStorageClass(spv::StorageClass::Output);
         ptr->setStorageClass(spv::StorageClass::Output);
         spvBuilder.createStore(ptr, *value);
         spvBuilder.createStore(ptr, *value);
       }
       }
@@ -2131,7 +2131,7 @@ DeclResultIdMapper::invertWIfRequested(SpirvInstruction *position) {
         spvBuilder.createCompositeExtract(astContext.FloatTy, position, {3});
         spvBuilder.createCompositeExtract(astContext.FloatTy, position, {3});
     const auto newW =
     const auto newW =
         spvBuilder.createBinaryOp(spv::Op::OpFDiv, astContext.FloatTy,
         spvBuilder.createBinaryOp(spv::Op::OpFDiv, astContext.FloatTy,
-                                  spvContext.getConstantFloat32(1), oldW);
+                                  spvBuilder.getConstantFloat32(1), oldW);
     position = spvBuilder.createCompositeInsert(
     position = spvBuilder.createCompositeInsert(
         astContext.getExtVectorType(astContext.FloatTy, 4), position, {3},
         astContext.getExtVectorType(astContext.FloatTy, 4), position, {3},
         newW);
         newW);

+ 6 - 1
tools/clang/lib/SPIRV/EmitVisitor.cpp

@@ -13,6 +13,7 @@
 #include "clang/SPIRV/SpirvFunction.h"
 #include "clang/SPIRV/SpirvFunction.h"
 #include "clang/SPIRV/SpirvInstruction.h"
 #include "clang/SPIRV/SpirvInstruction.h"
 #include "clang/SPIRV/SpirvModule.h"
 #include "clang/SPIRV/SpirvModule.h"
+#include "clang/SPIRV/SpirvBuilder.h"
 #include "clang/SPIRV/SpirvType.h"
 #include "clang/SPIRV/SpirvType.h"
 #include "clang/SPIRV/String.h"
 #include "clang/SPIRV/String.h"
 
 
@@ -183,6 +184,10 @@ std::vector<uint32_t> EmitVisitor::takeBinary() {
   result.insert(result.end(), typeConstantBinary.begin(),
   result.insert(result.end(), typeConstantBinary.begin(),
                 typeConstantBinary.end());
                 typeConstantBinary.end());
   result.insert(result.end(), mainBinary.begin(), mainBinary.end());
   result.insert(result.end(), mainBinary.begin(), mainBinary.end());
+
+  for (auto word : result) {
+    printf("%08" PRIx32 "\n", word);
+  }
   return result;
   return result;
 }
 }
 
 
@@ -1075,7 +1080,7 @@ uint32_t EmitTypeHandler::emitType(const SpirvType *type,
     // Emit the OpConstant instruction that is needed to get the result-id for
     // Emit the OpConstant instruction that is needed to get the result-id for
     // the array length.
     // the array length.
     SpirvConstant *constant =
     SpirvConstant *constant =
-        spirvContext.getConstantUint32(arrayType->getElementCount());
+        spirvBuilder.getConstantUint32(arrayType->getElementCount());
     if (getResultId<SpirvInstruction>(constant) == 0) {
     if (getResultId<SpirvInstruction>(constant) == 0) {
       constant->setResultId(takeNextIdFunction());
       constant->setResultId(takeNextIdFunction());
     }
     }

+ 10 - 10
tools/clang/lib/SPIRV/GlPerVertex.cpp

@@ -399,7 +399,7 @@ SpirvInstruction *GlPerVertex::readClipCullArrayAsType(bool isClip,
     uint32_t count = {};
     uint32_t count = {};
 
 
     if (isScalarType(asType)) {
     if (isScalarType(asType)) {
-      auto *spirvConstant = spvContext.getConstantUint32(offset);
+      auto *spirvConstant = spvBuilder.getConstantUint32(offset);
       auto *ptr =
       auto *ptr =
           spvBuilder.createAccessChain(ptrType, clipCullVar, {spirvConstant});
           spvBuilder.createAccessChain(ptrType, clipCullVar, {spirvConstant});
       return spvBuilder.createLoad(astContext.FloatTy, ptr);
       return spvBuilder.createLoad(astContext.FloatTy, ptr);
@@ -411,7 +411,7 @@ SpirvInstruction *GlPerVertex::readClipCullArrayAsType(bool isClip,
       llvm::SmallVector<SpirvInstruction *, 4> elements;
       llvm::SmallVector<SpirvInstruction *, 4> elements;
       for (uint32_t i = 0; i < count; ++i) {
       for (uint32_t i = 0; i < count; ++i) {
         // Read elements sequentially from the float array
         // Read elements sequentially from the float array
-        auto *spirvConstant = spvContext.getConstantUint32(offset + i);
+        auto *spirvConstant = spvBuilder.getConstantUint32(offset + i);
         auto *ptr =
         auto *ptr =
             spvBuilder.createAccessChain(ptrType, clipCullVar, {spirvConstant});
             spvBuilder.createAccessChain(ptrType, clipCullVar, {spirvConstant});
         elements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
         elements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
@@ -441,8 +441,8 @@ SpirvInstruction *GlPerVertex::readClipCullArrayAsType(bool isClip,
     for (uint32_t i = 0; i < inArraySize; ++i) {
     for (uint32_t i = 0; i < inArraySize; ++i) {
       auto *ptr = spvBuilder.createAccessChain(
       auto *ptr = spvBuilder.createAccessChain(
           ptrType, clipCullVar,
           ptrType, clipCullVar,
-          {spvContext.getConstantUint32(i), // Block array index
-           spvContext.getConstantUint32(offset)});
+          {spvBuilder.getConstantUint32(i), // Block array index
+           spvBuilder.getConstantUint32(offset)});
       arrayElements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
       arrayElements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
     }
     }
   } else if (isVectorType(asType, &elemType, &count)) {
   } else if (isVectorType(asType, &elemType, &count)) {
@@ -456,9 +456,9 @@ SpirvInstruction *GlPerVertex::readClipCullArrayAsType(bool isClip,
         auto *ptr = spvBuilder.createAccessChain(
         auto *ptr = spvBuilder.createAccessChain(
             ptrType, clipCullVar,
             ptrType, clipCullVar,
             // Block array index
             // Block array index
-            {spvContext.getConstantUint32(i),
+            {spvBuilder.getConstantUint32(i),
              // Read elements sequentially from the float array
              // Read elements sequentially from the float array
-             spvContext.getConstantUint32(offset + j)});
+             spvBuilder.getConstantUint32(offset + j)});
         vecElements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
         vecElements.push_back(spvBuilder.createLoad(astContext.FloatTy, ptr));
       }
       }
       arrayElements.push_back(spvBuilder.createCompositeConstruct(
       arrayElements.push_back(spvBuilder.createCompositeConstruct(
@@ -522,7 +522,7 @@ void GlPerVertex::writeClipCullArrayFromType(
     uint32_t count = {};
     uint32_t count = {};
 
 
     if (isScalarType(fromType)) {
     if (isScalarType(fromType)) {
-      auto *constant = spvContext.getConstantUint32(offset);
+      auto *constant = spvBuilder.getConstantUint32(offset);
       auto *ptr =
       auto *ptr =
           spvBuilder.createAccessChain(ptrType, clipCullVar, {constant});
           spvBuilder.createAccessChain(ptrType, clipCullVar, {constant});
       spvBuilder.createStore(ptr, fromValue);
       spvBuilder.createStore(ptr, fromValue);
@@ -534,7 +534,7 @@ void GlPerVertex::writeClipCullArrayFromType(
       // type. We need to write each component in the vector out.
       // type. We need to write each component in the vector out.
       for (uint32_t i = 0; i < count; ++i) {
       for (uint32_t i = 0; i < count; ++i) {
         // Write elements sequentially into the float array
         // Write elements sequentially into the float array
-        auto *constant = spvContext.getConstantUint32(offset + i);
+        auto *constant = spvBuilder.getConstantUint32(offset + i);
         auto *ptr =
         auto *ptr =
             spvBuilder.createAccessChain(ptrType, clipCullVar, {constant});
             spvBuilder.createAccessChain(ptrType, clipCullVar, {constant});
         auto *subValue = spvBuilder.createCompositeExtract(astContext.FloatTy,
         auto *subValue = spvBuilder.createCompositeExtract(astContext.FloatTy,
@@ -568,7 +568,7 @@ void GlPerVertex::writeClipCullArrayFromType(
   if (isScalarType(fromType)) {
   if (isScalarType(fromType)) {
     auto *ptr = spvBuilder.createAccessChain(
     auto *ptr = spvBuilder.createAccessChain(
         ptrType, clipCullVar,
         ptrType, clipCullVar,
-        {arrayIndex, spvContext.getConstantUint32(offset)});
+        {arrayIndex, spvBuilder.getConstantUint32(offset)});
     spvBuilder.createStore(ptr, fromValue);
     spvBuilder.createStore(ptr, fromValue);
     return;
     return;
   }
   }
@@ -581,7 +581,7 @@ void GlPerVertex::writeClipCullArrayFromType(
           // Block array index
           // Block array index
           {arrayIndex,
           {arrayIndex,
            // Write elements sequentially into the float array
            // Write elements sequentially into the float array
-           spvContext.getConstantUint32(offset + i)});
+           spvBuilder.getConstantUint32(offset + i)});
 
 
       auto *subValue =
       auto *subValue =
           spvBuilder.createCompositeExtract(astContext.FloatTy, fromValue, {i});
           spvBuilder.createCompositeExtract(astContext.FloatTy, fromValue, {i});

+ 1 - 95
tools/clang/lib/SPIRV/SPIRVContext.cpp

@@ -76,9 +76,7 @@ const Decoration *SPIRVContext::registerDecoration(const Decoration &d) {
 
 
 SpirvContext::SpirvContext()
 SpirvContext::SpirvContext()
     : allocator(), voidType(nullptr), boolType(nullptr), sintTypes({}),
     : allocator(), voidType(nullptr), boolType(nullptr), sintTypes({}),
-      uintTypes({}), floatTypes({}), samplerType(nullptr),
-      boolTrueConstant(nullptr), boolFalseConstant(nullptr),
-      boolTrueSpecConstant(nullptr), boolFalseSpecConstant(nullptr) {
+      uintTypes({}), floatTypes({}), samplerType(nullptr) {
   voidType = new (this) VoidType;
   voidType = new (this) VoidType;
   boolType = new (this) BoolType;
   boolType = new (this) BoolType;
   samplerType = new (this) SamplerType;
   samplerType = new (this) SamplerType;
@@ -377,98 +375,6 @@ const StructType *SpirvContext::getACSBufferCounterType() {
   return type;
   return type;
 }
 }
 
 
-SpirvConstant *SpirvContext::getConstantUint16(uint16_t value, bool specConst) {
-  return getConstantInt<uint16_t>(value, /*isSigned*/ false, 16, specConst);
-}
-SpirvConstant *SpirvContext::getConstantInt16(int16_t value, bool specConst) {
-  return getConstantInt<int16_t>(value, /*isSigned*/ true, 16, specConst);
-}
-SpirvConstant *SpirvContext::getConstantUint32(uint32_t value, bool specConst) {
-  return getConstantInt<uint32_t>(value, /*isSigned*/ false, 32, specConst);
-}
-SpirvConstant *SpirvContext::getConstantInt32(int32_t value, bool specConst) {
-  return getConstantInt<int32_t>(value, /*isSigned*/ true, 32, specConst);
-}
-SpirvConstant *SpirvContext::getConstantUint64(uint64_t value, bool specConst) {
-  return getConstantInt<uint64_t>(value, /*isSigned*/ false, 64, specConst);
-}
-SpirvConstant *SpirvContext::getConstantInt64(int64_t value, bool specConst) {
-  return getConstantInt<int64_t>(value, /*isSigned*/ true, 64, specConst);
-}
-
-SpirvConstant *SpirvContext::getConstantFloat16(uint16_t value,
-                                                bool specConst) {
-  return getConstantFloat<uint16_t>(value, 16, specConst);
-}
-SpirvConstant *SpirvContext::getConstantFloat32(float value, bool specConst) {
-  return getConstantFloat<float>(value, 32, specConst);
-}
-SpirvConstant *SpirvContext::getConstantFloat64(double value, bool specConst) {
-  return getConstantFloat<double>(value, 64, specConst);
-}
-
-SpirvConstant *SpirvContext::getConstantBool(bool value, bool specConst) {
-  if (value) {
-    if (specConst) {
-      return boolTrueSpecConstant;
-    } else {
-      return boolTrueConstant;
-    }
-  } else {
-    if (specConst) {
-      return boolFalseSpecConstant;
-    } else {
-      return boolFalseConstant;
-    }
-  }
-
-  // Couldn't find the constant. Create one.
-  auto *boolConst =
-      new (this) SpirvConstantBoolean(getBoolType(), value, specConst);
-
-  if (value) {
-    if (specConst)
-      boolTrueSpecConstant = boolConst;
-    else
-      boolTrueConstant = boolConst;
-  } else {
-    if (specConst)
-      boolFalseSpecConstant = boolConst;
-    else
-      boolFalseConstant = boolConst;
-  }
-
-  return boolConst;
-}
-
-SpirvConstant *
-SpirvContext::getConstantComposite(QualType compositeType,
-                                   llvm::ArrayRef<SpirvConstant *> constituents,
-                                   bool specConst) {
-  SpirvConstantComposite tempConstant(compositeType, constituents, specConst);
-  auto found =
-      std::find_if(compositeConstants.begin(), compositeConstants.end(),
-                   [&tempConstant](SpirvConstantComposite *cachedConstant) {
-                     return tempConstant == *cachedConstant;
-                   });
-
-  if (found != compositeConstants.end())
-    return *found;
-
-  // Couldn't find the constant. Create one.
-  auto *compositeConst =
-      new (this) SpirvConstantComposite(compositeType, constituents, specConst);
-  compositeConstants.push_back(compositeConst);
-  return compositeConst;
-}
-
-SpirvConstant *SpirvContext::getConstantNull(const SpirvType *type) {
-  return getConstantNullOfType<const SpirvType *>(type);
-}
-
-SpirvConstant *SpirvContext::getConstantNull(QualType type) {
-  return getConstantNullOfType<QualType>(type);
-}
 
 
 } // end namespace spirv
 } // end namespace spirv
 } // end namespace clang
 } // end namespace clang

+ 105 - 105
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -854,7 +854,7 @@ SpirvInstruction *SPIRVEmitter::doExpr(const Expr *expr) {
     result = doInitListExpr(initListExpr);
     result = doInitListExpr(initListExpr);
   } else if (const auto *boolLiteral = dyn_cast<CXXBoolLiteralExpr>(expr)) {
   } else if (const auto *boolLiteral = dyn_cast<CXXBoolLiteralExpr>(expr)) {
     result =
     result =
-        spvContext.getConstantBool(boolLiteral->getValue(), isSpecConstantMode);
+        spvBuilder.getConstantBool(boolLiteral->getValue(), isSpecConstantMode);
     result->setRValue();
     result->setRValue();
   } else if (const auto *intLiteral = dyn_cast<IntegerLiteral>(expr)) {
   } else if (const auto *intLiteral = dyn_cast<IntegerLiteral>(expr)) {
     result = translateAPInt(intLiteral->getValue(), expr->getType());
     result = translateAPInt(intLiteral->getValue(), expr->getType());
@@ -1177,7 +1177,7 @@ void SPIRVEmitter::doFunctionDecl(const FunctionDecl *decl) {
         // If the source code does not provide a proper return value for some
         // If the source code does not provide a proper return value for some
         // control flow path, it's undefined behavior. We just return null
         // control flow path, it's undefined behavior. We just return null
         // value here.
         // value here.
-        spvBuilder.createReturnValue(spvContext.getConstantNull(retType));
+        spvBuilder.createReturnValue(spvBuilder.getConstantNull(retType));
       }
       }
     }
     }
   }
   }
@@ -1529,7 +1529,7 @@ void SPIRVEmitter::doDoStmt(const DoStmt *theDoStmt,
     emitDebugLine(check->getLocStart());
     emitDebugLine(check->getLocStart());
     condition = doExpr(check);
     condition = doExpr(check);
   } else {
   } else {
-    condition = spvContext.getConstantBool(true);
+    condition = spvBuilder.getConstantBool(true);
   }
   }
   spvBuilder.createConditionalBranch(condition, headerBB, mergeBB);
   spvBuilder.createConditionalBranch(condition, headerBB, mergeBB);
   spvBuilder.addSuccessor(headerBB);
   spvBuilder.addSuccessor(headerBB);
@@ -1629,7 +1629,7 @@ void SPIRVEmitter::doWhileStmt(const WhileStmt *whileStmt,
     emitDebugLine(check->getLocStart());
     emitDebugLine(check->getLocStart());
     condition = doExpr(check);
     condition = doExpr(check);
   } else {
   } else {
-    condition = spvContext.getConstantBool(true);
+    condition = spvBuilder.getConstantBool(true);
   }
   }
   spvBuilder.createConditionalBranch(condition, bodyBB,
   spvBuilder.createConditionalBranch(condition, bodyBB,
                                      /*false branch*/ mergeBB,
                                      /*false branch*/ mergeBB,
@@ -1731,7 +1731,7 @@ void SPIRVEmitter::doForStmt(const ForStmt *forStmt,
     emitDebugLine(check->getLocStart());
     emitDebugLine(check->getLocStart());
     condition = doExpr(check);
     condition = doExpr(check);
   } else {
   } else {
-    condition = spvContext.getConstantBool(true);
+    condition = spvBuilder.getConstantBool(true);
   }
   }
   spvBuilder.createConditionalBranch(condition, bodyBB,
   spvBuilder.createConditionalBranch(condition, bodyBB,
                                      /*false branch*/ mergeBB,
                                      /*false branch*/ mergeBB,
@@ -2368,7 +2368,7 @@ SpirvInstruction *SPIRVEmitter::doCastExpr(const CastExpr *expr) {
     if (isa<SpirvConstant>(vecSplat)) {
     if (isa<SpirvConstant>(vecSplat)) {
       llvm::SmallVector<SpirvConstant *, 4> vectors(
       llvm::SmallVector<SpirvConstant *, 4> vectors(
           size_t(rowCount), cast<SpirvConstant>(vecSplat));
           size_t(rowCount), cast<SpirvConstant>(vecSplat));
-      auto *value = spvContext.getConstantComposite(toType, vectors);
+      auto *value = spvBuilder.getConstantComposite(toType, vectors);
       value->setRValue();
       value->setRValue();
       return value;
       return value;
     } else {
     } else {
@@ -2454,7 +2454,7 @@ SpirvInstruction *SPIRVEmitter::doCastExpr(const CastExpr *expr) {
     // Optimization: we can use OpConstantNull for cases where we want to
     // Optimization: we can use OpConstantNull for cases where we want to
     // initialize an entire data structure to zeros.
     // initialize an entire data structure to zeros.
     if (evaluatesToConstZero(subExpr, astContext)) {
     if (evaluatesToConstZero(subExpr, astContext)) {
-      subExprInstr = spvContext.getConstantNull(toType);
+      subExprInstr = spvBuilder.getConstantNull(toType);
       subExprInstr->setRValue();
       subExprInstr->setRValue();
       return subExprInstr;
       return subExprInstr;
     }
     }
@@ -2519,7 +2519,7 @@ SpirvInstruction *SPIRVEmitter::doCastExpr(const CastExpr *expr) {
 
 
     // Turn them in to SPIR-V constants
     // Turn them in to SPIR-V constants
     for (uint32_t i = 0; i < baseIndices.size(); ++i)
     for (uint32_t i = 0; i < baseIndices.size(); ++i)
-      baseIndexInstructions[i] = spvContext.getConstantUint32(baseIndices[i]);
+      baseIndexInstructions[i] = spvBuilder.getConstantUint32(baseIndices[i]);
 
 
     auto *derivedInfo = doExpr(subExpr);
     auto *derivedInfo = doExpr(subExpr);
     return turnIntoElementPtr(subExpr->getType(), derivedInfo, expr->getType(),
     return turnIntoElementPtr(subExpr->getType(), derivedInfo, expr->getType(),
@@ -2795,7 +2795,7 @@ SPIRVEmitter::processByteAddressBufferStructuredBufferGetDimensions(
   if (isByteAddressBuffer) {
   if (isByteAddressBuffer) {
     length =
     length =
         spvBuilder.createBinaryOp(spv::Op::OpIMul, astContext.UnsignedIntTy,
         spvBuilder.createBinaryOp(spv::Op::OpIMul, astContext.UnsignedIntTy,
-                                  length, spvContext.getConstantUint32(4u));
+                                  length, spvBuilder.getConstantUint32(4u));
   }
   }
   spvBuilder.createStore(doExpr(expr->getArg(0)), length);
   spvBuilder.createStore(doExpr(expr->getArg(0)), length);
 
 
@@ -2825,13 +2825,13 @@ SpirvInstruction *SPIRVEmitter::processRWByteAddressBufferAtomicMethods(
   const auto *object = expr->getImplicitObjectArgument();
   const auto *object = expr->getImplicitObjectArgument();
   auto *objectInfo = loadIfAliasVarRef(object);
   auto *objectInfo = loadIfAliasVarRef(object);
 
 
-  auto *zero = spvContext.getConstantUint32(0);
+  auto *zero = spvBuilder.getConstantUint32(0);
   auto *offset = doExpr(expr->getArg(0));
   auto *offset = doExpr(expr->getArg(0));
 
 
   // Right shift by 2 to convert the byte offset to uint32_t offset
   // Right shift by 2 to convert the byte offset to uint32_t offset
   auto *address = spvBuilder.createBinaryOp(spv::Op::OpShiftRightLogical,
   auto *address = spvBuilder.createBinaryOp(spv::Op::OpShiftRightLogical,
                                             astContext.UnsignedIntTy, offset,
                                             astContext.UnsignedIntTy, offset,
-                                            spvContext.getConstantUint32(2));
+                                            spvBuilder.getConstantUint32(2));
   // Note (ehsan): Using uintType instead of pointer-to-uint-type.
   // Note (ehsan): Using uintType instead of pointer-to-uint-type.
   auto *ptr = spvBuilder.createAccessChain(astContext.UnsignedIntTy, objectInfo,
   auto *ptr = spvBuilder.createAccessChain(astContext.UnsignedIntTy, objectInfo,
                                            {zero, address});
                                            {zero, address});
@@ -2882,8 +2882,8 @@ SPIRVEmitter::processSubpassLoad(const CXXMemberCallExpr *expr) {
   const auto *object = expr->getImplicitObjectArgument()->IgnoreParens();
   const auto *object = expr->getImplicitObjectArgument()->IgnoreParens();
   SpirvInstruction *sample =
   SpirvInstruction *sample =
       expr->getNumArgs() == 1 ? doExpr(expr->getArg(0)) : nullptr;
       expr->getNumArgs() == 1 ? doExpr(expr->getArg(0)) : nullptr;
-  auto *zero = spvContext.getConstantInt32(0);
-  auto *location = spvContext.getConstantComposite(
+  auto *zero = spvBuilder.getConstantInt32(0);
+  auto *location = spvBuilder.getConstantComposite(
       astContext.getExtVectorType(astContext.IntTy, 2), {zero, zero});
       astContext.getExtVectorType(astContext.IntTy, 2), {zero, zero});
 
 
   return processBufferTextureLoad(object, location, /*constOffset*/ 0,
   return processBufferTextureLoad(object, location, /*constOffset*/ 0,
@@ -2986,7 +2986,7 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
       lod = doExpr(mipLevel);
       lod = doExpr(mipLevel);
     } else {
     } else {
       // For Texture types when mipLevel argument is omitted.
       // For Texture types when mipLevel argument is omitted.
-      lod = spvContext.getConstantInt32(0);
+      lod = spvBuilder.getConstantInt32(0);
     }
     }
   }
   }
 
 
@@ -3129,7 +3129,7 @@ SpirvInstruction *SPIRVEmitter::processTextureGatherRGBACmpRGBA(
       const QualType v2i32 = astContext.getExtVectorType(astContext.IntTy, 2);
       const QualType v2i32 = astContext.getExtVectorType(astContext.IntTy, 2);
       const auto offsetType = astContext.getConstantArrayType(
       const auto offsetType = astContext.getConstantArrayType(
           v2i32, llvm::APInt(32, 4), clang::ArrayType::Normal, 0);
           v2i32, llvm::APInt(32, 4), clang::ArrayType::Normal, 0);
-      constOffsets = spvContext.getConstantComposite(
+      constOffsets = spvBuilder.getConstantComposite(
           offsetType, {offset0, offset1, offset2, offset3});
           offsetType, {offset0, offset1, offset2, offset3});
     } else {
     } else {
       needsEmulation = true;
       needsEmulation = true;
@@ -3147,7 +3147,7 @@ SpirvInstruction *SPIRVEmitter::processTextureGatherRGBACmpRGBA(
       varOffset = doExpr(expr->getArg(2 + isCmp + i));
       varOffset = doExpr(expr->getArg(2 + isCmp + i));
       auto *gatherRet = spvBuilder.createImageGather(
       auto *gatherRet = spvBuilder.createImageGather(
           retType, imageType, image, sampler, isNonUniform, coordinate,
           retType, imageType, image, sampler, isNonUniform, coordinate,
-          spvContext.getConstantInt32(component), compareVal,
+          spvBuilder.getConstantInt32(component), compareVal,
           /*constOffset*/ nullptr, varOffset, /*constOffsets*/ nullptr,
           /*constOffset*/ nullptr, varOffset, /*constOffsets*/ nullptr,
           /*sampleNumber*/ nullptr, status);
           /*sampleNumber*/ nullptr, status);
       texels[i] = spvBuilder.createCompositeExtract(elemType, gatherRet, {i});
       texels[i] = spvBuilder.createCompositeExtract(elemType, gatherRet, {i});
@@ -3158,7 +3158,7 @@ SpirvInstruction *SPIRVEmitter::processTextureGatherRGBACmpRGBA(
 
 
   return spvBuilder.createImageGather(
   return spvBuilder.createImageGather(
       retType, imageType, image, sampler, isNonUniform, coordinate,
       retType, imageType, image, sampler, isNonUniform, coordinate,
-      spvContext.getConstantInt32(component), compareVal, constOffset,
+      spvBuilder.getConstantInt32(component), compareVal, constOffset,
       varOffset, constOffsets, /*sampleNumber*/ nullptr, status);
       varOffset, constOffsets, /*sampleNumber*/ nullptr, status);
 }
 }
 
 
@@ -3309,7 +3309,7 @@ SpirvInstruction *SPIRVEmitter::processByteAddressBufferLoadStore(
   // Do a OpShiftRightLogical by 2 (divide by 4 to get aligned memory
   // Do a OpShiftRightLogical by 2 (divide by 4 to get aligned memory
   // access). The AST always casts the address to unsinged integer, so shift
   // access). The AST always casts the address to unsinged integer, so shift
   // by unsinged integer 2.
   // by unsinged integer 2.
-  auto *constUint2 = spvContext.getConstantUint32(2);
+  auto *constUint2 = spvBuilder.getConstantUint32(2);
   auto *address = spvBuilder.createBinaryOp(
   auto *address = spvBuilder.createBinaryOp(
       spv::Op::OpShiftRightLogical, addressType, byteAddress, constUint2);
       spv::Op::OpShiftRightLogical, addressType, byteAddress, constUint2);
 
 
@@ -3317,7 +3317,7 @@ SpirvInstruction *SPIRVEmitter::processByteAddressBufferLoadStore(
   // First index must be zero (member 0 of the struct is a
   // First index must be zero (member 0 of the struct is a
   // runtimeArray). The second index passed to OpAccessChain should be
   // runtimeArray). The second index passed to OpAccessChain should be
   // the address.
   // the address.
-  auto *constUint0 = spvContext.getConstantUint32(0);
+  auto *constUint0 = spvBuilder.getConstantUint32(0);
 
 
   if (doStore) {
   if (doStore) {
     auto *values = doExpr(expr->getArg(1));
     auto *values = doExpr(expr->getArg(1));
@@ -3331,7 +3331,7 @@ SpirvInstruction *SPIRVEmitter::processByteAddressBufferLoadStore(
 
 
       // Update the output address if necessary.
       // Update the output address if necessary.
       if (wordCounter > 0) {
       if (wordCounter > 0) {
-        auto *offset = spvContext.getConstantUint32(wordCounter);
+        auto *offset = spvBuilder.getConstantUint32(wordCounter);
         curStoreAddress = spvBuilder.createBinaryOp(
         curStoreAddress = spvBuilder.createBinaryOp(
             spv::Op::OpIAdd, addressType, address, offset);
             spv::Op::OpIAdd, addressType, address, offset);
       }
       }
@@ -3354,7 +3354,7 @@ SpirvInstruction *SPIRVEmitter::processByteAddressBufferLoadStore(
       llvm::SmallVector<SpirvInstruction *, 4> values;
       llvm::SmallVector<SpirvInstruction *, 4> values;
       values.push_back(result);
       values.push_back(result);
       for (uint32_t wordCounter = 2; wordCounter <= numWords; ++wordCounter) {
       for (uint32_t wordCounter = 2; wordCounter <= numWords; ++wordCounter) {
-        auto *offset = spvContext.getConstantUint32(wordCounter - 1);
+        auto *offset = spvBuilder.getConstantUint32(wordCounter - 1);
         auto *newAddress = spvBuilder.createBinaryOp(
         auto *newAddress = spvBuilder.createBinaryOp(
             spv::Op::OpIAdd, addressType, address, offset);
             spv::Op::OpIAdd, addressType, address, offset);
         // Note (ehsan): using value type rather than pointer type in access
         // Note (ehsan): using value type rather than pointer type in access
@@ -3389,7 +3389,7 @@ SPIRVEmitter::processStructuredBufferLoad(const CXXMemberCallExpr *expr) {
   const QualType structType =
   const QualType structType =
       hlsl::GetHLSLResourceResultType(buffer->getType());
       hlsl::GetHLSLResourceResultType(buffer->getType());
 
 
-  auto *zero = spvContext.getConstantInt32(0);
+  auto *zero = spvBuilder.getConstantInt32(0);
   auto *index = doExpr(expr->getArg(0));
   auto *index = doExpr(expr->getArg(0));
 
 
   return turnIntoElementPtr(buffer->getType(), info, structType, {zero, index});
   return turnIntoElementPtr(buffer->getType(), info, structType, {zero, index});
@@ -3398,8 +3398,8 @@ SPIRVEmitter::processStructuredBufferLoad(const CXXMemberCallExpr *expr) {
 SpirvInstruction *
 SpirvInstruction *
 SPIRVEmitter::incDecRWACSBufferCounter(const CXXMemberCallExpr *expr,
 SPIRVEmitter::incDecRWACSBufferCounter(const CXXMemberCallExpr *expr,
                                        bool isInc, bool loadObject) {
                                        bool isInc, bool loadObject) {
-  auto *zero = spvContext.getConstantUint32(0);
-  auto *sOne = spvContext.getConstantInt32(1);
+  auto *zero = spvBuilder.getConstantUint32(0);
+  auto *sOne = spvBuilder.getConstantInt32(1);
 
 
   const auto *object =
   const auto *object =
       expr->getImplicitObjectArgument()->IgnoreParenNoopCasts(astContext);
       expr->getImplicitObjectArgument()->IgnoreParenNoopCasts(astContext);
@@ -3576,7 +3576,7 @@ SpirvInstruction *
 SPIRVEmitter::processACSBufferAppendConsume(const CXXMemberCallExpr *expr) {
 SPIRVEmitter::processACSBufferAppendConsume(const CXXMemberCallExpr *expr) {
   const bool isAppend = expr->getNumArgs() == 1;
   const bool isAppend = expr->getNumArgs() == 1;
 
 
-  auto *zero = spvContext.getConstantUint32(0);
+  auto *zero = spvBuilder.getConstantUint32(0);
 
 
   const auto *object =
   const auto *object =
       expr->getImplicitObjectArgument()->IgnoreParenNoopCasts(astContext);
       expr->getImplicitObjectArgument()->IgnoreParenNoopCasts(astContext);
@@ -3694,14 +3694,14 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   const auto createArray = [this, v2f32Type](const Float2 *ptr, uint32_t len) {
   const auto createArray = [this, v2f32Type](const Float2 *ptr, uint32_t len) {
     llvm::SmallVector<SpirvConstant *, 16> components;
     llvm::SmallVector<SpirvConstant *, 16> components;
     for (uint32_t i = 0; i < len; ++i) {
     for (uint32_t i = 0; i < len; ++i) {
-      auto *x = spvContext.getConstantFloat32(ptr[i].x);
-      auto *y = spvContext.getConstantFloat32(ptr[i].y);
-      components.push_back(spvContext.getConstantComposite(v2f32Type, {x, y}));
+      auto *x = spvBuilder.getConstantFloat32(ptr[i].x);
+      auto *y = spvBuilder.getConstantFloat32(ptr[i].y);
+      components.push_back(spvBuilder.getConstantComposite(v2f32Type, {x, y}));
     }
     }
 
 
     const auto arrType = astContext.getConstantArrayType(
     const auto arrType = astContext.getConstantArrayType(
         v2f32Type, llvm::APInt(32, len), clang::ArrayType::Normal, 0);
         v2f32Type, llvm::APInt(32, len), clang::ArrayType::Normal, 0);
-    auto *val = spvContext.getConstantComposite(arrType, components);
+    auto *val = spvBuilder.getConstantComposite(arrType, components);
 
 
     const std::string varName =
     const std::string varName =
         "var.GetSamplePosition.data." + std::to_string(len);
         "var.GetSamplePosition.data." + std::to_string(len);
@@ -3736,7 +3736,7 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   //   if (count == 2) {
   //   if (count == 2) {
   const auto check2 =
   const auto check2 =
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
-                                sampleCount, spvContext.getConstantUint32(2));
+                                sampleCount, spvBuilder.getConstantUint32(2));
   spvBuilder.createConditionalBranch(check2, then2BB, else2BB, merge2BB);
   spvBuilder.createConditionalBranch(check2, then2BB, else2BB, merge2BB);
   spvBuilder.addSuccessor(then2BB);
   spvBuilder.addSuccessor(then2BB);
   spvBuilder.addSuccessor(else2BB);
   spvBuilder.addSuccessor(else2BB);
@@ -3755,7 +3755,7 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   spvBuilder.setInsertPoint(else2BB);
   spvBuilder.setInsertPoint(else2BB);
   const auto check4 =
   const auto check4 =
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
-                                sampleCount, spvContext.getConstantUint32(4));
+                                sampleCount, spvBuilder.getConstantUint32(4));
   spvBuilder.createConditionalBranch(check4, then4BB, else4BB, merge4BB);
   spvBuilder.createConditionalBranch(check4, then4BB, else4BB, merge4BB);
   spvBuilder.addSuccessor(then4BB);
   spvBuilder.addSuccessor(then4BB);
   spvBuilder.addSuccessor(else4BB);
   spvBuilder.addSuccessor(else4BB);
@@ -3774,7 +3774,7 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   spvBuilder.setInsertPoint(else4BB);
   spvBuilder.setInsertPoint(else4BB);
   const auto check8 =
   const auto check8 =
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
-                                sampleCount, spvContext.getConstantUint32(8));
+                                sampleCount, spvBuilder.getConstantUint32(8));
   spvBuilder.createConditionalBranch(check8, then8BB, else8BB, merge8BB);
   spvBuilder.createConditionalBranch(check8, then8BB, else8BB, merge8BB);
   spvBuilder.addSuccessor(then8BB);
   spvBuilder.addSuccessor(then8BB);
   spvBuilder.addSuccessor(else8BB);
   spvBuilder.addSuccessor(else8BB);
@@ -3793,7 +3793,7 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   spvBuilder.setInsertPoint(else8BB);
   spvBuilder.setInsertPoint(else8BB);
   const auto check16 =
   const auto check16 =
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
       spvBuilder.createBinaryOp(spv::Op::OpIEqual, astContext.BoolTy,
-                                sampleCount, spvContext.getConstantUint32(16));
+                                sampleCount, spvBuilder.getConstantUint32(16));
   spvBuilder.createConditionalBranch(check16, then16BB, else16BB, merge16BB);
   spvBuilder.createConditionalBranch(check16, then16BB, else16BB, merge16BB);
   spvBuilder.addSuccessor(then16BB);
   spvBuilder.addSuccessor(then16BB);
   spvBuilder.addSuccessor(else16BB);
   spvBuilder.addSuccessor(else16BB);
@@ -3812,8 +3812,8 @@ SPIRVEmitter::emitGetSamplePosition(SpirvInstruction *sampleCount,
   //     position = float2(0.0f, 0.0f);
   //     position = float2(0.0f, 0.0f);
   //   }
   //   }
   spvBuilder.setInsertPoint(else16BB);
   spvBuilder.setInsertPoint(else16BB);
-  auto *zero = spvContext.getConstantFloat32(0);
-  auto *v2f32Zero = spvContext.getConstantComposite(v2f32Type, {zero, zero});
+  auto *zero = spvBuilder.getConstantFloat32(0);
+  auto *v2f32Zero = spvBuilder.getConstantComposite(v2f32Type, {zero, zero});
   spvBuilder.createStore(resultVar, v2f32Zero);
   spvBuilder.createStore(resultVar, v2f32Zero);
   spvBuilder.createBranch(merge16BB);
   spvBuilder.createBranch(merge16BB);
   spvBuilder.addSuccessor(merge16BB);
   spvBuilder.addSuccessor(merge16BB);
@@ -4113,7 +4113,7 @@ SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
     return spvBuilder.createImageGather(
     return spvBuilder.createImageGather(
         retType, imageType, image, sampler, isNonUniform, coordinate,
         retType, imageType, image, sampler, isNonUniform, coordinate,
         // .Gather() doc says we return four components of red data.
         // .Gather() doc says we return four components of red data.
-        spvContext.getConstantInt32(0), /*compareVal*/ nullptr, constOffset,
+        spvBuilder.getConstantInt32(0), /*compareVal*/ nullptr, constOffset,
         varOffset, /*constOffsets*/ nullptr, /*sampleNumber*/ nullptr, status);
         varOffset, /*constOffsets*/ nullptr, /*sampleNumber*/ nullptr, status);
   }
   }
 }
 }
@@ -4330,7 +4330,7 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
   SpirvInstruction *constOffset = nullptr, *varOffset = nullptr;
   SpirvInstruction *constOffset = nullptr, *varOffset = nullptr;
   if (hasOffsetArg)
   if (hasOffsetArg)
     handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
     handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
-  auto *lod = isCmp ? nullptr : spvContext.getConstantFloat32(0);
+  auto *lod = isCmp ? nullptr : spvBuilder.getConstantFloat32(0);
 
 
   const auto retType = expr->getDirectCallee()->getReturnType();
   const auto retType = expr->getDirectCallee()->getReturnType();
   const auto imageType = imageExpr->getType();
   const auto imageType = imageExpr->getType();
@@ -4471,7 +4471,7 @@ SPIRVEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr) {
     // For Textures, regular indexing (operator[]) uses slice 0.
     // For Textures, regular indexing (operator[]) uses slice 0.
     if (isBufferTextureIndexing(expr, &baseExpr, &indexExpr)) {
     if (isBufferTextureIndexing(expr, &baseExpr, &indexExpr)) {
       auto *lod = TypeTranslator::isTexture(baseExpr->getType())
       auto *lod = TypeTranslator::isTexture(baseExpr->getType())
-                      ? spvContext.getConstantUint32(0)
+                      ? spvBuilder.getConstantUint32(0)
                       : nullptr;
                       : nullptr;
       return processBufferTextureLoad(baseExpr, doExpr(indexExpr),
       return processBufferTextureLoad(baseExpr, doExpr(indexExpr),
                                       /*constOffset*/ nullptr,
                                       /*constOffset*/ nullptr,
@@ -4543,7 +4543,7 @@ SPIRVEmitter::doExtMatrixElementExpr(const ExtMatrixElementExpr *expr) {
     if (baseExpr->isGLValue()) {
     if (baseExpr->isGLValue()) {
       llvm::SmallVector<SpirvInstruction *, 2> indexInstructions;
       llvm::SmallVector<SpirvInstruction *, 2> indexInstructions;
       for (uint32_t i = 0; i < indices.size(); ++i)
       for (uint32_t i = 0; i < indices.size(); ++i)
-        indexInstructions[i] = spvContext.getConstantInt32(indices[i]);
+        indexInstructions[i] = spvBuilder.getConstantInt32(indices[i]);
 
 
       if (!indices.empty()) {
       if (!indices.empty()) {
         assert(!baseInfo->isRValue());
         assert(!baseInfo->isRValue());
@@ -4623,7 +4623,7 @@ SPIRVEmitter::doHLSLVectorElementExpr(const HLSLVectorElementExpr *expr) {
     const auto type = expr->getType();
     const auto type = expr->getType();
 
 
     if (!baseInfo->isRValue()) { // E.g., v.x;
     if (!baseInfo->isRValue()) { // E.g., v.x;
-      auto *index = spvContext.getConstantInt32(accessor.Swz0);
+      auto *index = spvBuilder.getConstantInt32(accessor.Swz0);
       // We need a lvalue here. Do not try to load.
       // We need a lvalue here. Do not try to load.
       // Note (ehsan): result type of access chain used to be pointer to type.
       // Note (ehsan): result type of access chain used to be pointer to type.
       // now we're using type.
       // now we're using type.
@@ -5016,7 +5016,7 @@ void SPIRVEmitter::storeValue(SpirvInstruction *lhsPtr,
       // Note (ehsan): We used to use pointer to elemType as access chain result
       // Note (ehsan): We used to use pointer to elemType as access chain result
       // type. Now we are just using the elemType.
       // type. Now we are just using the elemType.
       auto *subRhsPtr = spvBuilder.createAccessChain(
       auto *subRhsPtr = spvBuilder.createAccessChain(
-          elemType, rhsVal, {spvContext.getConstantInt32(i)});
+          elemType, rhsVal, {spvBuilder.getConstantInt32(i)});
       elements.push_back(spvBuilder.createLoad(elemType, subRhsPtr));
       elements.push_back(spvBuilder.createLoad(elemType, subRhsPtr));
     }
     }
 
 
@@ -5312,7 +5312,7 @@ void SPIRVEmitter::initOnce(QualType varType, std::string varName,
   // Create a file/module visible variable to hold the initialization state.
   // Create a file/module visible variable to hold the initialization state.
   SpirvVariable *initDoneVar =
   SpirvVariable *initDoneVar =
       spvBuilder.addModuleVar(astContext.BoolTy, spv::StorageClass::Private,
       spvBuilder.addModuleVar(astContext.BoolTy, spv::StorageClass::Private,
-                              varName, spvContext.getConstantBool(false));
+                              varName, spvBuilder.getConstantBool(false));
 
 
   auto *condition = spvBuilder.createLoad(astContext.BoolTy, initDoneVar);
   auto *condition = spvBuilder.createLoad(astContext.BoolTy, initDoneVar);
 
 
@@ -5334,9 +5334,9 @@ void SPIRVEmitter::initOnce(QualType varType, std::string varName,
         // Static function variable are of private storage class
         // Static function variable are of private storage class
         var, doExpr(varInit), varInit->getType());
         var, doExpr(varInit), varInit->getType());
   } else {
   } else {
-    spvBuilder.createStore(var, spvContext.getConstantNull(varType));
+    spvBuilder.createStore(var, spvBuilder.getConstantNull(varType));
   }
   }
-  spvBuilder.createStore(initDoneVar, spvContext.getConstantBool(true));
+  spvBuilder.createStore(initDoneVar, spvBuilder.getConstantBool(true));
   spvBuilder.createBranch(doneBB);
   spvBuilder.createBranch(doneBB);
   spvBuilder.addSuccessor(doneBB);
   spvBuilder.addSuccessor(doneBB);
 
 
@@ -5508,7 +5508,7 @@ SpirvInstruction *SPIRVEmitter::createVectorSplat(const Expr *scalarExpr,
   // Should find a more meaningful one.
   // Should find a more meaningful one.
   if (auto *constVal = dyn_cast<SpirvConstant>(scalarVal)) {
   if (auto *constVal = dyn_cast<SpirvConstant>(scalarVal)) {
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), constVal);
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), constVal);
-    auto *value = spvContext.getConstantComposite(vecType, elements);
+    auto *value = spvBuilder.getConstantComposite(vecType, elements);
     value->setRValue();
     value->setRValue();
     return value;
     return value;
   } else {
   } else {
@@ -5859,7 +5859,7 @@ SPIRVEmitter::tryToAssignToMatrixElements(const Expr *lhs,
       indices.push_back(col);
       indices.push_back(col);
 
 
     for (uint32_t i = 0; i < indices.size(); ++i)
     for (uint32_t i = 0; i < indices.size(); ++i)
-      indexInstructions[i] = spvContext.getConstantInt32(indices[i]);
+      indexInstructions[i] = spvBuilder.getConstantInt32(indices[i]);
 
 
     // If we are writing to only one element, the rhs should already be a
     // If we are writing to only one element, the rhs should already be a
     // scalar value.
     // scalar value.
@@ -6068,7 +6068,7 @@ const Expr *SPIRVEmitter::collectArrayStructIndices(
     if (rawIndex) {
     if (rawIndex) {
       rawIndices->push_back(index);
       rawIndices->push_back(index);
     } else {
     } else {
-      indices->push_back(spvContext.getConstantInt32(index));
+      indices->push_back(spvBuilder.getConstantInt32(index));
     }
     }
 
 
     return base;
     return base;
@@ -6125,7 +6125,7 @@ const Expr *SPIRVEmitter::collectArrayStructIndices(
       // here. This is because we created an additional OpTypeRuntimeArray
       // here. This is because we created an additional OpTypeRuntimeArray
       // in the structure.
       // in the structure.
       if (TypeTranslator::isStructuredBuffer(thisBaseType))
       if (TypeTranslator::isStructuredBuffer(thisBaseType))
-        indices->push_back(spvContext.getConstantInt32(0));
+        indices->push_back(spvBuilder.getConstantInt32(0));
 
 
       if ((hlsl::IsHLSLVecType(thisBaseType) &&
       if ((hlsl::IsHLSLVecType(thisBaseType) &&
            (hlsl::GetHLSLVecSize(thisBaseType) == 1)) ||
            (hlsl::GetHLSLVecSize(thisBaseType) == 1)) ||
@@ -6146,7 +6146,7 @@ const Expr *SPIRVEmitter::collectArrayStructIndices(
 
 
       // For object.Load(index), there should be no more indexing into the
       // For object.Load(index), there should be no more indexing into the
       // object.
       // object.
-      indices->push_back(spvContext.getConstantInt32(0));
+      indices->push_back(spvBuilder.getConstantInt32(0));
       indices->push_back(doExpr(index));
       indices->push_back(doExpr(index));
       return object;
       return object;
     }
     }
@@ -6809,7 +6809,7 @@ SPIRVEmitter::processIntrinsicInterlockedMethod(const CallExpr *expr,
   // Moreover, the frontend does not add a cast AST node to cast uint to int
   // Moreover, the frontend does not add a cast AST node to cast uint to int
   // where necessary. To ensure SPIR-V validity, we add that where necessary.
   // where necessary. To ensure SPIR-V validity, we add that where necessary.
 
 
-  auto *zero = spvContext.getConstantUint32(0);
+  auto *zero = spvBuilder.getConstantUint32(0);
   const auto *dest = expr->getArg(0);
   const auto *dest = expr->getArg(0);
   const auto baseType = dest->getType();
   const auto baseType = dest->getType();
 
 
@@ -6984,10 +6984,10 @@ SPIRVEmitter::processIntrinsicMsad4(const CallExpr *callExpr) {
   auto *reference = doExpr(callExpr->getArg(0));
   auto *reference = doExpr(callExpr->getArg(0));
   auto *source = doExpr(callExpr->getArg(1));
   auto *source = doExpr(callExpr->getArg(1));
   auto *accum = doExpr(callExpr->getArg(2));
   auto *accum = doExpr(callExpr->getArg(2));
-  const auto uint0 = spvContext.getConstantUint32(0);
-  const auto uint8 = spvContext.getConstantUint32(8);
-  const auto uint16 = spvContext.getConstantUint32(16);
-  const auto uint24 = spvContext.getConstantUint32(24);
+  const auto uint0 = spvBuilder.getConstantUint32(0);
+  const auto uint8 = spvBuilder.getConstantUint32(8);
+  const auto uint16 = spvBuilder.getConstantUint32(16);
+  const auto uint24 = spvBuilder.getConstantUint32(24);
 
 
   // Step 1.
   // Step 1.
   auto *v1x = spvBuilder.createCompositeExtract(uintType, source, {0});
   auto *v1x = spvBuilder.createCompositeExtract(uintType, source, {0});
@@ -7073,7 +7073,7 @@ SPIRVEmitter::processIntrinsicMsad4(const CallExpr *callExpr) {
   llvm::SmallVector<SpirvInstruction *, 4> isRefByteZero;
   llvm::SmallVector<SpirvInstruction *, 4> isRefByteZero;
   for (uint32_t i = 0; i < 4; ++i) {
   for (uint32_t i = 0; i < 4; ++i) {
     refBytes.push_back(spvBuilder.createBitFieldExtract(
     refBytes.push_back(spvBuilder.createBitFieldExtract(
-        uintType, reference, /*offset*/ spvContext.getConstantUint32(i * 8),
+        uintType, reference, /*offset*/ spvBuilder.getConstantUint32(i * 8),
         /*count*/ uint8, /*isSigned*/ false));
         /*count*/ uint8, /*isSigned*/ false));
     signedRefBytes.push_back(
     signedRefBytes.push_back(
         spvBuilder.createUnaryOp(spv::Op::OpBitcast, intType, refBytes.back()));
         spvBuilder.createUnaryOp(spv::Op::OpBitcast, intType, refBytes.back()));
@@ -7086,7 +7086,7 @@ SPIRVEmitter::processIntrinsicMsad4(const CallExpr *callExpr) {
       // 'count' is always 8 because we are extracting 8 bits out of 32.
       // 'count' is always 8 because we are extracting 8 bits out of 32.
       auto *srcByte = spvBuilder.createBitFieldExtract(
       auto *srcByte = spvBuilder.createBitFieldExtract(
           uintType, sources[msadNum],
           uintType, sources[msadNum],
-          /*offset*/ spvContext.getConstantUint32(8 * byteCount),
+          /*offset*/ spvBuilder.getConstantUint32(8 * byteCount),
           /*count*/ uint8, /*isSigned*/ false);
           /*count*/ uint8, /*isSigned*/ false);
       auto *signedSrcByte =
       auto *signedSrcByte =
           spvBuilder.createUnaryOp(spv::Op::OpBitcast, intType, srcByte);
           spvBuilder.createUnaryOp(spv::Op::OpBitcast, intType, srcByte);
@@ -7300,13 +7300,13 @@ SPIRVEmitter::processWaveQuadWideShuffle(const CallExpr *callExpr,
   spv::Op opcode = spv::Op::OpGroupNonUniformQuadSwap;
   spv::Op opcode = spv::Op::OpGroupNonUniformQuadSwap;
   switch (op) {
   switch (op) {
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossX:
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossX:
-    target = spvContext.getConstantUint32(0);
+    target = spvBuilder.getConstantUint32(0);
     break;
     break;
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossY:
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossY:
-    target = spvContext.getConstantUint32(1);
+    target = spvBuilder.getConstantUint32(1);
     break;
     break;
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossDiagonal:
   case hlsl::IntrinsicOp::IOP_QuadReadAcrossDiagonal:
-    target = spvContext.getConstantUint32(2);
+    target = spvBuilder.getConstantUint32(2);
     break;
     break;
   case hlsl::IntrinsicOp::IOP_QuadReadLaneAt:
   case hlsl::IntrinsicOp::IOP_QuadReadLaneAt:
     target = doExpr(callExpr->getArg(1));
     target = doExpr(callExpr->getArg(1));
@@ -7422,8 +7422,8 @@ SpirvInstruction *SPIRVEmitter::processIntrinsicLit(const CallExpr *callExpr) {
   auto *m = doExpr(callExpr->getArg(2));
   auto *m = doExpr(callExpr->getArg(2));
   const QualType floatType = astContext.FloatTy;
   const QualType floatType = astContext.FloatTy;
   const QualType boolType = astContext.BoolTy;
   const QualType boolType = astContext.BoolTy;
-  SpirvInstruction *floatZero = spvContext.getConstantFloat32(0);
-  SpirvInstruction *floatOne = spvContext.getConstantFloat32(1);
+  SpirvInstruction *floatZero = spvBuilder.getConstantFloat32(0);
+  SpirvInstruction *floatOne = spvBuilder.getConstantFloat32(1);
   const QualType retType = callExpr->getType();
   const QualType retType = callExpr->getType();
   auto *diffuse = spvBuilder.createExtInst(
   auto *diffuse = spvBuilder.createExtInst(
       floatType, glslInstSet, GLSLstd450::GLSLstd450FMax, {floatZero, nDotL});
       floatType, glslInstSet, GLSLstd450::GLSLstd450FMax, {floatZero, nDotL});
@@ -7594,7 +7594,7 @@ SpirvInstruction *SPIRVEmitter::processIntrinsicDst(const CallExpr *callExpr) {
       spvBuilder.createBinaryOp(spv::Op::OpFMul, f32, arg0y, arg1y);
       spvBuilder.createBinaryOp(spv::Op::OpFMul, f32, arg0y, arg1y);
   return spvBuilder.createCompositeConstruct(
   return spvBuilder.createCompositeConstruct(
       callExpr->getType(),
       callExpr->getType(),
-      {spvContext.getConstantFloat32(1.0), arg0yMularg1y, arg0z, arg1w});
+      {spvBuilder.getConstantFloat32(1.0), arg0yMularg1y, arg0z, arg1w});
 }
 }
 
 
 SpirvInstruction *SPIRVEmitter::processIntrinsicClip(const CallExpr *callExpr) {
 SpirvInstruction *SPIRVEmitter::processIntrinsicClip(const CallExpr *callExpr) {
@@ -7631,7 +7631,7 @@ SpirvInstruction *SPIRVEmitter::processIntrinsicClip(const CallExpr *callExpr) {
     const auto floatVecType = astContext.getExtVectorType(elemType, colCount);
     const auto floatVecType = astContext.getExtVectorType(elemType, colCount);
     auto *elemZero = getValueZero(elemType);
     auto *elemZero = getValueZero(elemType);
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(colCount), elemZero);
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(colCount), elemZero);
-    auto *zero = spvContext.getConstantComposite(floatVecType, elements);
+    auto *zero = spvBuilder.getConstantComposite(floatVecType, elements);
     llvm::SmallVector<SpirvInstruction *, 4> cmpResults;
     llvm::SmallVector<SpirvInstruction *, 4> cmpResults;
     for (uint32_t i = 0; i < rowCount; ++i) {
     for (uint32_t i = 0; i < rowCount; ++i) {
       auto *lhsVec =
       auto *lhsVec =
@@ -8394,7 +8394,7 @@ SPIRVEmitter::processD3DCOLORtoUBYTE4(const CallExpr *callExpr) {
       spvBuilder.createVectorShuffle(argType, argId, argId, {2, 1, 0, 3});
       spvBuilder.createVectorShuffle(argType, argId, argId, {2, 1, 0, 3});
   auto *scaled =
   auto *scaled =
       spvBuilder.createBinaryOp(spv::Op::OpVectorTimesScalar, argType, swizzle,
       spvBuilder.createBinaryOp(spv::Op::OpVectorTimesScalar, argType, swizzle,
-                                spvContext.getConstantFloat32(255.002f));
+                                spvBuilder.getConstantFloat32(255.002f));
   return castToInt(scaled, arg->getType(), callExpr->getType(),
   return castToInt(scaled, arg->getType(), callExpr->getType(),
                    callExpr->getExprLoc());
                    callExpr->getExprLoc());
 }
 }
@@ -8557,7 +8557,7 @@ SPIRVEmitter::processIntrinsicF32ToF16(const CallExpr *callExpr) {
   const QualType f32Type = astContext.FloatTy;
   const QualType f32Type = astContext.FloatTy;
   const QualType u32Type = astContext.UnsignedIntTy;
   const QualType u32Type = astContext.UnsignedIntTy;
   const QualType v2f32Type = astContext.getExtVectorType(f32Type, 2);
   const QualType v2f32Type = astContext.getExtVectorType(f32Type, 2);
-  auto *zero = spvContext.getConstantFloat32(0);
+  auto *zero = spvBuilder.getConstantFloat32(0);
 
 
   const auto *arg = callExpr->getArg(0);
   const auto *arg = callExpr->getArg(0);
   auto *argId = doExpr(arg);
   auto *argId = doExpr(arg);
@@ -8724,7 +8724,7 @@ SPIRVEmitter::processIntrinsicLog10(const CallExpr *callExpr) {
   // Since there is no log10 instruction in SPIR-V, we can use:
   // Since there is no log10 instruction in SPIR-V, we can use:
   // log10(x) = log2(x) * ( 1 / log2(10) )
   // log10(x) = log2(x) * ( 1 / log2(10) )
   // 1 / log2(10) = 0.30103
   // 1 / log2(10) = 0.30103
-  auto *scale = spvContext.getConstantFloat32(0.30103f);
+  auto *scale = spvBuilder.getConstantFloat32(0.30103f);
   auto *log2 =
   auto *log2 =
       processIntrinsicUsingGLSLInst(callExpr, GLSLstd450::GLSLstd450Log2, true);
       processIntrinsicUsingGLSLInst(callExpr, GLSLstd450::GLSLstd450Log2, true);
   const auto returnType = callExpr->getType();
   const auto returnType = callExpr->getType();
@@ -8741,15 +8741,15 @@ SpirvConstant *SPIRVEmitter::getValueZero(QualType type) {
     QualType scalarType = {};
     QualType scalarType = {};
     if (isScalarType(type, &scalarType)) {
     if (isScalarType(type, &scalarType)) {
       if (scalarType->isSignedIntegerType()) {
       if (scalarType->isSignedIntegerType()) {
-        return spvContext.getConstantInt32(0);
+        return spvBuilder.getConstantInt32(0);
       }
       }
 
 
       if (scalarType->isUnsignedIntegerType()) {
       if (scalarType->isUnsignedIntegerType()) {
-        return spvContext.getConstantUint32(0);
+        return spvBuilder.getConstantUint32(0);
       }
       }
 
 
       if (scalarType->isFloatingType()) {
       if (scalarType->isFloatingType()) {
-        return spvContext.getConstantFloat32(0.0);
+        return spvBuilder.getConstantFloat32(0.0);
       }
       }
     }
     }
   }
   }
@@ -8768,7 +8768,7 @@ SpirvConstant *SPIRVEmitter::getValueZero(QualType type) {
     if (isMxNMatrix(type, &elemType, &rowCount, &colCount)) {
     if (isMxNMatrix(type, &elemType, &rowCount, &colCount)) {
       auto *row = getVecValueZero(elemType, colCount);
       auto *row = getVecValueZero(elemType, colCount);
       llvm::SmallVector<SpirvConstant *, 4> rows((size_t)rowCount, row);
       llvm::SmallVector<SpirvConstant *, 4> rows((size_t)rowCount, row);
-      return spvContext.getConstantComposite(type, rows);
+      return spvBuilder.getConstantComposite(type, rows);
     }
     }
   }
   }
 
 
@@ -8785,7 +8785,7 @@ SpirvConstant *SPIRVEmitter::getVecValueZero(QualType elemType, uint32_t size) {
 
 
   llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), elemZeroId);
   llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), elemZeroId);
   const QualType vecType = astContext.getExtVectorType(elemType, size);
   const QualType vecType = astContext.getExtVectorType(elemType, size);
-  return spvContext.getConstantComposite(vecType, elements);
+  return spvBuilder.getConstantComposite(vecType, elements);
 }
 }
 
 
 SpirvConstant *SPIRVEmitter::getValueOne(QualType type) {
 SpirvConstant *SPIRVEmitter::getValueOne(QualType type) {
@@ -8793,38 +8793,38 @@ SpirvConstant *SPIRVEmitter::getValueOne(QualType type) {
     QualType scalarType = {};
     QualType scalarType = {};
     if (isScalarType(type, &scalarType)) {
     if (isScalarType(type, &scalarType)) {
       if (scalarType->isBooleanType()) {
       if (scalarType->isBooleanType()) {
-        return spvContext.getConstantBool(true);
+        return spvBuilder.getConstantBool(true);
       }
       }
 
 
       const auto bitWidth = typeTranslator.getElementSpirvBitwidth(scalarType);
       const auto bitWidth = typeTranslator.getElementSpirvBitwidth(scalarType);
       if (scalarType->isSignedIntegerType()) {
       if (scalarType->isSignedIntegerType()) {
         switch (bitWidth) {
         switch (bitWidth) {
         case 16:
         case 16:
-          return spvContext.getConstantInt16(1);
+          return spvBuilder.getConstantInt16(1);
         case 32:
         case 32:
-          return spvContext.getConstantInt32(1);
+          return spvBuilder.getConstantInt32(1);
         case 64:
         case 64:
-          return spvContext.getConstantInt64(1);
+          return spvBuilder.getConstantInt64(1);
         }
         }
       }
       }
       if (scalarType->isUnsignedIntegerType()) {
       if (scalarType->isUnsignedIntegerType()) {
         switch (bitWidth) {
         switch (bitWidth) {
         case 16:
         case 16:
-          return spvContext.getConstantUint16(1);
+          return spvBuilder.getConstantUint16(1);
         case 32:
         case 32:
-          return spvContext.getConstantUint32(1);
+          return spvBuilder.getConstantUint32(1);
         case 64:
         case 64:
-          return spvContext.getConstantUint64(1);
+          return spvBuilder.getConstantUint64(1);
         }
         }
       }
       }
       if (scalarType->isFloatingType()) {
       if (scalarType->isFloatingType()) {
         switch (bitWidth) {
         switch (bitWidth) {
         case 16:
         case 16:
-          return spvContext.getConstantFloat16(1);
+          return spvBuilder.getConstantFloat16(1);
         case 32:
         case 32:
-          return spvContext.getConstantFloat32(1.0);
+          return spvBuilder.getConstantFloat32(1.0);
         case 64:
         case 64:
-          return spvContext.getConstantFloat64(1.0);
+          return spvBuilder.getConstantFloat64(1.0);
         }
         }
       }
       }
     }
     }
@@ -8850,7 +8850,7 @@ SpirvConstant *SPIRVEmitter::getVecValueOne(QualType elemType, uint32_t size) {
 
 
   llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), elemOne);
   llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), elemOne);
   const QualType vecType = astContext.getExtVectorType(elemType, size);
   const QualType vecType = astContext.getExtVectorType(elemType, size);
-  return spvContext.getConstantComposite(vecType, elements);
+  return spvBuilder.getConstantComposite(vecType, elements);
 }
 }
 
 
 SpirvConstant *SPIRVEmitter::getMatElemValueOne(QualType type) {
 SpirvConstant *SPIRVEmitter::getMatElemValueOne(QualType type) {
@@ -8876,13 +8876,13 @@ SpirvConstant *SPIRVEmitter::getMaskForBitwidthValue(QualType type) {
     SpirvConstant *mask = nullptr;
     SpirvConstant *mask = nullptr;
     switch (bitwidth) {
     switch (bitwidth) {
     case 16:
     case 16:
-      mask = spvContext.getConstantUint16(bitwidth - 1);
+      mask = spvBuilder.getConstantUint16(bitwidth - 1);
       break;
       break;
     case 32:
     case 32:
-      mask = spvContext.getConstantUint32(bitwidth - 1);
+      mask = spvBuilder.getConstantUint32(bitwidth - 1);
       break;
       break;
     case 64:
     case 64:
-      mask = spvContext.getConstantUint64(bitwidth - 1);
+      mask = spvBuilder.getConstantUint64(bitwidth - 1);
       break;
       break;
     default:
     default:
       assert(false && "this method only supports 16-, 32-, and 64-bit types");
       assert(false && "this method only supports 16-, 32-, and 64-bit types");
@@ -8893,7 +8893,7 @@ SpirvConstant *SPIRVEmitter::getMaskForBitwidthValue(QualType type) {
 
 
     const QualType resultType = astContext.getExtVectorType(elemType, count);
     const QualType resultType = astContext.getExtVectorType(elemType, count);
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(count), mask);
     llvm::SmallVector<SpirvConstant *, 4> elements(size_t(count), mask);
-    return spvContext.getConstantComposite(resultType, elements);
+    return spvBuilder.getConstantComposite(resultType, elements);
   }
   }
 
 
   assert(false && "this method only supports scalars and vectors");
   assert(false && "this method only supports scalars and vectors");
@@ -8909,7 +8909,7 @@ SpirvConstant *SPIRVEmitter::translateAPValue(const APValue &value,
   TypeTranslator::LiteralTypeHint hint(typeTranslator, targetType);
   TypeTranslator::LiteralTypeHint hint(typeTranslator, targetType);
 
 
   if (targetType->isBooleanType()) {
   if (targetType->isBooleanType()) {
-    result = spvContext.getConstantBool(value.getInt().getBoolValue(),
+    result = spvBuilder.getConstantBool(value.getInt().getBoolValue(),
                                         isSpecConstantMode);
                                         isSpecConstantMode);
   } else if (targetType->isIntegerType()) {
   } else if (targetType->isIntegerType()) {
     result = translateAPInt(value.getInt(), targetType);
     result = translateAPInt(value.getInt(), targetType);
@@ -8927,7 +8927,7 @@ SpirvConstant *SPIRVEmitter::translateAPValue(const APValue &value,
       for (uint32_t i = 0; i < numElements; ++i) {
       for (uint32_t i = 0; i < numElements; ++i) {
         elements.push_back(translateAPValue(value.getVectorElt(i), elemType));
         elements.push_back(translateAPValue(value.getVectorElt(i), elemType));
       }
       }
-      result = spvContext.getConstantComposite(targetType, elements);
+      result = spvBuilder.getConstantComposite(targetType, elements);
     }
     }
   }
   }
 
 
@@ -8948,19 +8948,19 @@ SpirvConstant *SPIRVEmitter::translateAPInt(const llvm::APInt &intValue,
   case 16: {
   case 16: {
     if (spirvOptions.enable16BitTypes) {
     if (spirvOptions.enable16BitTypes) {
       if (isSigned) {
       if (isSigned) {
-        return spvContext.getConstantInt16(
+        return spvBuilder.getConstantInt16(
             static_cast<int16_t>(intValue.getSExtValue()));
             static_cast<int16_t>(intValue.getSExtValue()));
       } else {
       } else {
-        return spvContext.getConstantUint16(
+        return spvBuilder.getConstantUint16(
             static_cast<uint16_t>(intValue.getZExtValue()));
             static_cast<uint16_t>(intValue.getZExtValue()));
       }
       }
     } else {
     } else {
       // If enable16BitTypes option is not true, treat as 32-bit integer.
       // If enable16BitTypes option is not true, treat as 32-bit integer.
       if (isSigned)
       if (isSigned)
-        return spvContext.getConstantInt32(
+        return spvBuilder.getConstantInt32(
             static_cast<int32_t>(intValue.getSExtValue()), isSpecConstantMode);
             static_cast<int32_t>(intValue.getSExtValue()), isSpecConstantMode);
       else
       else
-        return spvContext.getConstantUint32(
+        return spvBuilder.getConstantUint32(
             static_cast<uint32_t>(intValue.getZExtValue()), isSpecConstantMode);
             static_cast<uint32_t>(intValue.getZExtValue()), isSpecConstantMode);
     }
     }
   }
   }
@@ -8973,7 +8973,7 @@ SpirvConstant *SPIRVEmitter::translateAPInt(const llvm::APInt &intValue,
             << std::to_string(intValue.getSExtValue());
             << std::to_string(intValue.getSExtValue());
         return nullptr;
         return nullptr;
       }
       }
-      return spvContext.getConstantInt32(
+      return spvBuilder.getConstantInt32(
           static_cast<int32_t>(intValue.getSExtValue()), isSpecConstantMode);
           static_cast<int32_t>(intValue.getSExtValue()), isSpecConstantMode);
     } else {
     } else {
       if (!intValue.isIntN(32)) {
       if (!intValue.isIntN(32)) {
@@ -8983,15 +8983,15 @@ SpirvConstant *SPIRVEmitter::translateAPInt(const llvm::APInt &intValue,
             << std::to_string(intValue.getZExtValue());
             << std::to_string(intValue.getZExtValue());
         return nullptr;
         return nullptr;
       }
       }
-      return spvContext.getConstantUint32(
+      return spvBuilder.getConstantUint32(
           static_cast<uint32_t>(intValue.getZExtValue()), isSpecConstantMode);
           static_cast<uint32_t>(intValue.getZExtValue()), isSpecConstantMode);
     }
     }
   }
   }
   case 64: {
   case 64: {
     if (isSigned)
     if (isSigned)
-      return spvContext.getConstantInt64(intValue.getSExtValue());
+      return spvBuilder.getConstantInt64(intValue.getSExtValue());
     else
     else
-      return spvContext.getConstantUint64(intValue.getZExtValue());
+      return spvBuilder.getConstantUint64(intValue.getZExtValue());
   }
   }
   }
   }
 
 
@@ -9033,11 +9033,11 @@ bool SPIRVEmitter::isLiteralLargerThan32Bits(const Expr *expr) {
 SpirvConstant *SPIRVEmitter::tryToEvaluateAsInt32(const llvm::APInt &intValue,
 SpirvConstant *SPIRVEmitter::tryToEvaluateAsInt32(const llvm::APInt &intValue,
                                                   bool isSigned) {
                                                   bool isSigned) {
   if (isSigned && intValue.isSignedIntN(32)) {
   if (isSigned && intValue.isSignedIntN(32)) {
-    return spvContext.getConstantInt32(
+    return spvBuilder.getConstantInt32(
         static_cast<int32_t>(intValue.getSExtValue()));
         static_cast<int32_t>(intValue.getSExtValue()));
   }
   }
   if (!isSigned && intValue.isIntN(32)) {
   if (!isSigned && intValue.isIntN(32)) {
-    return spvContext.getConstantUint32(
+    return spvBuilder.getConstantUint32(
         static_cast<uint32_t>(intValue.getZExtValue()));
         static_cast<uint32_t>(intValue.getZExtValue()));
   }
   }
 
 
@@ -9050,7 +9050,7 @@ SPIRVEmitter::tryToEvaluateAsFloat32(const llvm::APFloat &floatValue) {
   const auto &semantics = floatValue.getSemantics();
   const auto &semantics = floatValue.getSemantics();
   // If the given value is already a 32-bit float, there is no need to convert.
   // If the given value is already a 32-bit float, there is no need to convert.
   if (&semantics == &llvm::APFloat::IEEEsingle) {
   if (&semantics == &llvm::APFloat::IEEEsingle) {
-    return spvContext.getConstantFloat32(floatValue.convertToFloat(),
+    return spvBuilder.getConstantFloat32(floatValue.convertToFloat(),
                                          isSpecConstantMode);
                                          isSpecConstantMode);
   }
   }
 
 
@@ -9063,7 +9063,7 @@ SPIRVEmitter::tryToEvaluateAsFloat32(const llvm::APFloat &floatValue) {
       eval.convert(llvm::APFloat::IEEEsingle,
       eval.convert(llvm::APFloat::IEEEsingle,
                    llvm::APFloat::rmNearestTiesToEven, &losesInfo);
                    llvm::APFloat::rmNearestTiesToEven, &losesInfo);
   if (convertStatus == llvm::APFloat::opOK && !losesInfo)
   if (convertStatus == llvm::APFloat::opOK && !losesInfo)
-    return spvContext.getConstantFloat32(eval.convertToFloat());
+    return spvBuilder.getConstantFloat32(eval.convertToFloat());
 
 
   // Couldn't evaluate as a 32-bit float without losing information.
   // Couldn't evaluate as a 32-bit float without losing information.
   return nullptr;
   return nullptr;
@@ -9107,13 +9107,13 @@ SpirvConstant *SPIRVEmitter::translateAPFloat(llvm::APFloat floatValue,
 
 
   switch (targetBitwidth) {
   switch (targetBitwidth) {
   case 16:
   case 16:
-    return spvContext.getConstantFloat16(
+    return spvBuilder.getConstantFloat16(
         static_cast<uint16_t>(floatValue.bitcastToAPInt().getZExtValue()));
         static_cast<uint16_t>(floatValue.bitcastToAPInt().getZExtValue()));
   case 32:
   case 32:
-    return spvContext.getConstantFloat32(floatValue.convertToFloat(),
+    return spvBuilder.getConstantFloat32(floatValue.convertToFloat(),
                                          isSpecConstantMode);
                                          isSpecConstantMode);
   case 64:
   case 64:
-    return spvContext.getConstantFloat64(floatValue.convertToDouble());
+    return spvBuilder.getConstantFloat64(floatValue.convertToDouble());
   default:
   default:
     break;
     break;
   }
   }
@@ -9509,7 +9509,7 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
     // resource objects
     // resource objects
     else if (!hlsl::IsHLSLResourceType(varDecl->getType())) {
     else if (!hlsl::IsHLSLResourceType(varDecl->getType())) {
       const QualType type = varDecl->getType();
       const QualType type = varDecl->getType();
-      auto *nullValue = spvContext.getConstantNull(varDecl->getType());
+      auto *nullValue = spvBuilder.getConstantNull(varDecl->getType());
       spvBuilder.createStore(varInfo, nullValue);
       spvBuilder.createStore(varInfo, nullValue);
     }
     }
   }
   }
@@ -9675,7 +9675,7 @@ bool SPIRVEmitter::processHSEntryPointOutputAndPCF(
   // and we only allow ID 0 to call the PCF.
   // and we only allow ID 0 to call the PCF.
   auto *condition = spvBuilder.createBinaryOp(
   auto *condition = spvBuilder.createBinaryOp(
       spv::Op::OpIEqual, astContext.BoolTy, outputControlPointId,
       spv::Op::OpIEqual, astContext.BoolTy, outputControlPointId,
-      spvContext.getConstantUint32(0));
+      spvBuilder.getConstantUint32(0));
   auto *thenBB = spvBuilder.createBasicBlock("if.true");
   auto *thenBB = spvBuilder.createBasicBlock("if.true");
   auto *mergeBB = spvBuilder.createBasicBlock("if.merge");
   auto *mergeBB = spvBuilder.createBasicBlock("if.merge");
   spvBuilder.createConditionalBranch(condition, thenBB, mergeBB, mergeBB);
   spvBuilder.createConditionalBranch(condition, thenBB, mergeBB, mergeBB);

+ 9 - 1
tools/clang/lib/SPIRV/SpirvBasicBlock.cpp

@@ -21,10 +21,18 @@ bool SpirvBasicBlock::hasTerminator() const {
   return !instructions.empty() && isa<SpirvTerminator>(instructions.back());
   return !instructions.empty() && isa<SpirvTerminator>(instructions.back());
 }
 }
 
 
-bool SpirvBasicBlock::invokeVisitor(Visitor *visitor) {
+bool SpirvBasicBlock::invokeVisitor(Visitor *visitor,
+                                    llvm::ArrayRef<SpirvVariable *> vars) {
   if (!visitor->visit(this, Visitor::Phase::Init))
   if (!visitor->visit(this, Visitor::Phase::Init))
     return false;
     return false;
 
 
+  // If a basic block is the first basic block of a function, it should include
+  // all the variables of the function.
+  if (!vars.empty())
+    for (auto *var : vars)
+      if (!var->invokeVisitor(visitor))
+        return false;
+
   for (auto *inst : instructions)
   for (auto *inst : instructions)
     if (!inst->invokeVisitor(visitor))
     if (!inst->invokeVisitor(visitor))
       return false;
       return false;

+ 186 - 18
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -18,7 +18,10 @@ namespace spirv {
 SpirvBuilder::SpirvBuilder(ASTContext &ac, SpirvContext &ctx,
 SpirvBuilder::SpirvBuilder(ASTContext &ac, SpirvContext &ctx,
                            FeatureManager *fm, const SpirvCodeGenOptions &opt)
                            FeatureManager *fm, const SpirvCodeGenOptions &opt)
     : astContext(ac), context(ctx), module(nullptr), function(nullptr),
     : astContext(ac), context(ctx), module(nullptr), function(nullptr),
-      featureManager(fm), spirvOptions(opt) {
+      featureManager(fm), spirvOptions(opt), compositeConstants({}),
+      integerConstants({}), floatConstants({}), nullConstants({}),
+      boolTrueConstant(nullptr), boolFalseConstant(nullptr),
+      boolTrueSpecConstant(nullptr), boolFalseSpecConstant(nullptr) {
   module = new (context) SpirvModule;
   module = new (context) SpirvModule;
 }
 }
 
 
@@ -41,21 +44,6 @@ SpirvFunction *SpirvBuilder::beginFunction(QualType returnType,
   return function;
   return function;
 }
 }
 
 
-/*
-SpirvFunction *SpirvBuilder::createFunction(QualType returnType,
-                                            const SpirvType *functionType,
-                                            SourceLocation loc,
-                                            llvm::StringRef funcName,
-                                            bool isAlias) {
-  SpirvFunction *fn = new (context)
-      SpirvFunction(returnType, functionType,  0,
-                    spv::FunctionControlMask::MaskNone, loc, funcName);
-  function->setConstainsAliasComponent(isAlias);
-  module->addFunction(function);
-  return function;
-}
-*/
-
 SpirvFunctionParameter *SpirvBuilder::addFnParam(QualType ptrType,
 SpirvFunctionParameter *SpirvBuilder::addFnParam(QualType ptrType,
                                                  SourceLocation loc,
                                                  SourceLocation loc,
                                                  llvm::StringRef name) {
                                                  llvm::StringRef name) {
@@ -989,13 +977,193 @@ void SpirvBuilder::decorateNonUniformEXT(SpirvInstruction *target,
   module->addDecoration(decor);
   module->addDecoration(decor);
 }
 }
 
 
+/*
+SpirvConstant *SpirvBuilder::getConstantUint16(uint16_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantUint16(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantInt16(int16_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantInt16(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantUint32(uint32_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantUint32(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantInt32(int32_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantInt32(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantUint64(uint64_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantUint64(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantInt64(int64_t value, bool specConst) {
+  SpirvConstant *result = context.getConstantInt64(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantFloat16(uint16_t value,
+                                                bool specConst) {
+  SpirvConstant *result = context.getConstantFloat16(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantFloat32(float value, bool specConst) {
+  SpirvConstant *result = context.getConstantFloat32(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantFloat64(double value, bool specConst) {
+  SpirvConstant *result = context.getConstantFloat64(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantBool(bool value, bool specConst) {
+  SpirvConstant *result = context.getConstantBool(value, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *
+SpirvBuilder::getConstantComposite(QualType compositeType,
+                                   llvm::ArrayRef<SpirvConstant *> constituents,
+                                   bool specConst) {
+  SpirvConstant *result =
+      context.getConstantComposite(compositeType, constituents, specConst);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantNull(const SpirvType *type) {
+  SpirvConstant *result = context.getConstantNull(type);
+  module->addConstant(result);
+  return result;
+}
+
+SpirvConstant *SpirvBuilder::getConstantNull(QualType type) {
+  SpirvConstant *result = context.getConstantNull(type);
+  module->addConstant(result);
+  return result;
+}
+*/
+
+SpirvConstant *SpirvBuilder::getConstantUint16(uint16_t value, bool specConst) {
+  return getConstantInt<uint16_t>(value, /*isSigned*/ false, 16, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantInt16(int16_t value, bool specConst) {
+  return getConstantInt<int16_t>(value, /*isSigned*/ true, 16, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantUint32(uint32_t value, bool specConst) {
+  return getConstantInt<uint32_t>(value, /*isSigned*/ false, 32, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantInt32(int32_t value, bool specConst) {
+  return getConstantInt<int32_t>(value, /*isSigned*/ true, 32, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantUint64(uint64_t value, bool specConst) {
+  return getConstantInt<uint64_t>(value, /*isSigned*/ false, 64, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantInt64(int64_t value, bool specConst) {
+  return getConstantInt<int64_t>(value, /*isSigned*/ true, 64, specConst);
+}
+
+SpirvConstant *SpirvBuilder::getConstantFloat16(uint16_t value,
+                                                bool specConst) {
+  return getConstantFloat<uint16_t>(value, 16, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantFloat32(float value, bool specConst) {
+  return getConstantFloat<float>(value, 32, specConst);
+}
+SpirvConstant *SpirvBuilder::getConstantFloat64(double value, bool specConst) {
+  return getConstantFloat<double>(value, 64, specConst);
+}
+
+SpirvConstant *SpirvBuilder::getConstantBool(bool value, bool specConst) {
+  if (value) {
+    if (specConst) {
+      return boolTrueSpecConstant;
+    } else {
+      return boolTrueConstant;
+    }
+  } else {
+    if (specConst) {
+      return boolFalseSpecConstant;
+    } else {
+      return boolFalseConstant;
+    }
+  }
+
+  // Couldn't find the constant. Create one.
+  auto *boolConst = new (context)
+      SpirvConstantBoolean(context.getBoolType(), value, specConst);
+
+  if (value) {
+    if (specConst)
+      boolTrueSpecConstant = boolConst;
+    else
+      boolTrueConstant = boolConst;
+  } else {
+    if (specConst)
+      boolFalseSpecConstant = boolConst;
+    else
+      boolFalseConstant = boolConst;
+  }
+
+  module->addConstant(boolConst);
+  return boolConst;
+}
+
+SpirvConstant *
+SpirvBuilder::getConstantComposite(QualType compositeType,
+                                   llvm::ArrayRef<SpirvConstant *> constituents,
+                                   bool specConst) {
+  SpirvConstantComposite tempConstant(compositeType, constituents, specConst);
+  auto found =
+      std::find_if(compositeConstants.begin(), compositeConstants.end(),
+                   [&tempConstant](SpirvConstantComposite *cachedConstant) {
+                     return tempConstant == *cachedConstant;
+                   });
+
+  if (found != compositeConstants.end())
+    return *found;
+
+  // Couldn't find the constant. Create one.
+  auto *compositeConst = new (context)
+      SpirvConstantComposite(compositeType, constituents, specConst);
+  compositeConstants.push_back(compositeConst);
+  module->addConstant(compositeConst);
+  return compositeConst;
+}
+
+SpirvConstant *SpirvBuilder::getConstantNull(const SpirvType *type) {
+  return getConstantNullOfType<const SpirvType *>(type);
+}
+
+SpirvConstant *SpirvBuilder::getConstantNull(QualType type) {
+  return getConstantNullOfType<QualType>(type);
+}
+
 std::vector<uint32_t> SpirvBuilder::takeModule() {
 std::vector<uint32_t> SpirvBuilder::takeModule() {
   // Run necessary visitor passes first
   // Run necessary visitor passes first
   LowerTypeVisitor lowerTypeVisitor(astContext, context, spirvOptions);
   LowerTypeVisitor lowerTypeVisitor(astContext, context, spirvOptions);
-  EmitVisitor emitVisitor(astContext, context, spirvOptions);
+  EmitVisitor emitVisitor(astContext, context, spirvOptions, *this);
   module->invokeVisitor(&lowerTypeVisitor);
   module->invokeVisitor(&lowerTypeVisitor);
   module->invokeVisitor(&emitVisitor);
   module->invokeVisitor(&emitVisitor);
-  
+
   return emitVisitor.takeBinary();
   return emitVisitor.takeBinary();
 }
 }
 
 

+ 14 - 6
tools/clang/lib/SPIRV/SpirvFunction.cpp

@@ -27,12 +27,20 @@ bool SpirvFunction::invokeVisitor(Visitor *visitor) {
   for (auto *param : parameters)
   for (auto *param : parameters)
     visitor->visit(param);
     visitor->visit(param);
 
 
-  for (auto *var : variables)
-    visitor->visit(var);
-
-  for (auto *bb : basicBlocks)
-    if (!bb->invokeVisitor(visitor))
-      return false;
+  for (auto *bb : basicBlocks) {
+    // The first basic block of the function should first visit the function
+    // variables.
+    if (bb == basicBlocks[0]) {
+      if (!bb->invokeVisitor(visitor, variables))
+        return false;
+    }
+    // The rest of the basic blocks in the function do not need to visit
+    // function variables.
+    else {
+      if (!bb->invokeVisitor(visitor))
+        return false;
+    }
+  }
 
 
   if (!visitor->visit(this, Visitor::Phase::Done))
   if (!visitor->visit(this, Visitor::Phase::Done))
     return false;
     return false;

+ 12 - 2
tools/clang/lib/SPIRV/SpirvModule.cpp

@@ -14,8 +14,10 @@ namespace clang {
 namespace spirv {
 namespace spirv {
 
 
 SpirvModule::SpirvModule()
 SpirvModule::SpirvModule()
-    : bound(1), shaderModelVersion(0), memoryModel(nullptr),
-      debugSource(nullptr) {}
+    : bound(0), shaderModelVersion(0), capabilities({}), extensions({}),
+      extInstSets({}), memoryModel(nullptr), entryPoints({}),
+      executionModes({}), debugSource(nullptr), decorations({}), constants({}),
+      variables({}), functions({}), sourceFileName(""), sourceFileContent("") {}
 
 
 bool SpirvModule::invokeVisitor(Visitor *visitor) {
 bool SpirvModule::invokeVisitor(Visitor *visitor) {
   if (!visitor->visit(this, Visitor::Phase::Init))
   if (!visitor->visit(this, Visitor::Phase::Init))
@@ -129,5 +131,13 @@ void SpirvModule::addDecoration(SpirvDecoration *decor) {
   decorations.push_back(decor);
   decorations.push_back(decor);
 }
 }
 
 
+void SpirvModule::addConstant(SpirvConstant *constant) {
+  assert(constant);
+  if (constants.empty()) {
+    printf("wtf\n");
+  }
+  constants.push_back(constant);
+}
+
 } // end namespace spirv
 } // end namespace spirv
 } // end namespace clang
 } // end namespace clang