2
0
Эх сурвалжийг харах

[spirv] support sizeof() (#3080)

* [spirv] support sizeof()

* Code review
Jaebaek Seo 5 жил өмнө
parent
commit
0fb58c61ad

+ 1 - 0
tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

@@ -253,6 +253,7 @@ const SpirvType *LowerTypeVisitor::lowerType(QualType type,
         case BuiltinType::Int:
           return spvContext.getSIntType(32);
         case BuiltinType::UInt:
+        case BuiltinType::ULong:
           return spvContext.getUIntType(32);
 
           // void and bool

+ 22 - 0
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -760,6 +760,8 @@ SpirvInstruction *SpirvEmitter::doExpr(const Expr *expr) {
     result = curThis;
   } else if (isa<CXXConstructExpr>(expr)) {
     result = curThis;
+  } else if (const auto *unaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(expr)) {
+    result = doUnaryExprOrTypeTraitExpr(unaryExpr);
   } else {
     emitError("expression class '%0' unimplemented", expr->getExprLoc())
         << expr->getStmtClassName() << expr->getSourceRange();
@@ -11675,5 +11677,25 @@ bool SpirvEmitter::spirvToolsLegalize(std::vector<uint32_t> *mod,
   return optimizer.Run(mod->data(), mod->size(), mod, options);
 }
 
+SpirvInstruction *
+SpirvEmitter::doUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *expr) {
+  // TODO: We support only `sizeof()`. Support other kinds.
+  if (expr->getKind() != clang::UnaryExprOrTypeTrait::UETT_SizeOf) {
+    emitError("expression class '%0' unimplemented", expr->getExprLoc())
+        << expr->getStmtClassName();
+    return nullptr;
+  }
+
+  AlignmentSizeCalculator alignmentCalc(astContext, spirvOptions);
+  uint32_t size = 0, stride = 0;
+  std::tie(std::ignore, size) = alignmentCalc.getAlignmentAndSize(
+      expr->getArgumentType(), SpirvLayoutRule::Void,
+      /*isRowMajor*/ llvm::None, &stride);
+  auto *sizeConst = spvBuilder.getConstantInt(astContext.UnsignedIntTy,
+                                              llvm::APInt(32, size));
+  sizeConst->setRValue();
+  return sizeConst;
+}
+
 } // end namespace spirv
 } // end namespace clang

+ 2 - 0
tools/clang/lib/SPIRV/SpirvEmitter.h

@@ -106,6 +106,8 @@ private:
   SpirvInstruction *doInitListExpr(const InitListExpr *expr);
   SpirvInstruction *doMemberExpr(const MemberExpr *expr);
   SpirvInstruction *doUnaryOperator(const UnaryOperator *expr);
+  SpirvInstruction *
+  doUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *expr);
 
   /// Overload with pre computed SpirvEvalInfo.
   ///

+ 61 - 0
tools/clang/test/CodeGenSPIRV/unary-op.sizeof.hlsl

@@ -0,0 +1,61 @@
+// Run: %dxc -T ps_6_2 -E main -HV 2018 -enable-16bit-types
+
+struct PSInput
+{
+  int4 color : COLOR;
+};
+ByteAddressBuffer g_meshData[] : register(t0, space3);
+
+struct EmptyStruct {};
+struct SimpleStruct { int x; };
+
+int3 main(PSInput input) : SV_TARGET
+{
+  int foo;
+
+// CHECK: OpStore %foo %int_4
+  foo = sizeof(int);
+// CHECK: OpStore %foo %int_4
+  foo = sizeof((int)0);
+// CHECK: OpStore %foo %int_4
+  foo = sizeof(int);
+// CHECK: OpStore %foo %int_8
+  foo = sizeof(int2);
+// CHECK: OpStore %foo %int_16
+  foo = sizeof(int2x2);
+// CHECK: OpStore %foo %int_8
+  foo = sizeof(int[2]);
+// CHECK: OpStore %foo %int_4
+  foo = sizeof(SimpleStruct);
+// CHECK: OpStore %foo %int_0
+  foo = sizeof(EmptyStruct);
+// CHECK: OpStore %foo %int_12
+  foo = sizeof(int16_t3[2]);
+// CHECK: OpStore %foo %int_12
+  foo = sizeof(half3[2]);
+// CHECK: OpStore %foo %int_24
+  foo = sizeof(int3[2]);
+// CHECK: OpStore %foo %int_24
+  foo = sizeof(float3[2]);
+// CHECK: OpStore %foo %int_24
+  foo = sizeof(bool3[2]);
+// CHECK: OpStore %foo %int_48
+  foo = sizeof(int64_t3[2]);
+// CHECK: OpStore %foo %int_48
+  foo = sizeof(double3[2]);
+// CHECK: OpStore %foo %int_0
+  foo = sizeof(EmptyStruct[2]);
+
+  struct
+  {
+    int16_t i16;
+    // 2-byte padding
+    struct { float f32; } s; // Nested type
+    struct {} _; // Zero-sized field.
+  } complexStruct;
+// CHECK: OpStore %foo %int_8
+  foo = sizeof(complexStruct);
+
+// CHECK: OpIMul %uint {{%\d+}} %uint_12
+  return g_meshData[input.color.x].Load3(input.color.y * sizeof(float3));
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -243,6 +243,9 @@ TEST_F(FileTest, UnaryOpLogicalNot) {
   runFileTest("unary-op.logical-not.hlsl");
 }
 
+// For sizeof()
+TEST_F(FileTest, UnaryOpSizeof) { runFileTest("unary-op.sizeof.hlsl"); }
+
 // For assignments
 TEST_F(FileTest, BinaryOpAssign) { runFileTest("binary-op.assign.hlsl"); }
 TEST_F(FileTest, BinaryOpAssignImage) {