Browse Source

Fix crash in code gen caused by cast atomic dst address. (#843)

Xiang Li 7 years ago
parent
commit
fa0674829b

+ 26 - 4
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -6060,16 +6060,38 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(
     const ParmVarDecl *Param = FD->getParamDecl(i);
     const Expr *Arg = E->getArg(i+ArgsToSkip);
     QualType ParamTy = Param->getType().getNonReferenceType();
-
+    bool RValOnRef = false;
     if (!Param->isModifierOut()) {
-      if (!ParamTy->isAggregateType() || hlsl::IsHLSLMatType(ParamTy))
-        continue;
+      if (!ParamTy->isAggregateType() || hlsl::IsHLSLMatType(ParamTy)) {
+        if (Arg->isRValue() && Param->getType()->isReferenceType()) {
+          // RValue on a reference type.
+          if (const CStyleCastExpr *cCast = dyn_cast<CStyleCastExpr>(Arg)) {
+            // TODO: Evolving this to warn then fail in future language versions.
+            // Allow special case like cast uint to uint for back-compat.
+            if (cCast->getCastKind() == CastKind::CK_NoOp) {
+              if (const ImplicitCastExpr *cast =
+                      dyn_cast<ImplicitCastExpr>(cCast->getSubExpr())) {
+                if (cast->getCastKind() == CastKind::CK_LValueToRValue) {
+                  // update the arg
+                  argList[i] = cast->getSubExpr();
+                  continue;
+                }
+              }
+            }
+          }
+          // EmitLValue will report error.
+          // Mark RValOnRef to create tmpArg for it.
+          RValOnRef = true;
+        } else {
+          continue;
+        }
+      }
     }
 
     // get original arg
     LValue argLV = CGF.EmitLValue(Arg);
 
-    if (!Param->isModifierOut()) {
+    if (!Param->isModifierOut() && !RValOnRef) {
       bool isDefaultAddrSpace = true;
       if (argLV.isSimple()) {
         isDefaultAddrSpace =

+ 13 - 0
tools/clang/test/CodeGenHLSL/quick-test/atomic_cast.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
+
+// Make sure NoOp cast on atomic operations compiles.
+// CHECK: main
+
+RWBuffer<uint> buffer;
+
+[numthreads(1,1,1)]
+void main()
+{
+	uint unused;
+	InterlockedOr((uint)buffer[0], 1, unused);
+}

+ 13 - 0
tools/clang/test/CodeGenHLSL/quick-test/atomic_cast1.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
+
+// Make sure cast lvalue not work.
+// CHECK: cannot compile this unexpected cast lvalue
+
+RWBuffer<uint> buffer;
+
+[numthreads(1,1,1)]
+void main()
+{
+	uint unused;
+	InterlockedOr((float)buffer[0], 1, unused);
+}