Sfoglia il codice sorgente

Print Lines or "add -Zi" on error messages (#2782)

* Print Lines or "add -Zi" on error messages

This change adds to the existing EmitErrorOnInstruction functionality in
dxilutil to include EmitErrorOnFunction and EmitErrorOnGlobalVariable.
Each derives line number information from the metadata of these objects
if available. If it isn't available, the error or warning messages are
still printed, but an additional suggestion to add a -Zi flag is added.
Greg Roth 5 anni fa
parent
commit
78b58851fd

+ 15 - 3
include/dxc/DXIL/DxilUtil.h

@@ -32,7 +32,9 @@ class BasicBlock;
 class raw_ostream;
 class raw_ostream;
 class ModulePass;
 class ModulePass;
 class PassRegistry;
 class PassRegistry;
+class DebugInfoFinder;
 class DebugLoc;
 class DebugLoc;
+class DIGlobalVariable;
 
 
 ModulePass *createDxilLoadMetadataPass();
 ModulePass *createDxilLoadMetadataPass();
 void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
 void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
@@ -41,13 +43,14 @@ void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
 namespace hlsl {
 namespace hlsl {
 
 
 class DxilFieldAnnotation;
 class DxilFieldAnnotation;
+class DxilModule;
 class DxilTypeSystem;
 class DxilTypeSystem;
 class OP;
 class OP;
 
 
 namespace dxilutil {
 namespace dxilutil {
   extern const char ManglingPrefix[];
   extern const char ManglingPrefix[];
   extern const char EntryPrefix[];
   extern const char EntryPrefix[];
-  extern const llvm::StringRef kResourceMapErrorMsg;
+  extern const char *kResourceMapErrorMsg;
 
 
   unsigned
   unsigned
   GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
   GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
@@ -69,8 +72,17 @@ namespace dxilutil {
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
   bool RemoveUnusedFunctions(llvm::Module &M, llvm::Function *EntryFunc,
   bool RemoveUnusedFunctions(llvm::Module &M, llvm::Function *EntryFunc,
                              llvm::Function *PatchConstantFunc, bool IsLib);
                              llvm::Function *PatchConstantFunc, bool IsLib);
-  void EmitErrorOnInstruction(llvm::Instruction *I, llvm::StringRef Msg);
-  void EmitWarningOnInstruction(llvm::Instruction *I, llvm::StringRef Msg);
+
+  llvm::DIGlobalVariable *FindGlobalVariableDebugInfo(llvm::GlobalVariable *GV,
+                                                llvm::DebugInfoFinder &DbgInfoFinder);
+
+  void EmitErrorOnInstruction(llvm::Instruction *I, llvm::Twine Msg);
+  void EmitWarningOnInstruction(llvm::Instruction *I, llvm::Twine Msg);
+  void EmitErrorOnFunction(llvm::Function *F, llvm::Twine Msg);
+  void EmitWarningOnFunction(llvm::Function *F, llvm::Twine Msg);
+  void EmitErrorOnGlobalVariable(llvm::GlobalVariable *GV, llvm::Twine Msg);
+  void EmitWarningOnGlobalVariable(llvm::GlobalVariable *GV, llvm::Twine Msg);
+
   void EmitResMappingError(llvm::Instruction *Res);
   void EmitResMappingError(llvm::Instruction *Res);
   std::string FormatMessageAtLocation(const llvm::DebugLoc &DL, const llvm::Twine& Msg);
   std::string FormatMessageAtLocation(const llvm::DebugLoc &DL, const llvm::Twine& Msg);
   llvm::Twine FormatMessageWithoutLocation(const llvm::Twine& Msg);
   llvm::Twine FormatMessageWithoutLocation(const llvm::Twine& Msg);

+ 0 - 3
include/dxc/HLSL/HLModule.h

@@ -231,9 +231,6 @@ public:
   DxilFunctionPropsMap &&ReleaseFunctionPropsMap();
   DxilFunctionPropsMap &&ReleaseFunctionPropsMap();
 
 
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
-  static llvm::DIGlobalVariable *
-  FindGlobalVariableDebugInfo(llvm::GlobalVariable *GV,
-                              llvm::DebugInfoFinder &DbgInfoFinder);
   // Create global variable debug info for element global variable based on the
   // Create global variable debug info for element global variable based on the
   // whole global variable.
   // whole global variable.
   static void CreateElementGlobalVariableDebugInfo(
   static void CreateElementGlobalVariableDebugInfo(

+ 100 - 6
lib/DXIL/DxilUtil.cpp

@@ -210,6 +210,25 @@ std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::StringRef BC,
   return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr);
   return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr);
 }
 }
 
 
+
+DIGlobalVariable *FindGlobalVariableDebugInfo(GlobalVariable *GV,
+                                              DebugInfoFinder &DbgInfoFinder) {
+  struct GlobalFinder {
+    GlobalVariable *GV;
+    bool operator()(llvm::DIGlobalVariable *const arg) const {
+      return arg->getVariable() == GV;
+    }
+  };
+  GlobalFinder F = {GV};
+  DebugInfoFinder::global_variable_iterator Found =
+      std::find_if(DbgInfoFinder.global_variables().begin(),
+                   DbgInfoFinder.global_variables().end(), F);
+  if (Found != DbgInfoFinder.global_variables().end()) {
+    return *Found;
+  }
+  return nullptr;
+}
+
 std::string FormatMessageAtLocation(const DebugLoc &DL, const Twine& Msg) {
 std::string FormatMessageAtLocation(const DebugLoc &DL, const Twine& Msg) {
   std::string locString;
   std::string locString;
   raw_string_ostream os(locString);
   raw_string_ostream os(locString);
@@ -218,11 +237,33 @@ std::string FormatMessageAtLocation(const DebugLoc &DL, const Twine& Msg) {
   return os.str();
   return os.str();
 }
 }
 
 
+std::string FormatMessageInSubProgram(DISubprogram *DISP, const Twine& Msg) {
+  std::string locString;
+  raw_string_ostream os(locString);
+
+  auto *Scope = cast<DIScope>(DISP->getScope());
+  os << Scope->getFilename();
+  os << ':' << DISP->getLine();
+  os << ": " << Msg;
+  return os.str();
+}
+
+std::string FormatMessageInVariable(DIVariable *DIV, const Twine& Msg) {
+  std::string locString;
+  raw_string_ostream os(locString);
+
+  auto *Scope = cast<DIScope>(DIV->getScope());
+  os << Scope->getFilename();
+  os << ':' << DIV->getLine();
+  os << ": " << Msg;
+  return os.str();
+}
+
 Twine FormatMessageWithoutLocation(const Twine& Msg) {
 Twine FormatMessageWithoutLocation(const Twine& Msg) {
   return Msg + " Use /Zi for source location.";
   return Msg + " Use /Zi for source location.";
 }
 }
 
 
-static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
+static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
                                             bool bWarning);
                                             bool bWarning);
 
 
 // If we don't have debug location and this is select/phi,
 // If we don't have debug location and this is select/phi,
@@ -230,7 +271,7 @@ static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
 // Only recurse phi/select and limit depth to prevent doing
 // Only recurse phi/select and limit depth to prevent doing
 // too much work if no debug location found.
 // too much work if no debug location found.
 static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
 static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
-                                                           StringRef Msg,
+                                                           Twine Msg,
                                                            bool bWarning,
                                                            bool bWarning,
                                                            unsigned depth = 0) {
                                                            unsigned depth = 0) {
   if (depth > 4)
   if (depth > 4)
@@ -249,7 +290,7 @@ static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
   return false;
   return false;
 }
 }
 
 
-static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
+static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
                                             bool bWarning) {
                                             bool bWarning) {
   const DebugLoc &DL = I->getDebugLoc();
   const DebugLoc &DL = I->getDebugLoc();
   if (DL.get()) {
   if (DL.get()) {
@@ -269,15 +310,68 @@ static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
     I->getContext().emitError(FormatMessageWithoutLocation(Msg));
     I->getContext().emitError(FormatMessageWithoutLocation(Msg));
 }
 }
 
 
-void EmitErrorOnInstruction(Instruction *I, StringRef Msg) {
+void EmitErrorOnInstruction(Instruction *I, Twine Msg) {
   EmitWarningOrErrorOnInstruction(I, Msg, /*bWarning*/false);
   EmitWarningOrErrorOnInstruction(I, Msg, /*bWarning*/false);
 }
 }
 
 
-void EmitWarningOnInstruction(Instruction *I, StringRef Msg) {
+void EmitWarningOnInstruction(Instruction *I, Twine Msg) {
   EmitWarningOrErrorOnInstruction(I, Msg, /*bWarning*/true);
   EmitWarningOrErrorOnInstruction(I, Msg, /*bWarning*/true);
 }
 }
 
 
-const StringRef kResourceMapErrorMsg =
+static void EmitWarningOrErrorOnFunction(Function *F, Twine Msg,
+                                         bool bWarning) {
+  DISubprogram *DISP = getDISubprogram(F);
+  if (DISP) {
+    if (bWarning)
+      F->getContext().emitWarning(FormatMessageInSubProgram(DISP, Msg));
+    else
+      F->getContext().emitError(FormatMessageInSubProgram(DISP, Msg));
+    return;
+  }
+
+  if (bWarning)
+    F->getContext().emitWarning(FormatMessageWithoutLocation(Msg));
+  else
+    F->getContext().emitError(FormatMessageWithoutLocation(Msg));
+}
+
+void EmitErrorOnFunction(Function *F, Twine Msg) {
+  EmitWarningOrErrorOnFunction(F, Msg, /*bWarning*/false);
+}
+
+void EmitWarningOnFunction(Function *F, Twine Msg) {
+  EmitWarningOrErrorOnFunction(F, Msg, /*bWarning*/true);
+}
+
+static void EmitWarningOrErrorOnGlobalVariable(GlobalVariable *GV,
+                                               Twine Msg, bool bWarning) {
+  DIVariable *DIV = nullptr;
+  if (GV)
+    DIV = FindGlobalVariableDebugInfo(GV, GV->getParent()->GetDxilModule().GetOrCreateDebugInfoFinder());
+  if (DIV) {
+    if (bWarning)
+      GV->getContext().emitWarning(FormatMessageInVariable(DIV, Msg));
+    else
+      GV->getContext().emitError(FormatMessageInVariable(DIV, Msg));
+    return;
+  }
+
+  if (bWarning)
+    GV->getContext().emitWarning(FormatMessageWithoutLocation(Msg));
+  else
+    GV->getContext().emitError(FormatMessageWithoutLocation(Msg));
+}
+
+void EmitErrorOnGlobalVariable(GlobalVariable *GV, Twine Msg) {
+  EmitWarningOrErrorOnGlobalVariable(GV, Msg, /*bWarning*/false);
+}
+
+void EmitWarningOnGlobalVariable(GlobalVariable *GV, Twine Msg) {
+  EmitWarningOrErrorOnGlobalVariable(GV, Msg, /*bWarning*/true);
+}
+
+
+const char *kResourceMapErrorMsg =
     "local resource not guaranteed to map to unique global resource.";
     "local resource not guaranteed to map to unique global resource.";
 void EmitResMappingError(Instruction *Res) {
 void EmitResMappingError(Instruction *Res) {
   EmitErrorOnInstruction(Res, kResourceMapErrorMsg);
   EmitErrorOnInstruction(Res, kResourceMapErrorMsg);

+ 28 - 42
lib/HLSL/DxilCondenseResources.cpp

@@ -121,7 +121,7 @@ private:
   template <typename T>
   template <typename T>
   static bool
   static bool
   AllocateRegisters(const std::vector<std::unique_ptr<T>> &resourceList,
   AllocateRegisters(const std::vector<std::unique_ptr<T>> &resourceList,
-    LLVMContext &Ctx, SpacesAllocator<unsigned, T> &ReservedRegisters,
+    SpacesAllocator<unsigned, T> &ReservedRegisters,
     unsigned AutoBindingSpace) {
     unsigned AutoBindingSpace) {
     bool bChanged = false;
     bool bChanged = false;
     SpacesAllocator<unsigned, T> SAlloc;
     SpacesAllocator<unsigned, T> SAlloc;
@@ -138,9 +138,10 @@ private:
         if (res->IsUnbounded()) {
         if (res->IsUnbounded()) {
           const T *unbounded = alloc.GetUnbounded();
           const T *unbounded = alloc.GetUnbounded();
           if (unbounded) {
           if (unbounded) {
-            Ctx.emitError(Twine("more than one unbounded resource (") +
-              unbounded->GetGlobalName() + (" and ") +
-              res->GetGlobalName() + (") in space ") + Twine(space));
+            dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
+                                                Twine("more than one unbounded resource (") +
+                                                unbounded->GetGlobalName() + (" and ") +
+                                                res->GetGlobalName() + (") in space ") + Twine(space));
           }
           }
           else {
           else {
             conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
             conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
@@ -154,13 +155,14 @@ private:
           conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
           conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
         }
         }
         if (conflict) {
         if (conflict) {
-          Ctx.emitError(((res->IsUnbounded()) ? Twine("unbounded ") : Twine("")) +
-            Twine("resource ") + res->GetGlobalName() +
-            Twine(" at register ") + Twine(reg) +
-            Twine(" overlaps with resource ") +
-            conflict->GetGlobalName() + Twine(" at register ") +
-            Twine(conflict->GetLowerBound()) + Twine(", space ") +
-            Twine(space));
+          dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()), 
+                                              ((res->IsUnbounded()) ? Twine("unbounded ") : Twine("")) +
+                                              Twine("resource ") + res->GetGlobalName() +
+                                              Twine(" at register ") + Twine(reg) +
+                                              Twine(" overlaps with resource ") +
+                                              conflict->GetGlobalName() + Twine(" at register ") +
+                                              Twine(conflict->GetLowerBound()) + Twine(", space ") +
+                                              Twine(space));
         }
         }
         else {
         else {
           // Also add this to the reserved (unallocatable) range, if it wasn't already there.
           // Also add this to the reserved (unallocatable) range, if it wasn't already there.
@@ -185,10 +187,11 @@ private:
       if (res->IsUnbounded()) {
       if (res->IsUnbounded()) {
         if (alloc.GetUnbounded() != nullptr) {
         if (alloc.GetUnbounded() != nullptr) {
           const T *unbounded = alloc.GetUnbounded();
           const T *unbounded = alloc.GetUnbounded();
-          Ctx.emitError(Twine("more than one unbounded resource (") +
-            unbounded->GetGlobalName() + Twine(" and ") +
-            res->GetGlobalName() + Twine(") in space ") +
-            Twine(space));
+          dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
+                                              Twine("more than one unbounded resource (") +
+                                              unbounded->GetGlobalName() + Twine(" and ") +
+                                              res->GetGlobalName() + Twine(") in space ") +
+                                              Twine(space));
           continue;
           continue;
         }
         }
 
 
@@ -218,9 +221,10 @@ private:
         res->SetSpaceID(space);
         res->SetSpaceID(space);
         bChanged = true;
         bChanged = true;
       } else {
       } else {
-        Ctx.emitError(((res->IsUnbounded()) ? Twine("unbounded ") : Twine("")) +
-          Twine("resource ") + res->GetGlobalName() +
-          Twine(" could not be allocated"));
+        dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
+                                            ((res->IsUnbounded()) ? Twine("unbounded ") : Twine("")) +
+                                            Twine("resource ") + res->GetGlobalName() +
+                                            Twine(" could not be allocated"));
       }
       }
     }
     }
 
 
@@ -250,10 +254,10 @@ public:
     }
     }
 
 
     bool bChanged = false;
     bool bChanged = false;
