OSDN Git Service

[OptDiag, opt-viewer] Save callee's location and display as link
authorAdam Nemet <anemet@apple.com>
Mon, 7 Nov 2016 22:41:13 +0000 (22:41 +0000)
committerAdam Nemet <anemet@apple.com>
Mon, 7 Nov 2016 22:41:13 +0000 (22:41 +0000)
With this we get a new field in the YAML record if the value being
streamed out has a debug location.  For examples, please see the changes
to the tests.

This is then used in opt-viewer to display a link for the callee
function in the inlining remarks.

Differential Revision: https://reviews.llvm.org/D26366

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286169 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DiagnosticInfo.h
lib/Analysis/OptimizationDiagnosticInfo.cpp
lib/IR/DiagnosticInfo.cpp
test/Transforms/Inline/optimization-remarks-passed-yaml.ll
test/Transforms/Inline/optimization-remarks-yaml.ll
utils/opt-viewer/opt-viewer.py

index 589a0c0..4951e94 100644 (file)
@@ -385,6 +385,8 @@ public:
   struct Argument {
     StringRef Key;
     std::string Val;
+    // If set, the debug location corresponding to the value.
+    DebugLoc DLoc;
 
     explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
     Argument(StringRef Key, Value *V);
index 6584876..0a5ef1b 100644 (file)
@@ -115,6 +115,8 @@ template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
   static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
     assert(io.outputting() && "input not yet implemented");
     io.mapRequired(A.Key.data(), A.Val);
+    if (A.DLoc)
+      io.mapOptional("DebugLoc", A.DLoc);
   }
 };
 
index ae10a6d..5618de8 100644 (file)
@@ -171,7 +171,14 @@ const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const {
   return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
 }
 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Value *V)
-    : Key(Key), Val(GlobalValue::getRealLinkageName(V->getName())) {}
+    : Key(Key), Val(GlobalValue::getRealLinkageName(V->getName())) {
+  if (auto *F = dyn_cast<Function>(V)) {
+    if (DISubprogram *SP = F->getSubprogram())
+      DLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
+  }
+  else if (auto *I = dyn_cast<Instruction>(V))
+    DLoc = I->getDebugLoc();
+}
 
 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
     : Key(Key), Val(itostr(N)) {}
index 60d0758..1e17334 100644 (file)
 ; YAML-NEXT: Hotness:         30
 ; YAML-NEXT: Args:
 ; YAML-NEXT:   - Callee: foo
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 1, Column: 0 }
 ; YAML-NEXT:   - String: ' can be inlined into '
 ; YAML-NEXT:   - Caller: bar
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 3, Column: 0 }
 ; YAML-NEXT:   - String: ' with cost='
 ; YAML-NEXT:   - Cost: '{{[0-9]+}}'
 ; YAML-NEXT:   - String: ' (threshold='
 ; YAML-NEXT: Hotness:         30
 ; YAML-NEXT: Args:
 ; YAML-NEXT:   - Callee: foo
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 1, Column: 0 }
 ; YAML-NEXT:   - String: ' inlined into '
 ; YAML-NEXT:   - Caller: bar
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 3, Column: 0 }
 ; YAML-NEXT: ...
 
 ; ModuleID = '/tmp/s.c'
index 8c690d9..cfdd3e6 100644 (file)
@@ -26,6 +26,7 @@
 ; YAML-NEXT:   - Callee: foo
 ; YAML-NEXT:   - String: ' will not be inlined into '
 ; YAML-NEXT:   - Caller: baz
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 4, Column: 0 }
 ; YAML-NEXT:   - String: ' because its definition is unavailable'
 ; YAML-NEXT: ...
 ; YAML-NEXT: --- !Missed
@@ -38,6 +39,7 @@
 ; YAML-NEXT:   - Callee: bar
 ; YAML-NEXT:   - String: ' will not be inlined into '
 ; YAML-NEXT:   - Caller: baz
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 4, Column: 0 }
 ; YAML-NEXT:   - String: ' because its definition is unavailable'
 ; YAML-NEXT: ...
 
index 1cafe0f..9d699f5 100755 (executable)
@@ -46,20 +46,36 @@ class Remark(yaml.YAMLObject):
     def DemangledFunctionName(self):
         return demangle(self.Function)
 
+    @classmethod
+    def make_link(cls, File, Line):
+        return "{}#L{}".format(SourceFileRenderer.html_file_name(File), Line)
+
     @property
     def Link(self):
-        return "{}#L{}".format(SourceFileRenderer.html_file_name(self.File), self.Line)
+        return Remark.make_link(self.File, self.Line)
+
+    def getArgString(self, mapping):
+        mapping = mapping.copy()
+        dl = mapping.get('DebugLoc')
+        if dl:
+            del mapping['DebugLoc']
+
+        assert(len(mapping) == 1)
+        (key, value) = mapping.items()[0]
+
+        if key == 'Caller' or key == 'Callee':
+            value = demangle(value)
 
-    def getArgString(self, pair):
-        if pair[0] == 'Callee' or pair[0] == 'Caller':
-            return demangle(pair[1])
-        return pair[1]
+        if dl and key != 'Caller':
+            return "<a href={}>{}</a>".format(
+                Remark.make_link(dl['File'], dl['Line']), value)
+        else:
+            return value
 
     @property
     def message(self):
-        # Args is a list of mappings (dictionaries) with each dictionary with
-        # exactly one key-value pair.
-        values = [self.getArgString(mapping.items()[0]) for mapping in self.Args]
+        # Args is a list of mappings (dictionaries)
+        values = [self.getArgString(mapping) for mapping in self.Args]
         return "".join(values)
 
     @property