Просмотр исходного кода

Strip function parameter for entry and patch constant function. (#20)

Strip function parameter for entry and patch constant function

* Update error message for ValidationTest::MultiDimArray

* Merge remote-tracking branch 'origin/master'

# Conflicts:
#	lib/HLSL/DxilValidation.cpp
#	tools/clang/unittests/HLSL/ValidationTest.cpp

* Update error message for ValidationTest::MultiDimArray

Update error message for ValidationTest::MultiDimArray

* Fix merge error. (#3)

* Delete local file (#4)

* Fix merge error.

* Delete local file

* Strip function parameter for entry and patch constant function. (#5)
Xiang Li 8 лет назад
Родитель
Сommit
5623234187

+ 1 - 1
docs/DXIL.rst

@@ -2124,7 +2124,7 @@ DECL.NOTUSEDEXTERNAL                  External declaration should not be used
 DECL.USEDEXTERNALFUNCTION             External function must be used
 DECL.USEDINTERNAL                     Internal declaration must be used
 FLOW.DEADLOOP                         Loop must have break
-FLOW.FUNCTIONCALL                     Function call on user defined function with parameter is not permitted
+FLOW.FUNCTIONCALL                     Function with parameter is not permitted
 FLOW.NORECUSION                       Recursion is not permitted
 FLOW.REDUCIBLE                        Execution flow must be reducible
 INSTR.ALLOWED                         Instructions must be of an allowed type

+ 1 - 1
include/dxc/HLSL/DxilValidation.h

@@ -147,7 +147,7 @@ enum class ValidationRule : unsigned {
 
   // Program flow
   FlowDeadLoop, // Loop must have break
-  FlowFunctionCall, // Function call on user defined function with parameter is not permitted
+  FlowFunctionCall, // Function with parameter is not permitted
   FlowNoRecusion, // Recursion is not permitted
   FlowReducible, // Execution flow must be reducible
 

+ 53 - 2
lib/HLSL/DxilGenerationPass.cpp

@@ -2496,6 +2496,39 @@ INITIALIZE_PASS(HLEnsureMetadata, "hlsl-hlensure", "HLSL High-Level Metadata Ens
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace {
+
+Function *StripFunctionParameter(Function *F, DxilModule &DM,
+    DenseMap<const Function *, DISubprogram *> &FunctionDIs) {
+  Module &M = *DM.GetModule();
+  Type *VoidTy = Type::getVoidTy(M.getContext());
+  FunctionType *FT = FunctionType::get(VoidTy, false);
+  for (auto &arg : F->args()) {
+    if (!arg.user_empty())
+      return nullptr;
+  }
+
+  Function *NewFunc = Function::Create(FT, F->getLinkage(), F->getName());
+  M.getFunctionList().insert(F, NewFunc);
+  // Splice the body of the old function right into the new function.
+  NewFunc->getBasicBlockList().splice(NewFunc->begin(), F->getBasicBlockList());
+
+  // Patch the pointer to LLVM function in debug info descriptor.
+  auto DI = FunctionDIs.find(F);
+  if (DI != FunctionDIs.end()) {
+    DISubprogram *SP = DI->second;
+    SP->replaceFunction(NewFunc);
+    // Ensure the map is updated so it can be reused on subsequent argument
+    // promotions of the same function.
+    FunctionDIs.erase(DI);
+    FunctionDIs[NewFunc] = SP;
+  }
+  NewFunc->takeName(F);
+  DM.GetTypeSystem().EraseFunctionAnnotation(F);
+  F->eraseFromParent();
+  DM.GetTypeSystem().AddFunctionAnnotation(NewFunc);
+  return NewFunc;
+}
+
 class DxilEmitMetadata : public ModulePass {
 public:
   static char ID; // Pass identification, replacement for typeid
@@ -2586,8 +2619,26 @@ public:
         }
       }
 
-      M.GetDxilModule().CollectShaderFlags(); // Update flags to reflect any changes.
-      M.GetDxilModule().EmitDxilMetadata();
+      DxilModule &DM = M.GetDxilModule();
+      DenseMap<const Function *, DISubprogram *> FunctionDIs =
+          makeSubprogramMap(M);
+      if (Function *PatchConstantFunc = DM.GetPatchConstantFunction()) {
+        PatchConstantFunc =
+            StripFunctionParameter(PatchConstantFunc, DM, FunctionDIs);
+        if (PatchConstantFunc)
+          DM.SetPatchConstantFunction(PatchConstantFunc);
+      }
+
+      if (Function *EntryFunc = DM.GetEntryFunction()) {
+        StringRef Name = DM.GetEntryFunctionName();
+        EntryFunc->setName(Name);
+        EntryFunc = StripFunctionParameter(EntryFunc, DM, FunctionDIs);
+        if (EntryFunc)
+          DM.SetEntryFunction(EntryFunc);
+      }
+
+      DM.CollectShaderFlags(); // Update flags to reflect any changes.
+      DM.EmitDxilMetadata();
       return true;
     }
 

+ 4 - 7
lib/HLSL/DxilValidation.cpp

@@ -216,7 +216,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::FlowReducible: return "Execution flow must be reducible";
     case hlsl::ValidationRule::FlowNoRecusion: return "Recursion is not permitted";
     case hlsl::ValidationRule::FlowDeadLoop: return "Loop must have break";
-    case hlsl::ValidationRule::FlowFunctionCall: return "Function call on user defined function with parameter %0 is not permitted, it should be inlined";
+    case hlsl::ValidationRule::FlowFunctionCall: return "Function %0 with parameter is not permitted, it should be inlined";
     case hlsl::ValidationRule::DeclDxilNsReserved: return "Declaration '%0' uses a reserved prefix";
     case hlsl::ValidationRule::DeclDxilFnExtern: return "External function '%0' is not a DXIL function";
     case hlsl::ValidationRule::DeclUsedInternal: return "Internal declaration '%0' is unused";
@@ -2529,12 +2529,9 @@ static void ValidateFunction(Function &F, ValidationContext &ValCtx) {
   if (F.isDeclaration()) {
     ValidateExternalFunction(&F, ValCtx);
   } else {
-    if (&F != ValCtx.DxilMod.GetEntryFunction() &&
-        &F != ValCtx.DxilMod.GetPatchConstantFunction()) {
-      if (!F.arg_empty())
-        ValCtx.EmitFormatError(ValidationRule::FlowFunctionCall,
-                               {F.getName().str().c_str()});
-    }
+    if (!F.arg_empty())
+      ValCtx.EmitFormatError(ValidationRule::FlowFunctionCall,
+                             {F.getName().str().c_str()});
 
     DxilFunctionAnnotation *funcAnnotation =
         ValCtx.DxilMod.GetTypeSystem().GetFunctionAnnotation(&F);

+ 13 - 25
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -4133,35 +4133,23 @@ void SROA_Parameter_HLSL::flattenArgument(
 void SROA_Parameter_HLSL::moveFunctionBody(Function *F, Function *flatF) {
   bool updateRetType = F->getReturnType() != flatF->getReturnType();
 
-  // Clone blocks and move instructions.
-  std::unordered_map<Value *, Value *> VMap;
-  Function::BasicBlockListType &blockList = F->getBasicBlockList();
-  for (BasicBlock &BB : blockList) {
-    BasicBlock *NewBB = BasicBlock::Create(BB.getContext(), "", flatF);
-    if (BB.hasName()) NewBB->setName(BB.getName());
-    // Add basic block mapping.
-    VMap[&BB] = NewBB;
-    // Update block uses.
-    BB.replaceAllUsesWith(NewBB);
-    // Move intrinsictions to NewBB.
-    NewBB->getInstList().splice(NewBB->begin(), BB.getInstList());
-  }
+  // Splice the body of the old function right into the new function.
+  flatF->getBasicBlockList().splice(flatF->begin(), F->getBasicBlockList());
+
   // Update Block uses.
-  for (BasicBlock &BB : blockList) {
-    BasicBlock *NewBB = cast<BasicBlock>(VMap[&BB]);
-    if (updateRetType) {
-      // Replace ret with ret void.
-      if (ReturnInst *RI = dyn_cast<ReturnInst>(NewBB->getTerminator())) {
-        // Create store for return.
-        IRBuilder<> Builder(RI);
-        Builder.CreateRetVoid();
-        RI->eraseFromParent();
+  if (updateRetType) {
+    for (BasicBlock &BB : flatF->getBasicBlockList()) {
+      if (updateRetType) {
+        // Replace ret with ret void.
+        if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
+          // Create store for return.
+          IRBuilder<> Builder(RI);
+          Builder.CreateRetVoid();
+          RI->eraseFromParent();
+        }
       }
     }
   }
-
-  // Cleanup the original function.
-  F->getBasicBlockList().clear();  
 }
 
 static void SplitArrayCopy(Value *V) {

+ 1 - 1
tools/clang/test/CodeGenHLSL/recursive.hlsl

@@ -1,7 +1,7 @@
 // RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
 
 // CHECK: Recursion is not permitted
-// CHECK: Function call on user defined function
+// CHECK: with parameter is not permitted
 
 void test_inout(inout float4 m, float4 a) 
 {

+ 1 - 1
tools/clang/unittests/HLSL/ExtensionTest.cpp

@@ -455,7 +455,7 @@ TEST_F(ExtensionTest, IntrinsicWhenAvailableThenUsed) {
   // - second argument is float, ie it got scalarized
   VERIFY_IS_TRUE(
     disassembly.npos !=
-    disassembly.find("call void @\"test.\\01?test_proc@hlsl@@YAXV?$vector@M$01@@@Z.r\"(i32 2, float %6)"));
+    disassembly.find("call void @\"test.\\01?test_proc@hlsl@@YAXV?$vector@M$01@@@Z.r\"(i32 2, float"));
   VERIFY_IS_TRUE(
     disassembly.npos !=
     disassembly.find("call float @\"test.\\01?test_fn@hlsl@@YA?AV?$vector@M$01@@V2@@Z.r\"(i32 1, float"));

+ 79 - 62
tools/clang/unittests/HLSL/ValidationTest.cpp

@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Regex.h"
+#include "llvm/ADT/ArrayRef.h"
 
 #include <atlbase.h>
 
@@ -120,6 +121,7 @@ public:
   TEST_METHOD(MinPrecisionBitCast)
   TEST_METHOD(StructBitCast)
   TEST_METHOD(MultiDimArray)
+  TEST_METHOD(NoFunctionParam)
 
   TEST_METHOD(ClipCullMaxComponents)
   TEST_METHOD(ClipCullMaxRows)
@@ -281,7 +283,7 @@ public:
   }
 
   void RewriteAssemblyCheckMsg(LPCSTR pSource, LPCSTR pShaderModel,
-                               LPCSTR pLookFor, LPCSTR pReplacement,
+                               llvm::ArrayRef<LPCSTR> pLookFors, llvm::ArrayRef<LPCSTR> pReplacements,
                                LPCSTR pErrorMsg, bool bRegex = false) {
     CComPtr<IDxcBlob> pText;
     CComPtr<IDxcBlobEncoding> pSourceBlob;
@@ -292,7 +294,7 @@ public:
 
     Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
 
-    RewriteAssemblyToText(pSourceBlob, pShaderModel, pLookFor, pReplacement, &pText, bRegex);
+    RewriteAssemblyToText(pSourceBlob, pShaderModel, pLookFors, pReplacements, &pText, bRegex);
 
     CComPtr<IDxcAssembler> pAssembler;
     CComPtr<IDxcOperationResult> pAssembleResult;
@@ -309,42 +311,46 @@ public:
   }
 
   void RewriteAssemblyToText(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
-                             LPCSTR pLookFor, LPCSTR pReplacement,
+                             llvm::ArrayRef<LPCSTR> pLookFors, llvm::ArrayRef<LPCSTR> pReplacements,
                              IDxcBlob **pBlob, bool bRegex = false) {
     CComPtr<IDxcBlob> pProgram;
     std::string disassembly;
     CompileSource(pSource, pShaderModel, &pProgram);
     DisassembleProgram(pProgram, &disassembly);
-    if (pLookFor && *pLookFor) {
-      if (bRegex) {
-        llvm::Regex RE(pLookFor);
-        std::string reErrors;
-        VERIFY_IS_TRUE(RE.isValid(reErrors));
-        std::string replaced = RE.sub(pReplacement, disassembly, &reErrors);
-        VERIFY_ARE_NOT_EQUAL(disassembly, replaced);
-        VERIFY_IS_TRUE(reErrors.empty());
-        disassembly = std::move(replaced);
-      } else {
-        bool found = false;
-        size_t pos = 0;
-        size_t lookForLen = strlen(pLookFor);
-        size_t replaceLen = strlen(pReplacement);
-        for (;;) {
-          pos = disassembly.find(pLookFor, pos);
-          if (pos == std::string::npos)
-            break;
-          found = true; // at least once
-          disassembly.replace(pos, lookForLen, pReplacement);
-          pos += replaceLen;
+    for (unsigned i = 0; i < pLookFors.size(); ++i) {
+      LPCSTR pLookFor = pLookFors[i];
+      LPCSTR pReplacement = pReplacements[i];
+      if (pLookFor && *pLookFor) {
+        if (bRegex) {
+          llvm::Regex RE(pLookFor);
+          std::string reErrors;
+          VERIFY_IS_TRUE(RE.isValid(reErrors));
+          std::string replaced = RE.sub(pReplacement, disassembly, &reErrors);
+          VERIFY_ARE_NOT_EQUAL(disassembly, replaced);
+          VERIFY_IS_TRUE(reErrors.empty());
+          disassembly = std::move(replaced);
+        } else {
+          bool found = false;
+          size_t pos = 0;
+          size_t lookForLen = strlen(pLookFor);
+          size_t replaceLen = strlen(pReplacement);
+          for (;;) {
+            pos = disassembly.find(pLookFor, pos);
+            if (pos == std::string::npos)
+              break;
+            found = true; // at least once
+            disassembly.replace(pos, lookForLen, pReplacement);
+            pos += replaceLen;
+          }
+          VERIFY_IS_TRUE(found);
         }
-        VERIFY_IS_TRUE(found);
       }
     }
     Utf8ToBlob(m_dllSupport, disassembly.c_str(), pBlob);
   }
   
   void RewriteAssemblyCheckMsg(LPCWSTR name, LPCSTR pShaderModel,
-                               LPCSTR pLookFor, LPCSTR pReplacement,
+                               llvm::ArrayRef<LPCSTR> pLookFors, llvm::ArrayRef<LPCSTR> pReplacements,
                                LPCSTR pErrorMsg, bool bRegex = false) {
     std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
     CComPtr<IDxcLibrary> pLibrary;
@@ -358,7 +364,7 @@ public:
 
     CComPtr<IDxcBlob> pText;
 
-    RewriteAssemblyToText(pSource, pShaderModel, pLookFor, pReplacement, &pText);
+    RewriteAssemblyToText(pSource, pShaderModel, pLookFors, pReplacements, &pText);
 
     CComPtr<IDxcAssembler> pAssembler;
     CComPtr<IDxcOperationResult> pAssembleResult;
@@ -553,7 +559,8 @@ TEST_F(ValidationTest, WhenIncorrectPSThenFail) {
 
 TEST_F(ValidationTest, WhenSmUnknownThenFail) {
   RewriteAssemblyCheckMsg("float4 main() : SV_Target { return 1; }", "ps_6_0",
-                          "{!\"ps\", i32 6, i32 0}", "{!\"ps\", i32 1, i32 2}",
+                          {"{!\"ps\", i32 6, i32 0}"},
+                          {"{!\"ps\", i32 1, i32 2}"},
                           "Unknown shader model 'ps_1_2'");
 }
 
@@ -857,15 +864,15 @@ TEST_F(ValidationTest, PsOutputSemantic) {
 TEST_F(ValidationTest, ArrayOfSVTarget) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_6_0",
-      "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 1",
-      "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 2",
+      "i32 6, !\"SV_Target\", i8 9, i8 16, !32, i8 0, i32 1",
+      "i32 6, !\"SV_Target\", i8 9, i8 16, !32, i8 0, i32 2",
       "Pixel shader output registers are not indexable.");
 }
 
 TEST_F(ValidationTest, InfiniteLog) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "op.unary.f32(i32 22, float %3)",
+      "op.unary.f32(i32 22, float %1)",
       "op.unary.f32(i32 22, float 0x7FF0000000000000)",
       "No indefinite logarithm");
 }
@@ -873,7 +880,7 @@ TEST_F(ValidationTest, InfiniteLog) {
 TEST_F(ValidationTest, InfiniteAsin) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "op.unary.f32(i32 16, float %3)",
+      "op.unary.f32(i32 16, float %1)",
       "op.unary.f32(i32 16, float 0x7FF0000000000000)",
       "No indefinite arcsine");
 }
@@ -881,7 +888,7 @@ TEST_F(ValidationTest, InfiniteAsin) {
 TEST_F(ValidationTest, InfiniteAcos) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "op.unary.f32(i32 15, float %3)",
+      "op.unary.f32(i32 15, float %1)",
       "op.unary.f32(i32 15, float 0x7FF0000000000000)",
       "No indefinite arccosine");
 }
@@ -889,7 +896,7 @@ TEST_F(ValidationTest, InfiniteAcos) {
 TEST_F(ValidationTest, InfiniteDdxDdy) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "op.unary.f32(i32 86, float %3)",
+      "op.unary.f32(i32 86, float %1)",
       "op.unary.f32(i32 86, float 0x7FF0000000000000)",
       "No indefinite derivative calculation");
 }
@@ -897,16 +904,16 @@ TEST_F(ValidationTest, InfiniteDdxDdy) {
 TEST_F(ValidationTest, IDivByZero) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "sdiv i32 %8, %9",
-      "sdiv i32 %8, 0",
+      "sdiv i32 %6, %7",
+      "sdiv i32 %6, 0",
       "No signed integer division by zero");
 }
 
 TEST_F(ValidationTest, UDivByZero) {
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_6_0",
-      "udiv i32 %5, %6",
-      "udiv i32 %5, 0",
+      "udiv i32 %3, %4",
+      "udiv i32 %3, 0",
       "No unsigned integer division by zero");
 }
 
@@ -919,59 +926,66 @@ TEST_F(ValidationTest, UnusedMetadata) {
 
 TEST_F(ValidationTest, MemoryOutOfBound) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_6_0",
-                          "getelementptr [4 x float], [4 x float]* %12, i32 0, i32 3",
-                          "getelementptr [4 x float], [4 x float]* %12, i32 0, i32 10",
+                          "getelementptr [4 x float], [4 x float]* %7, i32 0, i32 3",
+                          "getelementptr [4 x float], [4 x float]* %7, i32 0, i32 10",
                           "Access to out-of-bounds memory is disallowed");
 }
 
 TEST_F(ValidationTest, AddrSpaceCast) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\staticGlobals.hlsl", "ps_6_0",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  store float %11, float* %12, align 4",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  %X = addrspacecast float* %12 to float addrspace(1)*    \n"
-                          "  store float %11, float addrspace(1)* %X, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  store float %10, float* %11, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  %X = addrspacecast float* %11 to float addrspace(1)*    \n"
+                          "  store float %10, float addrspace(1)* %X, align 4",
                           "generic address space");
 }
 
 TEST_F(ValidationTest, PtrBitCast) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\staticGlobals.hlsl", "ps_6_0",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  store float %11, float* %12, align 4",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  %X = bitcast float* %12 to double*    \n"
-                          "  store float %11, float* %12, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  store float %10, float* %11, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  %X = bitcast float* %11 to double*    \n"
+                          "  store float %10, float* %11, align 4",
                           "Pointer type bitcast must be have same size");
 }
 
 TEST_F(ValidationTest, MinPrecisionBitCast) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\staticGlobals.hlsl", "ps_6_0",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  store float %11, float* %12, align 4",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  %X = bitcast float* %12 to [2 x half]*    \n"
-                          "  store float %11, float* %12, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  store float %10, float* %11, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  %X = bitcast float* %11 to [2 x half]*    \n"
+                          "  store float %10, float* %11, align 4",
                           "Bitcast on minprecison types is not allowed");
 }
 
 TEST_F(ValidationTest, StructBitCast) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\staticGlobals.hlsl", "ps_6_0",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  store float %11, float* %12, align 4",
-                          "%12 = getelementptr [4 x float], [4 x float]* %1, i32 0, i32 0\n"
-                          "  %X = bitcast float* %12 to %dx.types.Handle*    \n"
-                          "  store float %11, float* %12, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  store float %10, float* %11, align 4",
+                          "%11 = getelementptr [4 x float], [4 x float]* %0, i32 0, i32 0\n"
+                          "  %X = bitcast float* %11 to %dx.types.Handle*    \n"
+                          "  store float %10, float* %11, align 4",
                           "Bitcast on struct types is not allowed");
 }
 
 TEST_F(ValidationTest, MultiDimArray) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\staticGlobals.hlsl", "ps_6_0",