-    bChanged |= AllocateRegisters(DM.GetCBuffers(), DM.GetCtx(), m_reservedCBufferRegisters, AutoBindingSpace);
-    bChanged |= AllocateRegisters(DM.GetSamplers(), DM.GetCtx(), m_reservedSamplerRegisters, AutoBindingSpace);
-    bChanged |= AllocateRegisters(DM.GetUAVs(), DM.GetCtx(), m_reservedUAVRegisters, AutoBindingSpace);
-    bChanged |= AllocateRegisters(DM.GetSRVs(), DM.GetCtx(), m_reservedSRVRegisters, AutoBindingSpace);
+    bChanged |= AllocateRegisters(DM.GetCBuffers(), m_reservedCBufferRegisters, AutoBindingSpace);
+    bChanged |= AllocateRegisters(DM.GetSamplers(), m_reservedSamplerRegisters, AutoBindingSpace);
+    bChanged |= AllocateRegisters(DM.GetUAVs(), m_reservedUAVRegisters, AutoBindingSpace);
+    bChanged |= AllocateRegisters(DM.GetSRVs(), m_reservedSRVRegisters, AutoBindingSpace);
     return bChanged;
     return bChanged;
   }
   }
 };
 };
@@ -743,8 +747,7 @@ public:
         os.flush();
         os.flush();
         Name = escName;
         Name = escName;
       }
       }
