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

Fix argument translation for C++ member operators (#4916)

Previous to this change if we modified arguments for C++ operator calls
we were sliding the modified parameters in the argument list relative to
where they should have been. This results in mismatched arguments in
calls and all sorts of nastiness.
Chris B 2 жил өмнө
parent
commit
2b67226ddd

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

@@ -5899,7 +5899,8 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(
   llvm::SmallSet<llvm::Value*, 8> ArgVals;
   for (uint32_t i = 0; i < FD->getNumParams(); i++) {
     const ParmVarDecl *Param = FD->getParamDecl(i);
-    const Expr *Arg = E->getArg(i+ArgsToSkip);
+    uint32_t ArgIdx = i+ArgsToSkip;
+    const Expr *Arg = E->getArg(ArgIdx);
     QualType ParamTy = Param->getType().getNonReferenceType();
     bool isObject = dxilutil::IsHLSLObjectType(CGF.ConvertTypeForMem(ParamTy));
     bool bAnnotResource = false;
@@ -5939,7 +5940,7 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(
                       dyn_cast<ImplicitCastExpr>(cCast->getSubExpr())) {
                 if (cast->getCastKind() == CastKind::CK_LValueToRValue) {
                   // update the arg
-                  argList[i] = cast->getSubExpr();
+                  argList[ArgIdx] = cast->getSubExpr();
                   continue;
                 }
               }
@@ -6072,7 +6073,7 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(
         (isAggregateType || isObject) ? VK_RValue : VK_LValue);
 
     // must update the arg, since we did emit Arg, else we get double emit.
-    argList[i] = tmpRef;
+    argList[ArgIdx] = tmpRef;
 
     // create alloc for the tmp arg
     Value *tmpArgAddr = nullptr;

+ 38 - 0
tools/clang/test/HLSLFileCheck/hlsl/functions/arguments/copyin-copyout-operators.hlsl

@@ -0,0 +1,38 @@
+// RUN: %dxc -T lib_6_4 -fcgl -HV 2021 %s | FileCheck %s
+
+struct Doggo {
+void operator()(inout float X, inout int Y, inout float Z) {
+  X = 1.0;
+  Y = 2;
+  Z = 3.0;
+}
+};
+
+void fn() {
+  float X, Z = 0.0;
+  int Y = 0;
+  Doggo D;
+  D(X, Y, Z);
+
+  D(X, Y, X);
+}
+
+// CHECK: define internal void @"\01?fn@@YAXXZ"()
+// CHECK: [[Tmp1:%[0-9A-Z]+]] = alloca float
+// CHECK: [[X:%[0-9A-Z]+]] = alloca float, align 4
+// CHECK: [[Z:%[0-9A-Z]+]] = alloca float, align 4
+// CHECK: [[Y:%[0-9A-Z]+]] = alloca i32, align 4
+// CHECK: [[D:%[0-9A-Z]+]] = alloca %struct.Doggo
+
+// First call has no copy-in/copy out parameters since all parameters are unique.
+// CHECK: call void @"\01??RDoggo@@QAAXAIAMAIAH0@Z"(%struct.Doggo* [[D]], float* dereferenceable(4) [[X]], i32* dereferenceable(4) [[Y]], float* dereferenceable(4) [[Z]])
+
+// The second call copies X for the third parameter.
+// CHECK: [[TmpX:%[0-9A-Z]+]] = load float, float* [[X]], align 4
+// CHECK: store float [[TmpX]], float* [[Tmp1]]
+
+// CHECK: call void @"\01??RDoggo@@QAAXAIAMAIAH0@Z"(%struct.Doggo* [[D]], float* dereferenceable(4) [[X]], i32* dereferenceable(4) [[Y]], float* dereferenceable(4) [[Tmp1]])
+
+// The third call stores parameter 3 to X after the call.
+// CHECK: [[TmpX:%[0-9A-Z]+]] = load float, float* [[Tmp1]]
+// CHECK: store float [[TmpX]], float* [[X]]