-                          "%1 = alloca [4 x float]",
-                          "%1 = alloca [4 x float]\n"
+                          "%0 = alloca [4 x float]",
+                          "%0 = alloca [4 x float]\n"
                           "  %md = alloca [2 x [4 x float]]",
                           "Only one dimension allowed for array type");
 }
 
+TEST_F(ValidationTest, NoFunctionParam) {
+  RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\abs2.hlsl", "ps_6_0",
+                          {"define void @main()", "void ()* @main", "!5 = !{!6}"},
+                          {"define void @main(<4 x i32> %mainArg)", "void (<4 x i32>)* @main", "!5 = !{!6, !6}"},
+                          "with parameter is not permitted");
+}
+
 TEST_F(ValidationTest, WhenWaveAffectsGradientThenFail) {
   TestCheck(L"val-wave-failures-ps.hlsl");
 }
@@ -1630,9 +1644,11 @@ void main( \
     "vs_6_0",
 
     "!{i32 1, !\"Array\", i8 5, i8 0, !([0-9]+), i8 1, i32 2, i8 1, i32 1, i8 0, null}\n"
+    "!17 = !{i32 0, i32 1}\n"
     "!([0-9]+) = !{i32 2, !\"Value\", i8 5, i8 0, !([0-9]+), i8 1, i32 1, i8 3, i32 1, i8 1, null}",
 
     "!{i32 1, !\"Array\", i8 5, i8 0, !\\1, i8 1, i32 2, i8 1, i32 1, i8 1, null}\n"
+    "!17 = !{i32 0, i32 1}\n"
     "!\\2 = !{i32 2, !\"Value\", i8 5, i8 0, !\\3, i8 1, i32 1, i8 3, i32 2, i8 0, null}",
 
     "signature element Value at location \\(2,0\\) size \\(1,3\\) overlaps another signature element.",
@@ -1647,6 +1663,7 @@ float4 main(float4 f4 : Input, out float d0 : SV_Depth, out float d1 : SV_Target
     "ps_6_0",
 
     "!{i32 1, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 1, i32 1, i8 0, null}\n"
+    "!16 = !{i32 1}\n"
     "!([0-9]+) = !{i32 2, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 4, i32 0, i8 0, null}",
 
     "!{i32 1, !\"SV_DepthGreaterEqual\", i8 9, i8 19, !\\3, i8 0, i32 1, i8 1, i32 -1, i8 -1, null}\n"

+ 1 - 1
utils/hct/hctdb.py

@@ -1563,7 +1563,7 @@ class db_dxil(object):
         self.add_valrule("Flow.Reducible", "Execution flow must be reducible")
         self.add_valrule("Flow.NoRecusion", "Recursion is not permitted")
         self.add_valrule("Flow.DeadLoop", "Loop must have break")
-        self.add_valrule_msg("Flow.FunctionCall", "Function call on user defined function with parameter is not permitted", "Function call on user defined function with parameter %0 is not permitted, it should be inlined")
+        self.add_valrule_msg("Flow.FunctionCall", "Function with parameter is not permitted", "Function %0 with parameter is not permitted, it should be inlined")
 
         self.add_valrule_msg("Decl.DxilNsReserved", "The DXIL reserved prefixes must only be used by built-in functions and types", "Declaration '%0' uses a reserved prefix")
         self.add_valrule_msg("Decl.DxilFnExtern", "External function must be a DXIL function", "External function '%0' is not a DXIL function")