-      Twine msg = Twine(ErrorText[ec]) + " Value: " + Name;
-      V->getContext().emitError(msg);
+      V->getContext().emitError(Twine(ErrorText[ec]) + " Value: " + Name);
     }
     }
   }
   }
 
 
@@ -1884,23 +1887,6 @@ void ReplaceResourceUserWithHandle(
   Res->eraseFromParent();
   Res->eraseFromParent();
 }
 }
 
 
-DIGlobalVariable *FindGlobalVariableDebugInfo(GlobalVariable *GV,
-                                              DebugInfoFinder &DbgInfoFinder) {
-  struct GlobalFinder {
-    GlobalVariable *GV;
-    bool operator()(llvm::DIGlobalVariable *const arg) const {
-      return arg->getVariable() == GV;
-    }
-  };
-  GlobalFinder F = {GV};
-  DebugInfoFinder::global_variable_iterator Found =
-      std::find_if(DbgInfoFinder.global_variables().begin(),
-                   DbgInfoFinder.global_variables().end(), F);
-  if (Found != DbgInfoFinder.global_variables().end()) {
-    return *Found;
-  }
-  return nullptr;
-}
 } // namespace
 } // namespace
 void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
 void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
     DxilResourceBase &res) {
     DxilResourceBase &res) {
@@ -1936,7 +1922,7 @@ void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
   DILocation *DL = nullptr;
   DILocation *DL = nullptr;
   if (m_HasDbgInfo) {
   if (m_HasDbgInfo) {
     DebugInfoFinder &Finder = m_DM->GetOrCreateDebugInfoFinder();
     DebugInfoFinder &Finder = m_DM->GetOrCreateDebugInfoFinder();
-    DIV = FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
+    DIV = dxilutil::FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
     if (DIV)
     if (DIV)
       // TODO: how to get col?
       // TODO: how to get col?
       DL =
       DL =

+ 3 - 3
lib/HLSL/DxilGenerationPass.cpp

@@ -213,7 +213,7 @@ public:
     if (!SM->IsLib()) {
     if (!SM->IsLib()) {
       Function *EntryFn = m_pHLModule->GetEntryFunction();
       Function *EntryFn = m_pHLModule->GetEntryFunction();
       if (!m_pHLModule->HasDxilFunctionProps(EntryFn)) {
       if (!m_pHLModule->HasDxilFunctionProps(EntryFn)) {
-        M.getContext().emitError("Entry function don't have property.");
+        dxilutil::EmitErrorOnFunction(EntryFn, "Entry function don't have property.");
         return false;
         return false;
       }
       }
       DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(EntryFn);
       DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(EntryFn);
@@ -265,7 +265,7 @@ public:
           if (F.user_empty()) {
           if (F.user_empty()) {
             F.eraseFromParent();
             F.eraseFromParent();
           } else {
           } else {
-            M.getContext().emitError("Fail to lower createHandle.");
+            dxilutil::EmitErrorOnFunction(&F, "Fail to lower createHandle.");
           }
           }
         }
         }
       }
       }
@@ -521,7 +521,7 @@ void DxilGenerationPass::GenerateDxilCBufferHandles() {
     DILocation *DL = nullptr;
     DILocation *DL = nullptr;
     if (m_HasDbgInfo) {
     if (m_HasDbgInfo) {
       DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
       DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
-      DIV = HLModule::FindGlobalVariableDebugInfo(GV, Finder);
+      DIV = dxilutil::FindGlobalVariableDebugInfo(GV, Finder);
       if (DIV)
       if (DIV)
         // TODO: how to get col?
         // TODO: how to get col?
         DL = DILocation::get(Ctx, DIV->getLine(), 1,
         DL = DILocation::get(Ctx, DIV->getLine(), 1,

+ 5 - 9
lib/HLSL/DxilLegalizeSampleOffsetPass.cpp

@@ -13,6 +13,7 @@
 #include "llvm/Analysis/DxilValueCache.h"
 #include "llvm/Analysis/DxilValueCache.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilOperations.h"
 #include "dxc/DXIL/DxilOperations.h"
+#include "dxc/DXIL/DxilUtil.h"
 
 
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopInfo.h"
@@ -137,17 +138,12 @@ void DxilLegalizeSampleOffsetPass::FinalCheck(
   if (!finalIllegalOffsets.empty()) {
   if (!finalIllegalOffsets.empty()) {
     const StringRef kIllegalOffsetError =
     const StringRef kIllegalOffsetError =
         "Offsets for Sample* must be immediated value. "
         "Offsets for Sample* must be immediated value. "
-        "Consider unroll the loop manually and use O3, it may help in some "
-        "cases\n";
+        "Consider unrolling the loop manually and use -O3, "
+        "it may help in some cases.\n";
     std::string errorMsg;
     std::string errorMsg;
     raw_string_ostream errorStr(errorMsg);
     raw_string_ostream errorStr(errorMsg);
-    for (Instruction *offset : finalIllegalOffsets) {
-      if (const DebugLoc &L = offset->getDebugLoc())
-        L.print(errorStr);
-      errorStr << " " << kIllegalOffsetError;
-    }
-    errorStr.flush();
-    F.getContext().emitError(errorMsg);
+    for (Instruction *offset : finalIllegalOffsets)
+      dxilutil::EmitErrorOnInstruction(offset, kIllegalOffsetError);
   }
   }
 }
 }
 
 

+ 10 - 8
lib/HLSL/DxilLinker.cpp

@@ -464,8 +464,9 @@ bool DxilLinkJob::AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV) {
     bool bMatch = IsMatchedType(Ty0, Ty);
     bool bMatch = IsMatchedType(Ty0, Ty);
     if (!bMatch) {
     if (!bMatch) {
       // Report error.
       // Report error.
-      m_ctx.emitError(Twine(kRedefineResource) + res->GetResClassName() + " for " +
-                      res->GetGlobalName());
+      dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
+                                          Twine(kRedefineResource) + res->GetResClassName() + " for " +
+                                          res->GetGlobalName());
       return false;
       return false;
     }
     }
   } else {
   } else {
@@ -608,7 +609,7 @@ bool DxilLinkJob::AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap) {
           }
           }
 
 
           // Redefine of global.
           // Redefine of global.
-          m_ctx.emitError(Twine(kRedefineGlobal) + GV->getName());
+          dxilutil::EmitErrorOnGlobalVariable(GV, Twine(kRedefineGlobal) + GV->getName());
           bSuccess = false;
           bSuccess = false;
         }
         }
         continue;
         continue;
