瀏覽代碼

[dxil2spv] Translate DXIL constants to SPIR-V (#4426)

Add intial handling of DXIL float constants, translating to SPIR-V float
constant instructions. Emit errors for other constant types not yet
handled.
Natalie Chouinard 3 年之前
父節點
當前提交
f00b3c285d

+ 2 - 0
tools/clang/include/clang/SPIRV/SpirvBuilder.h

@@ -745,6 +745,8 @@ public:
                                 bool specConst = false);
   SpirvConstant *getConstantFloat(QualType type, llvm::APFloat value,
                                   bool specConst = false);
+  SpirvConstant *getConstantFloat(const SpirvType *type, llvm::APFloat value,
+                                  bool specConst = false);
   SpirvConstant *getConstantBool(bool value, bool specConst = false);
   SpirvConstant *
   getConstantComposite(QualType compositeType,

+ 2 - 0
tools/clang/include/clang/SPIRV/SpirvInstruction.h

@@ -1181,6 +1181,8 @@ class SpirvConstantFloat : public SpirvConstant {
 public:
   SpirvConstantFloat(QualType type, llvm::APFloat value,
                      bool isSpecConst = false);
+  SpirvConstantFloat(const SpirvType *type, llvm::APFloat value,
+                     bool isSpecConst = false);
 
   DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvConstantFloat)
 

+ 9 - 0
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -1673,6 +1673,15 @@ SpirvConstant *SpirvBuilder::getConstantFloat(QualType type,
   return floatConst;
 }
 
+SpirvConstant *SpirvBuilder::getConstantFloat(const SpirvType *type,
+                                              llvm::APFloat value,
+                                              bool specConst) {
+  // We do not reuse existing constant floats. Just create a new one.
+  auto *floatConst = new (context) SpirvConstantFloat(type, value, specConst);
+  mod->addConstant(floatConst);
+  return floatConst;
+}
+
 SpirvConstant *SpirvBuilder::getConstantBool(bool value, bool specConst) {
   // We do not care about making unique constants at this point.
   auto *boolConst =

+ 9 - 0
tools/clang/lib/SPIRV/SpirvInstruction.cpp

@@ -572,6 +572,15 @@ SpirvConstantFloat::SpirvConstantFloat(QualType type, llvm::APFloat val,
   assert(type->isFloatingType());
 }
 
+SpirvConstantFloat::SpirvConstantFloat(const SpirvType *type, llvm::APFloat val,
+                                       bool isSpecConst)
+    : SpirvConstant(IK_ConstantFloat,
+                    isSpecConst ? spv::Op::OpSpecConstant : spv::Op::OpConstant,
+                    type),
+      value(val) {
+  assert(isa<FloatType>(type));
+}
+
 bool SpirvConstantFloat::operator==(const SpirvConstantFloat &that) const {
   return resultType == that.resultType && astResultType == that.astResultType &&
          value.bitwiseIsEqual(that.value) && opcode == that.opcode;

+ 23 - 5
tools/clang/tools/dxil2spv/lib/dxil2spv.cpp

@@ -25,6 +25,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MemoryBuffer.h"
 
@@ -735,13 +736,30 @@ const spirv::SpirvType *Translator::toSpirvType(llvm::StructType *structType) {
 
 spirv::SpirvInstruction *
 Translator::getSpirvInstruction(llvm::Value *instruction) {
-  spirv::SpirvInstruction *spirvInstruction = instructionMap[instruction];
-  if (!spirvInstruction) {
-    emitError("Expected SPIR-V instruction not found for DXIL instruction: %0",
-              *instruction);
+  if (!instruction) {
+    emitError("Unexpected null DXIL instruction");
     return nullptr;
   }
-  return spirvInstruction;
+
+  if (spirv::SpirvInstruction *spirvInstruction = instructionMap[instruction])
+    return spirvInstruction;
+
+  if (auto *constant = llvm::dyn_cast<llvm::Constant>(instruction))
+    return createSpirvConstant(constant);
+
+  emitError("Expected SPIR-V instruction not found for DXIL instruction: %0",
+            *instruction);
+  return nullptr;
+}
+
+spirv::SpirvInstruction *
+Translator::createSpirvConstant(llvm::Constant *instruction) {
+  if (auto *fp = llvm::dyn_cast<llvm::ConstantFP>(instruction))
+    return spvBuilder.getConstantFloat(spvContext.getFloatType(32),
+                                       fp->getValueAPF());
+
+  emitError("Unhandled LLVM constant instruction: %0", *instruction);
+  return nullptr;
 }
 
 template <unsigned N>

+ 4 - 0
tools/clang/tools/dxil2spv/lib/dxil2spv.h

@@ -58,6 +58,10 @@ private:
   // error checking.
   spirv::SpirvInstruction *getSpirvInstruction(llvm::Value *instruction);
 
+  // Create corresponding SPIR-V constant for a given DXIL instruction, with
+  // error checking.
+  spirv::SpirvInstruction *createSpirvConstant(llvm::Constant *instruction);
+
   // Create SPIR-V stage IO variable from DXIL input and output signatures.
   void createStageIOVariables(
       const std::vector<std::unique_ptr<hlsl::DxilSignatureElement>>