Browse Source

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 years ago
parent
commit
78b58851fd

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

@@ -32,7 +32,9 @@ class BasicBlock;
 class raw_ostream;
 class ModulePass;
 class PassRegistry;
+class DebugInfoFinder;
 class DebugLoc;
+class DIGlobalVariable;
 
 ModulePass *createDxilLoadMetadataPass();
 void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
@@ -41,13 +43,14 @@ void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
 namespace hlsl {
 
 class DxilFieldAnnotation;
+class DxilModule;
 class DxilTypeSystem;
 class OP;
 
 namespace dxilutil {
   extern const char ManglingPrefix[];
   extern const char EntryPrefix[];
-  extern const llvm::StringRef kResourceMapErrorMsg;
+  extern const char *kResourceMapErrorMsg;
 
   unsigned
   GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
@@ -69,8 +72,17 @@ namespace dxilutil {
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
   bool RemoveUnusedFunctions(llvm::Module &M, llvm::Function *EntryFunc,
                              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);
   std::string FormatMessageAtLocation(const llvm::DebugLoc &DL, 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();
 
   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
   // whole global variable.
   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);
 }
 
+
+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 locString;
   raw_string_ostream os(locString);
@@ -218,11 +237,33 @@ std::string FormatMessageAtLocation(const DebugLoc &DL, const Twine& Msg) {
   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) {
   return Msg + " Use /Zi for source location.";
 }
 
-static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
+static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
                                             bool bWarning);
 
 // 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
 // too much work if no debug location found.
 static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
-                                                           StringRef Msg,
+                                                           Twine Msg,
                                                            bool bWarning,
                                                            unsigned depth = 0) {
   if (depth > 4)
@@ -249,7 +290,7 @@ static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
   return false;
 }
 