@@ -696,7 +697,7 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
   DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
   DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
   if (!entryDM.HasDxilFunctionProps(entryFunc)) {
   if (!entryDM.HasDxilFunctionProps(entryFunc)) {
     // Cannot get function props.
     // Cannot get function props.
-    m_ctx.emitError(Twine(kNoEntryProps) + entryFunc->getName());
+    dxilutil::EmitErrorOnFunction(entryFunc, Twine(kNoEntryProps) + entryFunc->getName());
     return nullptr;
     return nullptr;
   }
   }
 
 
@@ -704,9 +705,9 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
 
 
   if (pSM->GetKind() != props.shaderKind) {
   if (pSM->GetKind() != props.shaderKind) {
     // Shader kind mismatch.
     // Shader kind mismatch.
-    m_ctx.emitError(Twine(kShaderKindMismatch) +
-                    ShaderModel::GetKindName(pSM->GetKind()) + " and " +
-                    ShaderModel::GetKindName(props.shaderKind));
+    dxilutil::EmitErrorOnFunction(entryFunc, Twine(kShaderKindMismatch) +
+                                  ShaderModel::GetKindName(pSM->GetKind()) + " and " +
+                                  ShaderModel::GetKindName(props.shaderKind));
     return nullptr;
     return nullptr;
   }
   }
 
 
@@ -1120,7 +1121,8 @@ bool DxilLinkerImpl::AttachLib(DxilLib *lib) {
     StringRef name = it->getKey();
     StringRef name = it->getKey();
     if (m_functionNameMap.count(name)) {
     if (m_functionNameMap.count(name)) {
       // Redefine of function.
       // Redefine of function.
-      m_ctx.emitError(Twine(kRedefineFunction) + name);
+      const DxilFunctionLinkInfo *DFLI = it->getValue().get();
+      dxilutil::EmitErrorOnFunction(DFLI->func, Twine(kRedefineFunction) + name);
       bSuccess = false;
       bSuccess = false;
       continue;
       continue;
     }
     }

+ 6 - 0
lib/HLSL/DxilValidation.cpp

@@ -812,6 +812,8 @@ struct ValidationContext {
     if (!EmitInstrLoc(I, rule)) return;
     if (!EmitInstrLoc(I, rule)) return;
     DiagPrinter << GetValidationRuleText(rule);
     DiagPrinter << GetValidationRuleText(rule);
     DiagPrinter << '\n';
     DiagPrinter << '\n';
+    if (!GetDebugLoc(I))
+      DiagPrinter << "Use /Zi for source location.\n";
     Failed = true;
     Failed = true;
   }
   }
 
 
@@ -822,6 +824,8 @@ struct ValidationContext {
     FormatRuleText(ruleText, args);
     FormatRuleText(ruleText, args);
     DiagPrinter << ruleText;
     DiagPrinter << ruleText;
     DiagPrinter << '\n';
     DiagPrinter << '\n';
+    if (!GetDebugLoc(I))
+      DiagPrinter << "Use /Zi for source location.\n";
     Failed = true;
     Failed = true;
   }
   }
 
 
@@ -832,6 +836,8 @@ struct ValidationContext {
     FormatRuleText(ruleText, {name, range, v});
     FormatRuleText(ruleText, {name, range, v});
     DiagPrinter << ruleText;
     DiagPrinter << ruleText;
     DiagPrinter << '\n';
     DiagPrinter << '\n';
+    if (!GetDebugLoc(I))
+      DiagPrinter << "Use /Zi for source location.\n";
     Failed = true;
     Failed = true;
   }
   }
 
 

+ 2 - 21
lib/HLSL/HLModule.cpp

@@ -1234,25 +1234,6 @@ bool HLModule::HasPreciseAttribute(Function *F) {
   return preciseNode != nullptr;
   return preciseNode != nullptr;
 }
 }
 
 