-static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
+static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
                                             bool bWarning) {
   const DebugLoc &DL = I->getDebugLoc();
   if (DL.get()) {
@@ -269,15 +310,68 @@ static void EmitWarningOrErrorOnInstruction(Instruction *I, StringRef Msg,
     I->getContext().emitError(FormatMessageWithoutLocation(Msg));
 }
 
-void EmitErrorOnInstruction(Instruction *I, StringRef Msg) {
+void EmitErrorOnInstruction(Instruction *I, Twine Msg) {
   EmitWarningOrErrorOnInstruction(I, Msg, /*bWarning*/false);
 }
 
-void EmitWarningOnInstruction(Instruction *I, StringRef Msg) {
+void EmitWarningOnInstruction(Instruction *I, Twine Msg) {
   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.";
 void EmitResMappingError(Instruction *Res) {
   EmitErrorOnInstruction(Res, kResourceMapErrorMsg);

+ 28 - 42
lib/HLSL/DxilCondenseResources.cpp

@@ -121,7 +121,7 @@ private:
   template <typename T>
   static bool
   AllocateRegisters(const std::vector<std::unique_ptr<T>> &resourceList,
-    LLVMContext &Ctx, SpacesAllocator<unsigned, T> &ReservedRegisters,
+    SpacesAllocator<unsigned, T> &ReservedRegisters,
     unsigned AutoBindingSpace) {
     bool bChanged = false;
     SpacesAllocator<unsigned, T> SAlloc;
@@ -138,9 +138,10 @@ private:
         if (res->IsUnbounded()) {
           const T *unbounded = alloc.GetUnbounded();
           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 {
             conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
@@ -154,13 +155,14 @@ private:
           conflict = alloc.Insert(res.get(), reg, res->GetUpperBound());
         }
         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 {
           // Also add this to the reserved (unallocatable) range, if it wasn't already there.
@@ -185,10 +187,11 @@ private:
       if (res->IsUnbounded()) {
         if (alloc.GetUnbounded() != nullptr) {
           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;
         }
 
@@ -218,9 +221,10 @@ private:
         res->SetSpaceID(space);
         bChanged = true;
       } 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;
-    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;
   }
 };
@@ -743,8 +747,7 @@ public:
         os.flush();
         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();
 }
 
-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
 void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
     DxilResourceBase &res) {
@@ -1936,7 +1922,7 @@ void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
   DILocation *DL = nullptr;
   if (m_HasDbgInfo) {
     DebugInfoFinder &Finder = m_DM->GetOrCreateDebugInfoFinder();
-    DIV = FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
+    DIV = dxilutil::FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
     if (DIV)
       // TODO: how to get col?
       DL =

+ 3 - 3
lib/HLSL/DxilGenerationPass.cpp

@@ -213,7 +213,7 @@ public:
     if (!SM->IsLib()) {
       Function *EntryFn = m_pHLModule->GetEntryFunction();
       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;
       }
       DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(EntryFn);
@@ -265,7 +265,7 @@ public:
           if (F.user_empty()) {
             F.eraseFromParent();
           } 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;
     if (m_HasDbgInfo) {
       DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
-      DIV = HLModule::FindGlobalVariableDebugInfo(GV, Finder);
+      DIV = dxilutil::FindGlobalVariableDebugInfo(GV, Finder);
       if (DIV)
         // TODO: how to get col?
         DL = DILocation::get(Ctx, DIV->getLine(), 1,

+ 5 - 9
lib/HLSL/DxilLegalizeSampleOffsetPass.cpp

@@ -13,6 +13,7 @@
 #include "llvm/Analysis/DxilValueCache.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilOperations.h"
+#include "dxc/DXIL/DxilUtil.h"
 
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/LoopInfo.h"
@@ -137,17 +138,12 @@ void DxilLegalizeSampleOffsetPass::FinalCheck(
   if (!finalIllegalOffsets.empty()) {
     const StringRef kIllegalOffsetError =
         "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;
     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);
     if (!bMatch) {
       // 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;
     }
   } else {
@@ -608,7 +609,7 @@ bool DxilLinkJob::AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap) {
           }
 
           // Redefine of global.
-          m_ctx.emitError(Twine(kRedefineGlobal) + GV->getName());
+          dxilutil::EmitErrorOnGlobalVariable(GV, Twine(kRedefineGlobal) + GV->getName());
           bSuccess = false;
         }
         continue;
@@ -696,7 +697,7 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
   DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
   if (!entryDM.HasDxilFunctionProps(entryFunc)) {
     // Cannot get function props.
-    m_ctx.emitError(Twine(kNoEntryProps) + entryFunc->getName());
+    dxilutil::EmitErrorOnFunction(entryFunc, Twine(kNoEntryProps) + entryFunc->getName());
     return nullptr;
   }
 
@@ -704,9 +705,9 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
 
   if (pSM->GetKind() != props.shaderKind) {
     // 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;
   }
 
@@ -1120,7 +1121,8 @@ bool DxilLinkerImpl::AttachLib(DxilLib *lib) {
     StringRef name = it->getKey();
     if (m_functionNameMap.count(name)) {
       // Redefine of function.
-      m_ctx.emitError(Twine(kRedefineFunction) + name);
+      const DxilFunctionLinkInfo *DFLI = it->getValue().get();
+      dxilutil::EmitErrorOnFunction(DFLI->func, Twine(kRedefineFunction) + name);
       bSuccess = false;
       continue;
     }

+ 6 - 0
lib/HLSL/DxilValidation.cpp

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

+ 2 - 21
lib/HLSL/HLModule.cpp

@@ -1234,25 +1234,6 @@ bool HLModule::HasPreciseAttribute(Function *F) {
   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,
                                 StringRef Name, DIType *DITy,
                                 GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, bool removeLocDIGV) {
@@ -1307,7 +1288,7 @@ void HLModule::CreateElementGlobalVariableDebugInfo(
     GlobalVariable *GV, DebugInfoFinder &DbgInfoFinder, GlobalVariable *EltGV,
     unsigned sizeInBits, unsigned alignInBits, unsigned offsetInBits,
     StringRef eltName) {
-  DIGlobalVariable *DIGV = FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
+  DIGlobalVariable *DIGV = dxilutil::FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
   DXASSERT_NOMSG(DIGV);
   DIBuilder Builder(*GV->getParent());
   DITypeIdentifierMap EmptyMap;
@@ -1335,7 +1316,7 @@ void HLModule::CreateElementGlobalVariableDebugInfo(
 void HLModule::UpdateGlobalVariableDebugInfo(
     llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder,
     llvm::GlobalVariable *NewGV) {
-  DIGlobalVariable *DIGV = FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
+  DIGlobalVariable *DIGV = dxilutil::FindGlobalVariableDebugInfo(GV, DbgInfoFinder);
   DXASSERT_NOMSG(DIGV);
   DIBuilder Builder(*GV->getParent());
   DITypeIdentifierMap EmptyMap;

+ 20 - 23
lib/HLSL/HLOperationLower.cpp

@@ -256,7 +256,7 @@ private:
           CI->getArgOperand(HLOperandIndex::kCreateHandleResourceOpIdx);
       LoadInst *LdRes = dyn_cast<LoadInst>(Res);
       if (!LdRes) {
-        CI->getContext().emitError(CI, "cannot map resource to handle");
+        dxilutil::EmitErrorOnInstruction(CI, "cannot map resource to handle.");
         return;
       }
       UpdateCounterSet.insert(LdRes);
@@ -600,7 +600,7 @@ Value *TranslateD3DColorToUByte4(CallInst *CI, IntrinsicOp IOP,
       std::vector<int> mask { 2, 1, 0, 3 };
       val = Builder.CreateShuffleVector(val, val, mask);
     } 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());
     }
   }
@@ -740,15 +740,15 @@ Value *TranslateAddUint64(CallInst *CI, IntrinsicOp IOP,
   Type *Ty = val->getType();
   VectorType *VT = dyn_cast<VectorType>(Ty);
   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);
   }
 
   unsigned size = VT->getNumElements();
   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);
   }
   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) {
       Value *InputEl = FindScalarSource(val, i);
       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;
       }
       CallInst *loadInput = cast<CallInst>(InputEl);
@@ -862,8 +862,8 @@ Value *TranslateEvalHelper(CallInst *CI, Value *val, IRBuilder<> &Builder,
   else {
     Value *InputEl = FindScalarSource(val);
     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;
     }
     CallInst *loadInput = cast<CallInst>(InputEl);
@@ -5081,7 +5081,7 @@ namespace {
 Value *EmptyLower(CallInst *CI, IntrinsicOp IOP, DXIL::OpCode opcode,
                   HLOperationLowerHelper &helper,  HLObjectOperationLowerHelper *pObjHelper, bool &Translated) {
   Translated = false;
-  CI->getContext().emitError(CI, "Unsupported intrinsic");
+  dxilutil::EmitErrorOnInstruction(CI, "Unsupported intrinsic.");
   return nullptr;
 }
 
@@ -5093,7 +5093,7 @@ Value *UnsupportedVulkanIntrinsic(CallInst *CI, IntrinsicOp IOP,
                                   HLObjectOperationLowerHelper *pObjHelper,
                                   bool &Translated) {
   Translated = false;
-  CI->getContext().emitError(CI, "Unsupported Vulkan intrinsic");
+  dxilutil::EmitErrorOnInstruction(CI, "Unsupported Vulkan intrinsic.");
   return nullptr;
 }
 #endif // ENABLE_SPIRV_CODEGEN
@@ -7228,7 +7228,7 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         if (!isa<CallInst>(GEPUser)) {
           // Invalid operations.
           Translated = false;
-          CI->getContext().emitError(GEP, "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(GEP, "Invalid operation on typed buffer.");
           return;
         }
         CallInst *userCall = cast<CallInst>(GEPUser);
@@ -7237,8 +7237,7 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         if (group != HLOpcodeGroup::HLIntrinsic) {
           // Invalid operations.
           Translated = false;
-          CI->getContext().emitError(userCall,
-                                     "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
           return;
         }
         unsigned opcode = hlsl::GetHLOpcode(userCall);
@@ -7257,15 +7256,14 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
         case IntrinsicOp::IOP_InterlockedCompareExchange: {
           // Invalid operations.
           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;
         } break;
         default:
           // Invalid operations.
           Translated = false;
-          CI->getContext().emitError(userCall,
-                                     "Invalid operation on typed buffer");
+          dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
           return;
           break;
         }
@@ -7293,13 +7291,12 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
           case IntrinsicOp::IOP_InterlockedXor:
           case IntrinsicOp::IOP_InterlockedCompareStore:
           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;
           } break;
           default:
-            CI->getContext().emitError(userCall,
-                                       "Invalid operation on typed buffer");
+            dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
             return;
             break;
           }

+ 22 - 22
lib/HLSL/HLSignatureLower.cpp

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