-DIGlobalVariable *
-HLModule::FindGlobalVariableDebugInfo(GlobalVariable *GV,
-                                      DebugInfoFinder &DbgInfoFinder) {
-  struct GlobalFinder {
-    GlobalVariable *GV;
-    bool operator()(llvm::DIGlobalVariable *const arg) const {
-      return arg->getVariable() == GV;
-    }
-  };
-  GlobalFinder F = {GV};
-  DebugInfoFinder::global_variable_iterator Found =
-      std::find_if(DbgInfoFinder.global_variables().begin(),
-                   DbgInfoFinder.global_variables().end(), F);
-  if (Found != DbgInfoFinder.global_variables().end()) {
-    return *Found;
-  }
-  return nullptr;
-}
-
 static void AddDIGlobalVariable(DIBuilder &Builder, DIGlobalVariable *LocDIGV,
 static void AddDIGlobalVariable(DIBuilder &Builder, DIGlobalVariable *LocDIGV,
                                 StringRef Name, DIType *DITy,
                                 StringRef Name, DIType *DITy,
                                 GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, bool removeLocDIGV) {
                                 GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, bool removeLocDIGV) {
@@ -1307,7 +1288,7 @@ void HLModule::CreateElementGlobalVariableDebugInfo(
     GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, GlobalVariable *EltGV,
     GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, GlobalVariable *EltGV,
     unsigned sizeInBits, unsigned alignInBits, unsigned offsetInBits,
     unsigned sizeInBits, unsigned alignInBits, unsigned offsetInBits,
     StringRef eltName) {
     StringRef eltName) {
-  DIGlobalVariable *DIGV = FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
+  DIGlobalVariable *DIGV = dxilutil::FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
   DXASSERT_NOMSG(DIGV);
   DXASSERT_NOMSG(DIGV);
   DIBuilder Builder(*GV->getParent());
   DIBuilder Builder(*GV->getParent());
   DITypeIdentifierMap EmptyMap;
   DITypeIdentifierMap EmptyMap;
@@ -1335,7 +1316,7 @@ void HLModule::CreateElementGlobalVariableDebugInfo(
 void HLModule::UpdateGlobalVariableDebugInfo(
 void HLModule::UpdateGlobalVariableDebugInfo(
     llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder,
     llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder,
     llvm::GlobalVariable *NewGV) {
     llvm::GlobalVariable *NewGV) {
-  DIGlobalVariable *DIGV = FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
+  DIGlobalVariable *DIGV = dxilutil::FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
   DXASSERT_NOMSG(DIGV);
   DXASSERT_NOMSG(DIGV);
   DIBuilder Builder(*GV->getParent());
   DIBuilder Builder(*GV->getParent());
   DITypeIdentifierMap EmptyMap;
   DITypeIdentifierMap EmptyMap;

+ 20 - 23
lib/HLSL/HLOperationLower.cpp

@@ -256,7 +256,7 @@ private:
           CI->getArgOperand(HLOperandIndex::kCreateHandleResourceOpIdx);
           CI->getArgOperand(HLOperandIndex::kCreateHandleResourceOpIdx);
       LoadInst *LdRes = dyn_cast<LoadInst>(Res);
       LoadInst *LdRes = dyn_cast<LoadInst>(Res);
       if (!LdRes) {
       if (!LdRes) {
-        CI->getContext().emitError(CI, "cannot map resource to handle");
+        dxilutil::EmitErrorOnInstruction(CI, "cannot map resource to handle.");
         return;
         return;
       }
       }
       UpdateCounterSet.insert(LdRes);
       UpdateCounterSet.insert(LdRes);
@@ -600,7 +600,7 @@ Value *TranslateD3DColorToUByte4(CallInst *CI, IntrinsicOp IOP,
       std::vector<int> mask { 2, 1, 0, 3 };
       std::vector<int> mask { 2, 1, 0, 3 };
       val = Builder.CreateShuffleVector(val, val, mask);
       val = Builder.CreateShuffleVector(val, val, mask);
     } else {
     } else {
-      CI->getContext().emitError(CI, "Unsupported input type for intrinsic D3DColorToUByte4");
+      dxilutil::EmitErrorOnInstruction(CI, "Unsupported input type for intrinsic D3DColorToUByte4.");
       return UndefValue::get(CI->getType());
       return UndefValue::get(CI->getType());
     }
     }
   }
   }
@@ -740,15 +740,15 @@ Value *TranslateAddUint64(CallInst *CI, IntrinsicOp IOP,
   Type *Ty = val->getType();
   Type *Ty = val->getType();
   VectorType *VT = dyn_cast<VectorType>(Ty);
   VectorType *VT = dyn_cast<VectorType>(Ty);
   if (!VT) {
   if (!VT) {
-    CI->getContext().emitError(
-        CI, "AddUint64 can only be applied to uint2 and uint4 operands");
+    dxilutil::EmitErrorOnInstruction(
+        CI, "AddUint64 can only be applied to uint2 and uint4 operands.");
     return UndefValue::get(Ty);
     return UndefValue::get(Ty);
   }
   }
 
 
   unsigned size = VT->getNumElements();
   unsigned size = VT->getNumElements();
   if (size != 2 && size != 4) {
   if (size != 2 && size != 4) {
-    CI->getContext().emitError(
-        CI, "AddUint64 can only be applied to uint2 and uint4 operands");
+    dxilutil::EmitErrorOnInstruction(
+        CI, "AddUint64 can only be applied to uint2 and uint4 operands.");
     return UndefValue::get(Ty);
     return UndefValue::get(Ty);
   }
   }
   Value *op0 = CI->getArgOperand(HLOperandIndex::kBinaryOpSrc0Idx);
   Value *op0 = CI->getArgOperand(HLOperandIndex::kBinaryOpSrc0Idx);
@@ -847,8 +847,8 @@ Value *TranslateEvalHelper(CallInst *CI, Value *val, IRBuilder<> &Builder,
     for (unsigned i = 0; i < Ty->getVectorNumElements(); ++i) {
     for (unsigned i = 0; i < Ty->getVectorNumElements(); ++i) {
       Value *InputEl = FindScalarSource(val, i);
       Value *InputEl = FindScalarSource(val, i);
       if (!IsValidLoadInput(InputEl)) {
       if (!IsValidLoadInput(InputEl)) {
-        CI->getContext().emitError(CI, "attribute evaluation can only be done "
-                                       "on values taken directly from inputs");
+        dxilutil::EmitErrorOnInstruction(CI, "attribute evaluation can only be done "
+                                             "on values taken directly from inputs.");
         return result;
         return result;
       }
       }
       CallInst *loadInput = cast<CallInst>(InputEl);
       CallInst *loadInput = cast<CallInst>(InputEl);
@@ -862,8 +862,8 @@ Value *TranslateEvalHelper(CallInst *CI, Value *val, IRBuilder<> &Builder,
   else {
   else {
     Value *InputEl = FindScalarSource(val);
     Value *InputEl = FindScalarSource(val);
     if (!IsValidLoadInput(InputEl)) {
     if (!IsValidLoadInput(InputEl)) {
-      CI->getContext().emitError(CI, "attribute evaluation can only be done "
-                                     "on values taken directly from inputs");
+      dxilutil::EmitErrorOnInstruction(CI, "attribute evaluation can only be done "
+                                           "on values taken directly from inputs.");
       return result;
       return result;
     }
     }
     CallInst *loadInput = cast<CallInst>(InputEl);
     CallInst *loadInput = cast<CallInst>(InputEl);
@@ -5081,7 +5081,7 @@ namespace {
 Value *EmptyLower(CallInst *CI, IntrinsicOp IOP, DXIL::OpCode opcode,
 Value *EmptyLower(CallInst *CI, IntrinsicOp IOP, DXIL::OpCode opcode,
                   HLOperationLowerHelper &helper,  HLObjectOperationLowerHelper *pObjHelper, bool &Translated) {
                   HLOperationLowerHelper &helper,  HLObjectOperationLowerHelper *pObjHelper, bool &Translated) {
   Translated = false;
   Translated = false;
-  CI->getContext().emitError(CI, "Unsupported intrinsic");
+  dxilutil::EmitErrorOnInstruction(CI, "Unsupported intrinsic.");
   return nullptr;
   return nullptr;
 }
 }
 
 
@@ -5093,7 +5093,7 @@ Value *UnsupportedVulkanIntrinsic(CallInst *CI, IntrinsicOp IOP,
                                   HLObjectOperationLowerHelper *pObjHelper,
                                   HLObjectOperationLowerHelper *pObjHelper,
                                   bool &Translated) {
                                   bool &Translated) {
   Translated = false;
   Translated = false;
-  CI->getContext().emitError(CI, "Unsupported Vulkan intrinsic");
+  dxilutil::EmitErrorOnInstruction(CI, "Unsupported Vulkan intrinsic.");
   return nullptr;
   return nullptr;
 }
 }
 #endif // ENABLE_SPIRV_CODEGEN
 #endif // ENABLE_SPIRV_CODEGEN
@@ -7228,7 +7228,7 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         if (!isa<CallInst>(GEPUser)) {
         if (!isa<CallInst>(GEPUser)) {
           // Invalid operations.
           // Invalid operations.
           Translated = false;
           Translated = false;
-          CI->getContext().emitError(GEP, "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(GEP, "Invalid operation on typed buffer.");
           return;
           return;
         }
         }
         CallInst *userCall = cast<CallInst>(GEPUser);
         CallInst *userCall = cast<CallInst>(GEPUser);
@@ -7237,8 +7237,7 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         if (group != HLOpcodeGroup::HLIntrinsic) {
         if (group != HLOpcodeGroup::HLIntrinsic) {
           // Invalid operations.
           // Invalid operations.
           Translated = false;
           Translated = false;
-          CI->getContext().emitError(userCall,
-                                     "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
           return;
           return;
         }
         }
         unsigned opcode = hlsl::GetHLOpcode(userCall);
         unsigned opcode = hlsl::GetHLOpcode(userCall);
@@ -7257,15 +7256,14 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         case IntrinsicOp::IOP_InterlockedCompareExchange: {
         case IntrinsicOp::IOP_InterlockedCompareExchange: {
           // Invalid operations.
           // Invalid operations.
           Translated = false;
           Translated = false;
-          CI->getContext().emitError(
-              userCall, "Atomic operation on typed buffer is not supported");
+          dxilutil::EmitErrorOnInstruction(
+              userCall, "Atomic operation on typed buffer is not supported.");
           return;
           return;
         } break;
         } break;
         default:
         default:
           // Invalid operations.
           // Invalid operations.
           Translated = false;
           Translated = false;
-          CI->getContext().emitError(userCall,
-                                     "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
           return;
           return;
           break;
           break;
         }
         }
@@ -7293,13 +7291,12 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
           case IntrinsicOp::IOP_InterlockedXor:
           case IntrinsicOp::IOP_InterlockedXor:
           case IntrinsicOp::IOP_InterlockedCompareStore:
           case IntrinsicOp::IOP_InterlockedCompareStore:
           case IntrinsicOp::IOP_InterlockedCompareExchange: {
           case IntrinsicOp::IOP_InterlockedCompareExchange: {
-            CI->getContext().emitError(
-                userCall, "Atomic operation targets must be groupshared on UAV");
+            dxilutil::EmitErrorOnInstruction(
+                userCall, "Atomic operation targets must be groupshared on UAV.");
             return;
             return;
           } break;
           } break;
           default:
           default:
-            CI->getContext().emitError(userCall,
-                                       "Invalid operation on typed buffer");
+            dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
             return;
             return;
             break;
             break;
           }
           }

+ 22 - 22
lib/HLSL/HLSignatureLower.cpp

@@ -244,7 +244,7 @@ void HLSignatureLower::ProcessArgument(Function *func,
   if (sigPoint->GetKind() == DXIL::SigPointKind::MSPOut) {
   if (sigPoint->GetKind() == DXIL::SigPointKind::MSPOut) {
     if (interpMode != InterpolationMode::Kind::Undefined &&
     if (interpMode != InterpolationMode::Kind::Undefined &&
         interpMode != InterpolationMode::Kind::Constant) {
         interpMode != InterpolationMode::Kind::Constant) {
-      Entry->getContext().emitError(
+      dxilutil::EmitErrorOnFunction(func,
         "Mesh shader's primitive outputs' interpolation mode must be constant or undefined.");
         "Mesh shader's primitive outputs' interpolation mode must be constant or undefined.");
     }
     }
     interpMode = InterpolationMode::Kind::Constant;
     interpMode = InterpolationMode::Kind::Constant;
@@ -266,7 +266,7 @@ void HLSignatureLower::ProcessArgument(Function *func,
 
 
   llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
   llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
   if (semanticStr.empty()) {
   if (semanticStr.empty()) {
-    func->getContext().emitError(
+    dxilutil::EmitErrorOnFunction(func,
         "Semantic must be defined for all parameters of an entry function or "
         "Semantic must be defined for all parameters of an entry function or "
         "patch constant function");
         "patch constant function");
     return;
     return;
@@ -298,9 +298,8 @@ void HLSignatureLower::ProcessArgument(Function *func,
       auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
       auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
       for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
       for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
         if (SemanticIndexSet.count(idx) > 0) {
         if (SemanticIndexSet.count(idx) > 0) {
-          func->getContext().emitError(
-              Twine("Parameter with semantic ") + semanticStr +
-              Twine(" has overlapping semantic index at ") + Twine(idx));
+          dxilutil::EmitErrorOnFunction(func, "Parameter with semantic " + semanticStr +
+            " has overlapping semantic index at " + std::to_string(idx) + ".");
           return;
           return;
         }
         }
       }
       }
@@ -316,7 +315,7 @@ void HLSignatureLower::ProcessArgument(Function *func,
                0) ||
                0) ||
           (pSemantic->GetKind() == DXIL::SemanticKind::InnerCoverage &&
           (pSemantic->GetKind() == DXIL::SemanticKind::InnerCoverage &&
            SemanticUseMap.count((unsigned)DXIL::SemanticKind::Coverage) > 0)) {
            SemanticUseMap.count((unsigned)DXIL::SemanticKind::Coverage) > 0)) {
-        func->getContext().emitError(
+        dxilutil::EmitErrorOnFunction(func,
             "Pixel shader inputs SV_Coverage and SV_InnerCoverage are mutually "
             "Pixel shader inputs SV_Coverage and SV_InnerCoverage are mutually "
             "exclusive");
             "exclusive");
         return;
         return;
@@ -328,12 +327,13 @@ void HLSignatureLower::ProcessArgument(Function *func,
   // intrinsics
   // intrinsics
   {
   {
     switch (interpretation) {
     switch (interpretation) {
-    case DXIL::SemanticInterpretationKind::NA:
-      func->getContext().emitError(Twine("Semantic ") + semanticStr +
-                                   Twine(" is invalid for shader model: ") +
-                                   ShaderModel::GetKindName(props.shaderKind));
+    case DXIL::SemanticInterpretationKind::NA: {
+      dxilutil::EmitErrorOnFunction(func, Twine("Semantic ") + semanticStr +
+                                    Twine(" is invalid for shader model: ") +
+                                    ShaderModel::GetKindName(props.shaderKind));
 
 
       return;
       return;
+    }
     case DXIL::SemanticInterpretationKind::NotInSig:
     case DXIL::SemanticInterpretationKind::NotInSig:
     case DXIL::SemanticInterpretationKind::Shadow: {
     case DXIL::SemanticInterpretationKind::Shadow: {
       IRBuilder<> funcBuilder(func->getEntryBlock().getFirstInsertionPt());
       IRBuilder<> funcBuilder(func->getEntryBlock().getFirstInsertionPt());
@@ -389,11 +389,10 @@ void HLSignatureLower::ProcessArgument(Function *func,
       pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
       pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
                                interpMode, sigPoint->GetKind(), *pSig);
                                interpMode, sigPoint->GetKind(), *pSig);
       if (!pSE) {
       if (!pSE) {
-        func->getContext().emitError(
-            Twine("Signature element ") + semanticStr +
-            Twine(", referred to by patch constant function, is not found in "
-                  "corresponding hull shader ") +
-            (sigKind == DXIL::SignatureKind::Input ? "input." : "output."));
+        dxilutil::EmitErrorOnFunction(func, Twine("Signature element ") + semanticStr +
+                                      Twine(", referred to by patch constant function, is not found in "
+                                            "corresponding hull shader ") +
+                                      (sigKind == DXIL::SignatureKind::Input ? "input." : "output."));
         return;
         return;
       }
       }
       m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
       m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
@@ -454,7 +453,7 @@ void HLSignatureLower::CreateDxilSignatures() {
   }
   }
 
 
   if (bHasClipPlane) {
   if (bHasClipPlane) {
-    Entry->getContext().emitError("Cannot use clipplanes attribute without "
+    dxilutil::EmitErrorOnFunction(Entry, "Cannot use clipplanes attribute without "
                                   "specifying a 4-component SV_Position "
                                   "specifying a 4-component SV_Position "
                                   "output");
                                   "output");
   }
   }
@@ -464,7 +463,7 @@ void HLSignatureLower::CreateDxilSignatures() {
   if (props.shaderKind == DXIL::ShaderKind::Hull) {
   if (props.shaderKind == DXIL::ShaderKind::Hull) {
     Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
     Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
     if (patchConstantFunc == nullptr) {
     if (patchConstantFunc == nullptr) {
-      Entry->getContext().emitError(
+      dxilutil::EmitErrorOnFunction(Entry,
           "Patch constant function is not specified.");
           "Patch constant function is not specified.");
     }
     }
 
 
@@ -493,14 +492,14 @@ void HLSignatureLower::AllocateDxilInputOutputs() {
 
 
   hlsl::PackDxilSignature(EntrySig.InputSignature, packing);
   hlsl::PackDxilSignature(EntrySig.InputSignature, packing);
   if (!EntrySig.InputSignature.IsFullyAllocated()) {
   if (!EntrySig.InputSignature.IsFullyAllocated()) {
-    HLM.GetCtx().emitError(
+    dxilutil::EmitErrorOnFunction(Entry,
         "Failed to allocate all input signature elements in available space.");
         "Failed to allocate all input signature elements in available space.");
   }
   }
 
 
   if (props.shaderKind != DXIL::ShaderKind::Amplification) {
   if (props.shaderKind != DXIL::ShaderKind::Amplification) {
     hlsl::PackDxilSignature(EntrySig.OutputSignature, packing);
     hlsl::PackDxilSignature(EntrySig.OutputSignature, packing);
     if (!EntrySig.OutputSignature.IsFullyAllocated()) {
     if (!EntrySig.OutputSignature.IsFullyAllocated()) {
-      HLM.GetCtx().emitError(
+      dxilutil::EmitErrorOnFunction(Entry,
           "Failed to allocate all output signature elements in available space.");
           "Failed to allocate all output signature elements in available space.");
     }
     }
   }
   }
@@ -510,7 +509,8 @@ void HLSignatureLower::AllocateDxilInputOutputs() {
       props.shaderKind == DXIL::ShaderKind::Mesh) {
       props.shaderKind == DXIL::ShaderKind::Mesh) {
     hlsl::PackDxilSignature(EntrySig.PatchConstOrPrimSignature, packing);
     hlsl::PackDxilSignature(EntrySig.PatchConstOrPrimSignature, packing);
     if (!EntrySig.PatchConstOrPrimSignature.IsFullyAllocated()) {
     if (!EntrySig.PatchConstOrPrimSignature.IsFullyAllocated()) {
-      HLM.GetCtx().emitError("Failed to allocate all patch constant signature "
+      dxilutil::EmitErrorOnFunction(Entry,
+                             "Failed to allocate all patch constant signature "
                              "elements in available space.");
                              "elements in available space.");
     }
     }
   }
   }
@@ -1195,7 +1195,7 @@ void HLSignatureLower::GenerateDxilCSInputs() {
 
 
     llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
     llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
     if (semanticStr.empty()) {
     if (semanticStr.empty()) {
-      Entry->getContext().emitError("Semantic must be defined for all "
+      dxilutil::EmitErrorOnFunction(Entry, "Semantic must be defined for all "
                                     "parameters of an entry function or patch "
                                     "parameters of an entry function or patch "
                                     "constant function");
                                     "constant function");
       return;
       return;
@@ -1220,7 +1220,7 @@ void HLSignatureLower::GenerateDxilCSInputs() {
     default:
     default:
       DXASSERT(semantic->IsInvalid(),
       DXASSERT(semantic->IsInvalid(),
                "else compute shader semantics out-of-date");
                "else compute shader semantics out-of-date");
-      Entry->getContext().emitError("invalid semantic found in CS");
+      dxilutil::EmitErrorOnFunction(Entry, "invalid semantic found in CS");
       return;
       return;
     }
     }