HPCToolkit
Struct-Tree.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 //************************* System Include Files ****************************
61 
62 #include <iostream>
63 using std::ostream;
64 using std::hex;
65 using std::dec;
66 using std::endl;
67 
68 #include <string>
69 using std::string;
70 
71 #include <typeinfo>
72 
73 #include <algorithm>
74 
75 #include <cstring> // for 'strcmp'
76 
77 
78 //*************************** User Include Files ****************************
79 
80 #include <include/gcc-attr.h>
81 #include <include/uint.h>
82 
83 #include "Struct-Tree.hpp"
84 
85 #include <lib/xml/xml.hpp>
86 
88 #include <lib/support/FileUtil.hpp>
89 #include <lib/support/Logic.hpp>
90 #include <lib/support/SrcFile.hpp>
91 using SrcFile::ln_NULL;
92 #include <lib/support/StrUtil.hpp>
93 
94 //*************************** Forward Declarations **************************
95 
96 using namespace xml;
97 
98 #define DBG_FILE 0
99 
100 //***************************************************************************
101 
102 namespace Prof {
103 namespace Struct {
104 
105 
107 
108 //***************************************************************************
109 // Tree
110 //***************************************************************************
111 
112 uint ANode::s_nextUniqueId = 1;
113 
114 const std::string Tree::UnknownLMNm = "<unknown load module>";
115 
116 const std::string Tree::UnknownFileNm = "<unknown file>";
117 
118 const std::string Tree::UnknownProcNm = "<unknown procedure>";
119 
120 const std::string Tree::PartialUnwindProcNm = "<partial call paths>";
121 
122 const std::string Tree::UnknownGlobalVariable = "<unknown variable>";
123 
124 const SrcFile::ln Tree::UnknownLine = SrcFile::ln_NULL;
125 
126 
127 Tree::Tree(const char* name, Root* root)
128  : m_root(root)
129 {
130  if (!m_root) {
131  m_root = new Root(name);
132  }
133 }
134 
135 
137 {
138  delete m_root;
139 }
140 
141 string
142 Tree::name() const
143 {
144  string nm = (m_root) ? std::string(m_root->name()) : "";
145  return nm;
146 }
147 
148 
149 ostream&
150 Tree::writeXML(ostream& os, uint oFlags) const
151 {
152  if (m_root) {
153  m_root->writeXML(os, oFlags);
154  }
155  return os;
156 }
157 
158 
159 ostream&
160 Tree::dump(ostream& os, uint oFlags) const
161 {
162  writeXML(os, oFlags);
163  return os;
164 }
165 
166 
167 void
168 Tree::ddump() const
169 {
170  dump(std::cerr, Tree::OFlg_Debug);
171 }
172 
173 
174 void
175 writeXML(std::ostream& os, const Prof::Struct::Tree& strctTree,
176  bool prettyPrint)
177 {
178  static const char* structureDTD =
180 
181  os << "<?xml version=\"1.0\"?>\n";
182  os << "<!DOCTYPE HPCToolkitStructure [\n" << structureDTD << "]>\n";
183  os.flush();
184 
185  int oFlags = 0;
186  if (!prettyPrint) {
188  }
189 
190  os << "<HPCToolkitStructure i=\"0\" version=\"4.6\" n"
191  << xml::MakeAttrStr(strctTree.name()) << ">\n";
192  strctTree.writeXML(os, oFlags);
193  os << "</HPCToolkitStructure>\n";
194  os.flush();
195 }
196 
197 
198 //***************************************************************************
199 // ANodeTy `methods' (could completely replace with dynamic typing)
200 //***************************************************************************
201 
202 const string ANode::ScopeNames[ANode::TyNUMBER] = {
203  "Pgm", "Group", "LM", "File", "Proc", "Alien", "Loop", "Stmt", "Ref", "ANY"
204 };
205 
206 
207 const string&
209 {
210  return ScopeNames[tp];
211 }
212 
213 
216 {
217  DIAG_Assert((i >= 0) && (i < TyNUMBER), "");
218  return (ANodeTy) i;
219 }
220 
221 
222 //***************************************************************************
223 // ANode, etc: constructors/destructors
224 //***************************************************************************
225 
226 void
228 {
229  this->link(parent);
230  if (begLine() != ln_NULL) {
231  SrcFile::ln bLn = std::min(parent->begLine(), begLine());
232  SrcFile::ln eLn = std::max(parent->endLine(), endLine());
233  parent->setLineRange(bLn, eLn);
234  }
235 }
236 
237 
238 #if 0
240 #endif
241 
242 void
243 Root::Ctor(const char* nm)
244 {
245  DIAG_Assert(nm, "");
246  setInvisible();
247  m_name = nm;
248  groupMap = new GroupMap();
249  lmMap_realpath = new LMMap();
250  lmMap_basename = new LMMap();
251 }
252 
253 
254 Root&
256 {
257  // shallow copy
258  if (&x != this) {
259  m_name = x.m_name;
260  groupMap = NULL;
261  lmMap_realpath = NULL;
262  lmMap_basename = NULL;
263  }
264  return *this;
265 }
266 
267 
268 LM*
269 Root::findLM(const char* nm) const
270 {
271  // TODO: if the map is empty and Root has LM children, we should
272  // populate the map
273 
274  string nm_real = nm;
275  s_realpathMgr.realpath(nm_real);
276 
277  LMMap::iterator it1 = lmMap_realpath->find(nm_real);
278  LM* x = (it1 != lmMap_realpath->end()) ? it1->second : NULL;
279 
280  if (!x) {
281  string nm_base = FileUtil::basename(nm_real);
282 
283  // N.B. Must be careful about simply searching by nm_base. If we have
284  // nm = <path1>/base
285  // then we could mistakenly find <path2>/base.
286  if (nm_real == nm_base) {
287  LMMap::iterator it2 = lmMap_basename->find(nm_base);
288  // N.B. it2->second is NULL if nm_base was inserted multiple times
289  x = (it2 != lmMap_basename->end()) ? it2->second : NULL;
290  }
291  }
292 
293  return x;
294 }
295 
296 
297 void
298 Group::Ctor(const char* nm, ANode* parent)
299 {
300  DIAG_Assert(nm, "");
301  ANodeTy t = (parent) ? parent->type() : TyANY;
302  DIAG_Assert((parent == NULL) || (t == TyRoot) || (t == TyGroup) || (t == TyLM)
303  || (t == TyFile) || (t == TyProc) || (t == TyAlien)
304  || (t == TyLoop), "");
305  m_name = nm;
306  ancestorRoot()->insertGroupMap(this);
307 }
308 
309 
310 Group*
311 Group::demand(Root* pgm, const string& nm, ANode* parent)
312 {
313  Group* grp = pgm->findGroup(nm);
314  if (!grp) {
315  grp = new Group(nm, parent);
316  }
317  return grp;
318 }
319 
320 
321 #if 0
323 #endif
324 
325 void
326 LM::Ctor(const char* nm, ANode* parent)
327 {
328  DIAG_Assert(nm, "");
329  ANodeTy t = (parent) ? parent->type() : TyANY;
330  DIAG_Assert((parent == NULL) || (t == TyRoot) || (t == TyGroup), "");
331 
332  m_name = nm;
333  m_pretty_name = nm;
334 
335  m_fileMap = new FileMap();
336  m_procMap = NULL;
337  m_stmtMap = NULL;
338 
339  Root* root = ancestorRoot();
340  if (root) {
341  root->insertLMMap(this);
342  }
343 }
344 
345 
346 LM&
347 LM::operator=(const LM& x)
348 {
349  // shallow copy
350  if (&x != this) {
351  m_name = x.m_name;
352  m_fileMap = NULL;
353  m_procMap = NULL;
354  m_stmtMap = NULL;
355  }
356  return *this;
357 }
358 
359 
360 LM*
361 LM::demand(Root* pgm, const string& lm_nm)
362 {
363  LM* lm = pgm->findLM(lm_nm);
364  if (!lm) {
365  lm = new LM(lm_nm, pgm);
366  }
367  return lm;
368 }
369 
370 
371 #if 0
373 #endif
374 
375 void
376 File::Ctor(const char* fname, ANode* parent)
377 {
378  ANodeTy t = (parent) ? parent->type() : TyANY;
379  DIAG_Assert((parent == NULL) || (t == TyRoot) || (t == TyGroup) || (t == TyLM), "");
380 
381  m_name = (fname) ? fname : "";
382  m_procMap = new ProcMap();
383 
384  ancestorLM()->insertFileMap(this);
385 }
386 
387 
388 File&
390 {
391  // shallow copy
392  if (&x != this) {
393  m_name = x.m_name;
394  m_procMap = NULL;
395  }
396  return *this;
397 }
398 
399 
400 File*
401 File::demand(LM* lm, const string& filenm)
402 {
403  const char* note = "(found)";
404 
405  string nm_real = filenm;
406  s_realpathMgr.realpath(nm_real);
407 
408  File* file = lm->findFile(nm_real);
409  if (!file) {
410  note = "(created)";
411  file = new File(nm_real, lm);
412  }
413  DIAG_DevMsgIf(DBG_FILE, "Struct::File::demand: " << note << endl
414  << "\tin : " << filenm << endl
415  << "\tout: " << file->name());
416  return file;
417 }
418 
419 
420 void
421 Proc::Ctor(const char* n, ACodeNode* parent, const char* ln, bool hasSym)
422 {
423  DIAG_Assert(n, "");
424  ANodeTy t = (parent) ? parent->type() : TyANY;
425  DIAG_Assert((parent == NULL) || (t == TyGroup) || (t == TyFile), "");
426 
427  m_name = (n) ? n : "";
428  m_linkname = (ln) ? ln : "";
429  m_hasSym = hasSym;
430  m_stmtMap = new StmtMap();
431  if (parent) {
432  relocate();
433  }
434 
435  File* fileStrct = ancestorFile();
436  if (fileStrct) {
437  fileStrct->insertProcMap(this);
438  }
439 }
440 
441 
442 Proc&
444 {
445  // shallow copy
446  if (&x != this) {
447  m_name = x.m_name;
448  m_linkname = x.m_linkname;
449  m_hasSym = x.m_hasSym;
450  m_stmtMap = new StmtMap();
451  }
452  return *this;
453 }
454 
455 
456 Proc*
457 Proc::demand(File* file, const string& name, const std::string& linkname,
458  SrcFile::ln begLn, SrcFile::ln endLn, bool* didCreate)
459 {
460  Proc* proc = file->findProc(name, linkname);
461  if (!proc) {
462  proc = new Proc(name, file, linkname, false, begLn, endLn);
463  if (didCreate) {
464  *didCreate = true;
465  }
466  }
467  else if (didCreate) {
468  *didCreate = false;
469  }
470  return proc;
471 }
472 
473 
474 #if 0
476 #endif
477 
478 void
479 Alien::Ctor(ACodeNode* parent, const char* filenm, const char* nm,
480  const char* displaynm)
481 {
482  ANodeTy t = (parent) ? parent->type() : TyANY;
483  DIAG_Assert((parent == NULL) || (t == TyGroup) || (t == TyAlien)
484  || (t == TyProc) || (t == TyLoop), "");
485 
486  m_filenm = (filenm) ? filenm : "";
487  s_realpathMgr.realpath(m_filenm);
488 
489  m_name = (nm) ? nm : "";
490  m_displaynm = (displaynm) ? displaynm : "";
491  freezeLine();
492 }
493 
494 
495 Alien&
497 {
498  // shallow copy
499  if (&x != this) {
500  m_filenm = x.m_filenm;
501  m_name = x.m_name;
502  m_displaynm = x.m_displaynm;
503  }
504  return *this;
505 }
506 
507 
508 Ref::Ref(ACodeNode* parent, int _begPos, int _endPos, const char* refName)
509  : ACodeNode(TyRef, parent, parent->begLine(), parent->begLine(), 0, 0)
510 {
511  DIAG_Assert(parent->type() == TyStmt, "");
512  begPos = _begPos;
513  endPos = _endPos;
514  m_name = refName;
515  RelocateRef();
516  DIAG_Assert(begPos <= endPos, "");
517  DIAG_Assert(begPos > 0, "");
518  DIAG_Assert(m_name.length() > 0, "");
519 }
520 
521 
522 //***************************************************************************
523 // ANode: ancestor
524 //***************************************************************************
525 
526 #define dyn_cast_return(base, derived, expr) \
527  { base* ptr = expr; \
528  if (ptr == NULL) { \
529  return NULL; \
530  } else { \
531  return dynamic_cast<derived*>(ptr); \
532  } \
533  }
534 
535 ACodeNode*
537 {
538  return dynamic_cast<ACodeNode*>(parent());
539 }
540 
541 
542 ANode*
544 {
545  const ANode* x = this;
546  while (x && x->type() != ty) {
547  x = x->parent();
548  }
549  return const_cast<ANode*>(x);
550 }
551 
552 
553 ANode*
555 {
556  const ANode* x = this;
557  while (x && x->type() != ty1 && x->type() != ty2) {
558  x = x->parent();
559  }
560  return const_cast<ANode*>(x);
561 }
562 
563 
564 ANode*
566 {
567  const ANode* x = this;
568  while (x && x->type() != ty1 && x->type() != ty2 && x->type() != ty3) {
569  x = x->parent();
570  }
571  return const_cast<ANode*>(x);
572 }
573 
574 
575 #if 0
576 int IsAncestorOf(ANode *parent, ANode *son, int difference)
577 {
578  ANode *iter = son;
579  while (iter && difference > 0 && iter != parent) {
580  iter = iter->Parent();
581  difference--;
582  }
583  if (iter && iter == parent)
584  return 1;
585  return 0;
586 }
587 #endif
588 
589 
590 ANode*
592 {
593  // Collect all ancestors of n1 and n2. The root will be at the front
594  // of the ancestor list.
595  ANodeList anc1, anc2;
596  for (ANode* a = n1->parent(); (a); a = a->parent()) {
597  anc1.push_front(a);
598  }
599  for (ANode* a = n2->parent(); (a); a = a->parent()) {
600  anc2.push_front(a);
601  }
602 
603  // Find the most deeply nested common ancestor
604  ANode* lca = NULL;
605  while ( (!anc1.empty() && !anc2.empty()) && (anc1.front() == anc2.front())) {
606  lca = anc1.front();
607  anc1.pop_front();
608  anc2.pop_front();
609  }
610 
611  return lca;
612 }
613 
614 
615 Root*
617 {
618  // iff this is called during ANode construction within the Root
619  // construction dyn_cast does not do the correct thing
620  if (Parent() == NULL) {
621  // eraxxon: This cannot be a good thing to do! Root() was being
622  // called on a LoopInfo object; then the resulting pointer
623  // (the LoopInfo itself) was queried for Root member data. Ouch!
624  // eraxxon: return (Root*) this;
625  return NULL;
626  }
627  else {
629  }
630 }
631 
632 
633 Group*
635 {
637 }
638 
639 
640 LM*
642 {
644 }
645 
646 
647 File*
649 {
651 }
652 
653 
654 Proc*
656 {
658 }
659 
660 
661 Alien*
663 {
665 }
666 
667 
668 Loop*
670 {
672 }
673 
674 
675 Stmt*
677 {
679 }
680 
681 
682 ACodeNode*
684 {
685  return dynamic_cast<ACodeNode*>(ancestor(TyProc, TyAlien));
686 }
687 
688 
689 //***************************************************************************
690 // Metrics
691 //***************************************************************************
692 
693 void
695 {
696  if ( !(mBegId < mEndId) ) {
697  return; // short circuit
698  }
699 
700  const ANode* root = this;
701  ANodeIterator it(root, NULL/*filter*/, false/*leavesOnly*/,
703  for (ANode* n = NULL; (n = it.current()); ++it) {
704  ANode* n_parent = n->parent();
705  if (n != root) {
706  for (uint mId = mBegId; mId < mEndId; ++mId) {
707  double mVal = n->demandMetric(mId, mEndId/*size*/);
708  n_parent->demandMetric(mId, mEndId/*size*/) += mVal;
709  }
710  }
711  }
712 }
713 
714 
715 void
717 {
718  for (ANodeChildIterator it(this); it.Current(); /* */) {
719  ANode* x = it.current();
720  it++; // advance iterator -- it is pointing at 'x'
721 
722  if (x->hasMetrics()) {
723  x->pruneByMetrics();
724  }
725  else {
726  x->unlink(); // unlink 'x' from tree
727  delete x;
728  }
729  }
730 }
731 
732 
733 //***************************************************************************
734 // ANode: Paths and Merging
735 //***************************************************************************
736 
737 int
739 {
740  int distance = 0;
741  for (ANode* x = desc; x != NULL; x = x->parent()) {
742  if (x == anc) {
743  return distance;
744  }
745  ++distance;
746  }
747 
748  // If we arrive here, there was no path between 'anc' and 'desc'
749  return -1;
750 }
751 
752 
753 bool
755 {
756  // Ensure that d1 is on the longest path
757  ANode* d1 = desc1, *d2 = desc2;
758  int dist1 = distance(lca, d1);
759  int dist2 = distance(lca, d2);
760  if (dist2 > dist1) {
761  ANode* t = d1;
762  d1 = d2;
763  d2 = t;
764  }
765 
766  // Iterate over the longest path (d1 -> lca) searching for d2. Stop
767  // when x is NULL or lca.
768  for (ANode* x = d1; (x && x != lca); x = x->parent()) {
769  if (x == d2) {
770  return true;
771  }
772  }
773 
774  // If we arrive here, we did not encounter d2. Divergent.
775  return false;
776 }
777 
778 
779 bool
780 ANode::mergePaths(ANode* lca, ANode* node_dst, ANode* node_src)
781 {
782  bool merged = false;
783  // Should we verify that lca is really the lca?
784 
785  // Collect nodes along the paths 'lca' --> 'node_dst', 'node_src'.
786  // Exclude 'lca'. Shallowest nodes are at beginning of list.
787  ANodeList path_dst, path_src;
788  for (ANode* x = node_dst; x != lca; x = x->parent()) {
789  path_dst.push_front(x);
790  }
791  for (ANode* x = node_src; x != lca; x = x->parent()) {
792  path_src.push_front(x);
793  }
794  DIAG_Assert(path_dst.size() > 0 && path_src.size() > 0, "");
795 
796  // Merge nodes in 'path_src' into 'path_dst', shallowest to deepest,
797  // exiting as soon as a merge fails
798  ANodeList::iterator it_dst = path_dst.begin();
799  ANodeList::iterator it_src = path_src.begin();
800 
801  for ( ; (it_dst != path_dst.end() && it_src != path_src.end());
802  ++it_src, ++it_dst) {
803  ANode* x_src = *it_src;
804  ANode* x_dst = *it_dst;
805  if (isMergable(x_dst, x_src)) {
806  merged |= merge(x_dst, x_src);
807  }
808  else {
809  break; // done
810  }
811  }
812 
813  return merged;
814 }
815 
816 
817 bool
818 ANode::merge(ANode* node_dst, ANode* node_src)
819 {
820  // Do we really want this?
821  //if (!IsMergable(node_dst, node_src)) {
822  // return false;
823  //}
824 
825  // Perform the merge
826  // 1. Move all children of 'node_src' into 'node_dst'
827  for (ANodeChildIterator it(node_src); it.Current(); /* */) {
828  ANode* x = it.current();
829  it++; // advance iterator so we can unlink 'x'
830 
831  x->unlink();
832  x->link(node_dst);
833  }
834 
835  // 2. If merging ACodeNodes, update line ranges
836  ACodeNode* dst0 = dynamic_cast<ACodeNode*>(node_dst);
837  ACodeNode* src0 = dynamic_cast<ACodeNode*>(node_src);
838  DIAG_Assert(Logic::equiv(dst0, src0), "Invariant broken!");
839  if (dst0 && src0) {
840  SrcFile::ln begLn = std::min(dst0->begLine(), src0->begLine());
841  SrcFile::ln endLn = std::max(dst0->endLine(), src0->endLine());
842  dst0->setLineRange(begLn, endLn);
843  dst0->vmaSet().merge(src0->vmaSet()); // merge VMAs
844  }
845 
846  // 3. Unlink 'node_src' from the tree and delete it
847  node_src->unlink();
848  delete node_src;
849 
850  return true;
851 }
852 
853 
854 bool
855 ANode::isMergable(ANode* node_dst, ANode* node_src)
856 {
857  ANode::ANodeTy ty_dst = node_dst->type(), ty_src = node_src->type();
858 
859  // 1. For now, merges are only defined on following types
860  bool goodTy = (ty_dst == TyLoop || ty_dst == TyAlien || ty_dst == TyGroup);
861 
862  // 2. Check bounds
863  bool goodBnds = true;
864  if (goodTy) {
865  ACodeNode* dst0 = dynamic_cast<ACodeNode*>(node_dst);
866  ACodeNode* src0 = dynamic_cast<ACodeNode*>(node_src);
867  goodBnds = Logic::equiv(SrcFile::isValid(dst0->begLine(), dst0->endLine()),
868  SrcFile::isValid(src0->begLine(), src0->endLine()));
869  }
870 
871  return ((ty_dst == ty_src) && goodTy && goodBnds);
872 }
873 
874 
875 //***************************************************************************
876 // ANode, etc: Names, Name Maps, and Retrieval by Name
877 //***************************************************************************
878 
879 void
881 {
882  std::pair<GroupMap::iterator, bool> ret =
883  groupMap->insert(std::make_pair(grp->name(), grp));
884  DIAG_Assert(ret.second, "Duplicate!");
885 }
886 
887 void
888 Loop::setFile(std::string filenm)
889 {
890  m_filenm = filenm;
891  s_realpathMgr.realpath(m_filenm);
892 }
893 
894 
895 void
897 {
898  string nm_real = lm->name();
899  s_realpathMgr.realpath(nm_real);
900 
901  std::pair<LMMap::iterator, bool> ret1 =
902  lmMap_realpath->insert(std::make_pair(nm_real, lm));
903  DIAG_Assert(ret1.second, "Root::insertLMMap: Duplicate!");
904 
905  string nm_base = FileUtil::basename(nm_real);
906  std::pair<LMMap::iterator, bool> ret2 =
907  lmMap_basename->insert(std::make_pair(nm_base, lm));
908  if (!ret2.second /* no insertion performed */) {
909  // Set target to NULL to indicate 'nm_base' appears more than once
910  LMMap::iterator entry = ret2.first;
911  entry->second = NULL;
912  }
913 }
914 
915 
916 void
918 {
919  string nm_real = f->name();
920  s_realpathMgr.realpath(nm_real);
921  DIAG_DevMsg(2, "LM: mapping file name '" << nm_real << "' to File* " << f);
922  std::pair<FileMap::iterator, bool> ret =
923  m_fileMap->insert(std::make_pair(nm_real, f));
924  DIAG_Assert(ret.second, "Duplicate instance: " << f->name() << "\n" << toStringXML());
925 }
926 
927 
928 void
930 {
931  DIAG_DevMsg(2, "File (" << this << "): mapping proc name '" << p->name()
932  << "' to Proc* " << p);
933  m_procMap->insert(make_pair(p->name(), p)); // multimap
934 }
935 
936 
937 void
939 {
940  // FIXME: confusion between native and alien statements
941  (*m_stmtMap)[stmt->begLine()] = stmt;
942 }
943 
944 
945 File*
946 LM::findFile(const char* nm) const
947 {
948  string nm_real = nm;
949  s_realpathMgr.realpath(nm_real);
950  FileMap::iterator it = m_fileMap->find(nm_real);
951  File* x = (it != m_fileMap->end()) ? it->second : NULL;
952  return x;
953 }
954 
955 
956 ACodeNode*
957 LM::findByVMA(VMA vma) const
958 {
959  // Attempt to find StatementRange and then Proc
960  ACodeNode* found = findStmt(vma);
961  if (!found) {
962  found = findProc(vma);
963  }
964  return found;
965 }
966 
967 
968 Proc*
969 LM::findProc(VMA vma) const
970 {
971  if (!m_procMap) {
972  buildMap(m_procMap, ANode::TyProc);
973  }
974  VMAInterval toFind(vma, vma+1); // [vma, vma+1)
975  VMAIntervalMap<Proc*>::iterator it = m_procMap->find(toFind);
976  return (it != m_procMap->end()) ? it->second : NULL;
977 }
978 
979 
980 Stmt*
981 LM::findStmt(VMA vma) const
982 {
983  if (!m_stmtMap) {
984  buildMap(m_stmtMap, ANode::TyStmt);
985  }
986  VMAInterval toFind(vma, vma+1); // [vma, vma+1)
987  VMAIntervalMap<Stmt*>::iterator it = m_stmtMap->find(toFind);
988  return (it != m_stmtMap->end()) ? it->second : NULL;
989 }
990 
991 
992 template<typename T>
993 void
995 {
996  if (!mp) {
997  mp = new VMAIntervalMap<T>;
998  }
999 
1000  ANodeIterator it(this, &ANodeTyFilter[ty]);
1001  for (; it.Current(); ++it) {
1002  T x = dynamic_cast<T>(it.Current());
1003  insertInMap(mp, x);
1004  }
1005 }
1006 
1007 
1008 template<typename T>
1009 bool
1010 LM::verifyMap(VMAIntervalMap<T>* m, const char* map_nm)
1011 {
1012  if (!m) { return true; }
1013 
1014  for (typename VMAIntervalMap<T>::const_iterator it = m->begin();
1015  it != m->end(); ) {
1016  const VMAInterval& x = it->first;
1017  ++it;
1018  if (it != m->end()) {
1019  const VMAInterval& y = it->first;
1020  DIAG_Assert(!x.overlaps(y), "LM::verifyMap: found overlapping elements within " << map_nm << ": " << x.toString() << " and " << y.toString());
1021  }
1022  }
1023 
1024  return true;
1025 }
1026 
1027 
1028 bool
1030 {
1031  if (!m_stmtMap) {
1032  VMAToStmtRangeMap* mp;
1033  buildMap(mp, ANode::TyStmt);
1034  verifyMap(mp, "stmtMap");
1035  delete mp;
1036  return true;
1037  }
1038  else {
1039  return verifyMap(m_stmtMap, "stmtMap");
1040  }
1041 }
1042 
1043 
1044 Proc*
1045 File::findProc(const char* name, const char* linkname) const
1046 {
1047  Proc* found = NULL;
1048 
1049  ProcMap::const_iterator it = m_procMap->find(name);
1050  if (it != m_procMap->end()) {
1051  if (linkname && linkname[0] != '\0') {
1052  for ( ; (it != m_procMap->end() && strcmp(it->first.c_str(), name) == 0);
1053  ++it) {
1054  Proc* p = it->second;
1055  if (strcmp(p->linkName().c_str(), linkname) == 0) {
1056  return p; // found = p
1057  }
1058  }
1059  }
1060  else {
1061  found = it->second;
1062  }
1063  }
1064 
1065  return found;
1066 }
1067 
1068 
1069 //***************************************************************************
1070 // ACodeNode methods
1071 //***************************************************************************
1072 
1073 void
1075 {
1076  if (m_lineno_frozen) return;
1077 
1078  checkLineRange(begLn, endLn);
1079 
1080  m_begLn = begLn;
1081  m_endLn = endLn;
1082 
1083  relocateIf();
1084 
1085  // never propagate changes outside an Alien
1086  if (propagate && SrcFile::isValid(begLn)
1087  && ACodeNodeParent()
1088  && type() != ANode::TyAlien
1089  // tallent: for some reason this is not equivalent to the above...
1090  /* typeid(*this) != typeid(Struct::Alien)*/) {
1092  }
1093 }
1094 
1095 void
1097 {
1098  if (m_lineno_frozen) return;
1099 
1100  if (type() == ANode::TyAlien) return; // never expand an alien line range
1101  if (type() == ANode::TyLoop) return; // never expand a loop range
1102 
1103  checkLineRange(begLn, endLn);
1104 
1105  if (begLn == ln_NULL) {
1106  DIAG_Assert(m_begLn == ln_NULL, "");
1107  // simply relocate at beginning of sibling list
1108  relocateIf();
1109  }
1110  else {
1111  bool changed = false;
1112  if (m_begLn == ln_NULL) {
1113  m_begLn = begLn;
1114  m_endLn = endLn;
1115  changed = true;
1116  }
1117  else {
1118  if (begLn < m_begLn) { m_begLn = begLn; changed = true; }
1119  if (endLn > m_endLn) { m_endLn = endLn; changed = true; }
1120  }
1121 
1122  if (changed) {
1123  // never propagate changes outside an Alien
1124  relocateIf();
1125  if (propagate && ACodeNodeParent() && type() != ANode::TyAlien) {
1127  }
1128  }
1129  }
1130 }
1131 
1132 
1133 void
1135 {
1136  ACodeNode* prev = dynamic_cast<ACodeNode*>(prevSibling());
1137  ACodeNode* next = dynamic_cast<ACodeNode*>(nextSibling());
1138 
1139  // NOTE: Technically should check for ln_NULL
1140  if ((!prev || (prev->begLine() <= m_begLn))
1141  && (!next || (m_begLn <= next->begLine()))) {
1142  return;
1143  }
1144 
1145  // INVARIANT: The parent scope contains at least two children
1146  DIAG_Assert(parent()->childCount() >= 2, "");
1147 
1148  ANode* prnt = parent();
1149  unlink();
1150 
1151  //if (prnt->firstChild() == NULL) {
1152  // link(prnt);
1153  //}
1154  if (m_begLn == ln_NULL) {
1155  // insert as first child
1156  linkBefore(prnt->firstChild());
1157  }
1158  else {
1159  // insert after sibling with sibling->begLine() <= begLine()
1160  // or iff that does not exist insert as first in sibling list
1161  ACodeNode* sibling = NULL;
1162  for (sibling = dynamic_cast<ACodeNode*>(prnt->lastChild()); sibling;
1163  sibling = dynamic_cast<ACodeNode*>(sibling->prevSibling())) {
1164  if (sibling->begLine() <= m_begLn) {
1165  break;
1166  }
1167  }
1168  if (sibling != NULL) {
1169  linkAfter(sibling);
1170  }
1171  else {
1172  linkBefore(prnt->FirstChild());
1173  }
1174  }
1175 }
1176 
1177 
1178 bool
1179 ACodeNode::containsLine(SrcFile::ln ln, int beg_epsilon, int end_epsilon) const
1180 {
1181  // We assume it makes no sense to compare against ln_NULL
1182  if (m_begLn != ln_NULL) {
1183  if (containsLine(ln)) {
1184  return true;
1185  }
1186  else if (beg_epsilon != 0 || end_epsilon != 0) {
1187  // INVARIANT: 'ln' is strictly outside the range of this context
1188  int beg_delta = begLine() - ln; // > 0 if line is before beg
1189  int end_delta = ln - endLine(); // > 0 if end is before line
1190  return ((beg_delta > 0 && beg_delta <= beg_epsilon)
1191  || (end_delta > 0 && end_delta <= end_epsilon));
1192  }
1193  }
1194  return false;
1195 }
1196 
1197 
1198 ACodeNode*
1200 {
1201  DIAG_Assert(ln != ln_NULL, "ACodeNode::ACodeNodeWithLine: invalid line");
1202  ACodeNode* fnd = NULL;
1203  // ln > m_endLn means there is no child that contains ln
1204  if (ln <= m_endLn) {
1205  for (ANodeChildIterator it(this); it.Current(); it++) {
1206  fnd = dynamic_cast<ACodeNode*>(it.Current());
1207  DIAG_Assert(fnd, "");
1208  if (fnd->containsLine(ln)) {
1209  if (fnd->type() == TyStmt) {
1210  return fnd; // never look inside LINE_SCOPEs
1211  }
1212 
1213  // desired line might be in inner scope; however, it might be
1214  // elsewhere because optimization left procedure with
1215  // non-contiguous line ranges in scopes at various levels.
1216  ACodeNode* inner = fnd->ACodeNodeWithLine(ln);
1217  if (inner) return inner;
1218  }
1219  }
1220  }
1221  if (fnd && fnd->type() == TyProc) {
1222  return const_cast<ACodeNode*>(this);
1223  }
1224  else {
1225  return NULL;
1226  }
1227 }
1228 
1229 
1230 int
1232 {
1233  if (x->begLine() == y->begLine()) {
1234  bool endLinesEqual = (x->endLine() == y->endLine());
1235  if (endLinesEqual) {
1236  // We have two ACodeNode's with identical line intervals...
1237 
1238  // Use lexicographic comparison for procedures
1239  if (x->type() == ANode::TyProc && y->type() == ANode::TyProc) {
1240  Proc *px = (Proc*)x, *py = (Proc*)y;
1241  int cmp1 = px->name().compare(py->name());
1242  if (cmp1 != 0) { return cmp1; }
1243  int cmp2 = px->linkName().compare(py->linkName());
1244  if (cmp2 != 0) { return cmp2; }
1245  }
1246 
1247  // Use VMAInterval sets otherwise.
1248  bool x_lt_y = (x->vmaSet() < y->vmaSet());
1249  bool y_lt_x = (y->vmaSet() < x->vmaSet());
1250  bool vmaSetsEqual = (!x_lt_y && !y_lt_x);
1251 
1252  if (vmaSetsEqual) {
1253  // Try ranking a leaf node before a non-leaf node
1254  if ( !(x->isLeaf() && y->isLeaf())) {
1255  if (x->isLeaf()) { return -1; } // x < y
1256  else if (y->isLeaf()) { return 1; } // x > y
1257  }
1258 
1259  // Give up!
1260  return 0;
1261  }
1262  else if (x_lt_y) { return -1; }
1263  else if (y_lt_x) { return 1; }
1264  else {
1266  }
1267  }
1268  else {
1269  return SrcFile::compare(x->endLine(), y->endLine());
1270  }
1271  }
1272  else {
1273  return SrcFile::compare(x->begLine(), y->begLine());
1274  }
1275 }
1276 
1277 
1278 ACodeNode*
1280 {
1281  const ACodeNode* x = this;
1282 
1283  // FIXME: possibly convert this to static_cast
1284  const ACodeNode* y = dynamic_cast<ACodeNode*>(nextSibling()); // sorted
1285  while (y) {
1286  if (!x->containsLine(y->begLine())) {
1287  break;
1288  }
1289  y = dynamic_cast<const ACodeNode*>(y->nextSibling());
1290  }
1291  return const_cast<ACodeNode*>(y);
1292 }
1293 
1294 
1295 //***************************************************************************
1296 // ACodeNode, etc: CodeName methods
1297 //***************************************************************************
1298 
1299 string
1301 {
1302  string self = "l=" + StrUtil::toStr(m_begLn) + "-" + StrUtil::toStr(m_endLn);
1303  return self;
1304 }
1305 
1306 
1307 string
1309 {
1310  string nm = StrUtil::toStr(m_begLn);
1311  if (m_begLn != m_endLn) {
1312  nm += "-" + StrUtil::toStr(m_endLn);
1313  }
1314  return nm;
1315 }
1316 
1317 
1318 string
1320 {
1321  File* fileStrct = ancestorFile();
1322  LM* lmStrct = (fileStrct) ? fileStrct->ancestorLM() : NULL;
1323  string nm;
1324  if (lmStrct && fileStrct) {
1325  nm = "[" + lmStrct->name() + "]<" + fileStrct->name() + ">";
1326  }
1327  return nm;
1328 }
1329 
1330 
1331 string
1333 {
1334  string self = ANodeTyToName(type()) + " " + ACodeNode::codeName();
1335  return self;
1336 }
1337 
1338 
1339 string
1341 {
1342  string nm;
1343  LM* lmStrct = ancestorLM();
1344  if (lmStrct) {
1345  nm = "[" + lmStrct->name() + "]";
1346  }
1347  nm += name();
1348  return nm;
1349 }
1350 
1351 
1352 string
1354 {
1355  string nm = codeName_LM_F();
1356  nm += name();
1357  return nm;
1358 }
1359 
1360 
1361 string
1363 {
1364  string nm = "<" + m_filenm + ">[" + m_name + "]:";
1365  nm += StrUtil::toStr(m_begLn);
1366  return nm;
1367 }
1368 
1369 
1370 string
1372 {
1373  string nm = codeName_LM_F();
1374  nm += ACodeNode::codeName();
1375  return nm;
1376 }
1377 
1378 
1379 string
1381 {
1382  string nm = codeName_LM_F();
1383  nm += ACodeNode::codeName();
1384  return nm;
1385 }
1386 
1387 
1388 string
1390 {
1391  return m_name + " " + ACodeNode::codeName();
1392 }
1393 
1394 
1395 //***************************************************************************
1396 // ANode, etc: XML output
1397 //***************************************************************************
1398 
1399 static const string XMLelements[ANode::TyNUMBER] = {
1400  "HPCToolkitStructure", "G", "LM", "F", "P", "A", "L", "S", "REF", "ANY"
1401 };
1402 
1403 const string&
1405 {
1406  return XMLelements[tp];
1407 }
1408 
1409 
1410 string
1411 ANode::toStringXML(uint oFlags, const char* pre) const
1412 {
1413  std::ostringstream os;
1414  writeXML(os, oFlags, pre);
1415  return os.str();
1416 }
1417 
1418 
1419 string
1421 {
1422  string self = ANodeTyToXMLelement(type()) + " i" + MakeAttrNum(id());
1423  return self;
1424 }
1425 
1426 
1427 string
1428 ACodeNode::toXML(uint oFlags) const
1429 {
1430  string self = ANode::toXML(oFlags)
1431  + " " + XMLLineRange(oFlags) + " " + XMLVMAIntervals(oFlags);
1432  return self;
1433 }
1434 
1435 
1436 string
1438 {
1439  string line = StrUtil::toStr(begLine());
1440  if (begLine() != endLine()) {
1441  line += "-" + StrUtil::toStr(endLine());
1442  }
1443 
1444  string self = "l" + xml::MakeAttrStr(line);
1445  return self;
1446 }
1447 
1448 
1449 string
1451 {
1452  string self = "v" + MakeAttrStr(m_vmaSet.toString(), xml::ESC_FALSE);
1453  return self;
1454 }
1455 
1456 
1457 string
1458 Root::toXML(uint oFlags) const
1459 {
1460  string self = ANode::toXML(oFlags) + " n" + MakeAttrStr(m_name);
1461  return self;
1462 }
1463 
1464 
1465 string
1466 Group::toXML(uint oFlags) const
1467 {
1468  string self = ANode::toXML(oFlags) + " n" + MakeAttrStr(m_name);
1469  return self;
1470 }
1471 
1472 
1473 string
1474 LM::toXML(uint oFlags) const
1475 {
1476  string self = ANode::toXML(oFlags)
1477  + " n" + MakeAttrStr(m_name) + " " + XMLVMAIntervals(oFlags);
1478  return self;
1479 }
1480 
1481 
1482 string
1483 File::toXML(uint oFlags) const
1484 {
1485  string self = ANode::toXML(oFlags) + " n" + MakeAttrStr(m_name);
1486  return self;
1487 }
1488 
1489 
1490 string
1491 Proc::toXML(uint oFlags) const
1492 {
1493  string self = ANode::toXML(oFlags) + " n" + MakeAttrStr(m_name);
1494  if (!m_linkname.empty() && m_name != m_linkname) { // print if different
1495  self = self + " ln" + MakeAttrStr(m_linkname);
1496  }
1497  self = self + " " + XMLLineRange(oFlags) + " " + XMLVMAIntervals(oFlags);
1498  return self;
1499 }
1500 
1501 
1502 string
1503 Alien::toXML(uint oFlags) const
1504 {
1505  string self = ANode::toXML(oFlags)
1506  + " f" + MakeAttrStr(m_filenm) + " n" + MakeAttrStr(m_displaynm);
1507  self = self + " " + XMLLineRange(oFlags) + " " + XMLVMAIntervals(oFlags);
1508 
1509  // add information on the function definition
1510  // If the alien has an ancestor and the same procedure definition exists,
1511  // we'll add an attribute 'ln' to point to the ID of the function definition.
1512  // This is needed to inform hpcprof that the alien shouldn't be considered
1513  // as different function.
1514 
1515  // 1a: get the load module of the alien
1516  LM *lm = ancestorLM();
1517 
1518  // 1b: check if the alien has the file pointer to its definition
1519  File *file = lm->findFile(m_filenm);
1520  if (file) {
1521 
1522  // 2: check if there's the same procedure name in the file
1523  Proc *proc = file->findProc(m_displaynm);
1524 
1525  if (proc) {
1526 #if 0
1527  // 3: check if alien's line range is within the function definition
1528  bool inc = SrcFile::include(proc->begLine(), proc->endLine(), begLine(), endLine());
1529  if (inc) {
1530  // 4: add the link attribute to the function definition
1531  self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id()));
1532  }
1533 #endif
1534  self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id()));
1535  }
1536  }
1537  return self;
1538 }
1539 
1540 
1541 string
1542 Loop::toXML(uint oFlags) const
1543 {
1544  string self = ACodeNode::toXML(oFlags) + " f" + MakeAttrStr(m_filenm);
1545  return self;
1546 }
1547 
1548 
1549 string
1550 Stmt::toXML(uint oFlags) const
1551 {
1552  string self = ACodeNode::toXML(oFlags);
1553  return self;
1554 }
1555 
1556 
1557 string
1558 Ref::toXML(uint oFlags) const
1559 {
1560  string self = ACodeNode::toXML(oFlags)
1561  + " b" + MakeAttrNum(begPos) + " e" + MakeAttrNum(endPos);
1562  return self;
1563 }
1564 
1565 
1566 bool
1567 ANode::writeXML_pre(ostream& os, uint oFlags, const char* pfx) const
1568 {
1569  bool doTag = isVisible();
1570  bool doMetrics = ((oFlags & Tree::OFlg_LeafMetricsOnly) ?
1571  isLeaf() && hasMetrics() : hasMetrics());
1572  bool isXMLLeaf = isLeaf() && !doMetrics;
1573 
1574  // 1. Write element name
1575  if (doTag) {
1576  if (isXMLLeaf) {
1577  os << pfx << "<" << toXML(oFlags) << "/>\n";
1578  }
1579  else {
1580  os << pfx << "<" << toXML(oFlags) << ">\n";
1581  }
1582  }
1583 
1584  // 2. Write associated metrics
1585  if (doMetrics) {
1587  os << "\n";
1588  }
1589 
1590  return !isXMLLeaf; // whether to execute writeXML_post()
1591 }
1592 
1593 
1594 void
1595 ANode::writeXML_post(ostream& os, uint GCC_ATTR_UNUSED oFlags,
1596  const char* pfx) const
1597 {
1598  bool doTag = isVisible();
1599 
1600  if (doTag) {
1601  os << pfx << "</" << ANodeTyToXMLelement(type()) << ">\n";
1602  }
1603 }
1604 
1605 
1606 ostream&
1607 ANode::writeXML(ostream& os, uint oFlags, const char* pfx) const
1608 {
1609  // indent childen of visible nodes
1610  string indent = isVisible() ? " " : "";
1611 
1612  if (oFlags & Tree::OFlg_Compressed) {
1613  pfx = "";
1614  indent = "";
1615  }
1616 
1617  bool doPost = writeXML_pre(os, oFlags, pfx);
1618  string pfx_new = pfx + indent;
1620  it.current(); it++) {
1621  it.current()->writeXML(os, oFlags, pfx_new.c_str());
1622  }
1623  if (doPost) {
1624  writeXML_post(os, oFlags, pfx);
1625  }
1626  return os;
1627 }
1628 
1629 
1630 void
1632 {
1633  writeXML(std::cerr, Tree::OFlg_Debug);
1634 }
1635 
1636 
1637 ostream&
1638 Root::writeXML(ostream& os, uint oFlags, const char* pfx) const
1639 {
1640  if (oFlags & Tree::OFlg_Compressed) {
1641  pfx = "";
1642  }
1643 
1644  // N.B.: Assume that my children are LM's
1645  bool doPost = ANode::writeXML_pre(os, oFlags, pfx);
1647  it.current(); it++) {
1648  ANode* scope = it.current();
1649  scope->writeXML(os, oFlags, pfx);
1650  }
1651  if (doPost) {
1652  ANode::writeXML_post(os, oFlags, pfx);
1653  }
1654  return os;
1655 }
1656 
1657 
1658 ostream&
1659 LM::writeXML(ostream& os, uint oFlags, const char* pre) const
1660 {
1661  string indent = " ";
1662  if (oFlags & Tree::OFlg_Compressed) {
1663  pre = "";
1664  indent = "";
1665  }
1666 
1667  // N.B.: Assume my children are Files
1668  bool doPost = ANode::writeXML_pre(os, oFlags, pre);
1669  string prefix = pre + indent;
1671  it.current(); it++) {
1672  ANode* scope = it.current();
1673  scope->writeXML(os, oFlags, prefix.c_str());
1674  }
1675  if (doPost) {
1676  ANode::writeXML_post(os, oFlags, pre);
1677  }
1678  return os;
1679 }
1680 
1681 
1682 //***************************************************************************
1683 // ANode, etc: CSV output
1684 //***************************************************************************
1685 
1686 void
1687 ANode::CSV_DumpSelf(const Root& root, ostream& os) const
1688 {
1689  char temp[32];
1690  for (uint i = 0; i < numMetrics(); i++) {
1691  double val = (hasMetric(i) ? metric(i) : 0);
1692  os << "," << val;
1693 #if 0
1694  // FIXME: tallent: Conversioon from static perf-table to MetricDescMgr
1695  const PerfMetric& metric = IndexToPerfDataInfo(i);
1696  bool percent = metric.Percent();
1697 #else
1698  bool percent = true;
1699 #endif
1700 
1701  if (percent) {
1702  double percVal = val / root.metric(i) * 100;
1703  sprintf(temp, "%5.2lf", percVal);
1704  os << "," << temp;
1705  }
1706  }
1707  os << endl;
1708 }
1709 
1710 
1711 void
1712 ANode::CSV_dump(const Root& root, ostream& os,
1713  const char* GCC_ATTR_UNUSED file_name,
1714  const char* GCC_ATTR_UNUSED proc_name,
1715  int GCC_ATTR_UNUSED lLevel) const
1716 {
1717  // print file name, routine name, start and end line, loop level
1718  os << name() << ",,,,";
1719  CSV_DumpSelf(root, os);
1721  it.current(); it++) {
1722  it.current()->CSV_dump(root, os);
1723  }
1724 }
1725 
1726 
1727 void
1728 File::CSV_dump(const Root& root, ostream& os,
1729  const char* GCC_ATTR_UNUSED file_name,
1730  const char* GCC_ATTR_UNUSED proc_name,
1731  int GCC_ATTR_UNUSED lLevel) const
1732 {
1733  // print file name, routine name, start and end line, loop level
1734  os << baseName() << ",," << m_begLn << "," << m_endLn << ",";
1735  CSV_DumpSelf(root, os);
1737  it.current(); it++) {
1738  it.current()->CSV_dump(root, os, baseName().c_str());
1739  }
1740 }
1741 
1742 
1743 void
1744 Proc::CSV_dump(const Root& root, ostream& os,
1745  const char* file_name,
1746  const char* GCC_ATTR_UNUSED proc_name,
1747  int GCC_ATTR_UNUSED lLevel) const
1748 {
1749  // print file name, routine name, start and end line, loop level
1750  os << file_name << "," << name() << "," << m_begLn << "," << m_endLn
1751  << ",0";
1752  CSV_DumpSelf(root, os);
1754  it.current(); it++) {
1755  it.current()->CSV_dump(root, os, file_name, name().c_str(), 1);
1756  }
1757 }
1758 
1759 
1760 void
1762  const char* GCC_ATTR_UNUSED file_name,
1763  const char* GCC_ATTR_UNUSED proc_name,
1764  int GCC_ATTR_UNUSED lLevel) const
1765 {
1767 }
1768 
1769 
1770 void
1771 ACodeNode::CSV_dump(const Root& root, ostream& os,
1772  const char* file_name, const char* proc_name,
1773  int lLevel) const
1774 {
1775  ANodeTy myANodeTy = this->type();
1776  // do not display info for single lines
1777  if (myANodeTy == TyStmt)
1778  return;
1779  // print file name, routine name, start and end line, loop level
1780  os << (file_name ? file_name : name().c_str()) << ","
1781  << (proc_name ? proc_name : "") << ","
1782  << m_begLn << "," << m_endLn << ",";
1783  if (lLevel)
1784  os << lLevel;
1785  CSV_DumpSelf(root, os);
1787  it.current(); it++) {
1788  it.current()->CSV_dump(root, os, file_name, proc_name, lLevel+1);
1789  }
1790 }
1791 
1792 
1793 void
1794 Root::CSV_TreeDump(ostream& os) const
1795 {
1796  ANode::CSV_dump(*this, os);
1797 }
1798 
1799 
1800 //***************************************************************************
1801 // ANode, etc: Output and Debugging support
1802 //***************************************************************************
1803 
1804 string
1805 ANode::toString(uint oFlags, const char* pre) const
1806 {
1807  std::ostringstream os;
1808  dump(os, oFlags, pre);
1809  return os.str();
1810 }
1811 
1812 
1813 string
1815 {
1816  string str = "<" + ANodeTyToName(type()) + " uid="
1817  + StrUtil::toStr(id()) + ">";
1818  return str;
1819 }
1820 
1821 
1822 string
1823 ANode::toStringMe(uint oFlags, const char* prefix) const
1824 {
1825  std::ostringstream os;
1826  dumpme(os, oFlags, prefix);
1827  return os.str();
1828 }
1829 
1830 
1831 std::ostream&
1832 ANode::dump(ostream& os, uint oFlags, const char* pre) const
1833 {
1834  string prefix = string(pre) + " ";
1835 
1836  dumpme(os, oFlags, pre);
1837 
1838  for (uint i = 0; i < numMetrics(); i++) {
1839  os << i << " = " ;
1840  if (hasMetric(i)) {
1841  os << metric(i);
1842  }
1843  else {
1844  os << "UNDEF";
1845  }
1846  os << "; ";
1847  }
1848 
1849  for (ANodeChildIterator it(this); it.Current(); it++) {
1850  it.current()->dump(os, oFlags, prefix.c_str());
1851  }
1852  return os;
1853 }
1854 
1855 
1856 void
1858 {
1859  //writeXML(std::cerr, 0, "");
1860  dump(std::cerr, Tree::OFlg_Debug, "");
1861 }
1862 
1863 
1864 ostream&
1865 ANode::dumpme(ostream& os, uint oFlags, const char* prefix) const
1866 {
1867  os << prefix << toString_id(oFlags) << endl;
1868  return os;
1869 }
1870 
1871 
1872 ostream&
1873 ACodeNode::dumpme(ostream& os, uint oFlags, const char* prefix) const
1874 {
1875  os << prefix << toString_id(oFlags) << " "
1876  << lineRange() << " " << m_vmaSet.toString();
1877  return os;
1878 }
1879 
1880 
1881 ostream&
1882 Root::dumpme(ostream& os, uint oFlags, const char* prefix) const
1883 {
1884  os << prefix << toString_id(oFlags) << " n=" << m_name;
1885  return os;
1886 }
1887 
1888 
1889 ostream&
1890 Group::dumpme(ostream& os, uint oFlags, const char* prefix) const
1891 {
1892  os << prefix << toString_id(oFlags) << " n=" << m_name;
1893  return os;
1894 }
1895 
1896 
1897 ostream&
1898 LM::dumpme(ostream& os, uint oFlags, const char* prefix) const
1899 {
1900  os << prefix << toString_id(oFlags) << " n=" << m_name;
1901  return os;
1902 }
1903 
1904 
1905 ostream&
1906 File::dumpme(ostream& os, uint oFlags, const char* prefix) const
1907 {
1908  ACodeNode::dumpme(os, oFlags, prefix) << " n=" << m_name;
1909  return os;
1910 }
1911 
1912 
1913 ostream&
1914 Proc::dumpme(ostream& os, uint oFlags, const char* prefix) const
1915 {
1916  ACodeNode::dumpme(os, oFlags, prefix) << " n=" << m_name;
1917  return os;
1918 }
1919 
1920 
1921 ostream&
1922 Alien::dumpme(ostream& os, uint oFlags, const char* prefix) const
1923 {
1924  ACodeNode::dumpme(os, oFlags, prefix);
1925  return os;
1926 }
1927 
1928 
1929 ostream&
1930 Loop::dumpme(ostream& os, uint oFlags, const char* prefix) const
1931 {
1932  ACodeNode::dumpme(os, oFlags, prefix);
1933  return os;
1934 }
1935 
1936 
1937 ostream&
1938 Stmt::dumpme(ostream& os, uint oFlags, const char* prefix) const
1939 {
1940  ACodeNode::dumpme(os, oFlags, prefix);
1941  return os;
1942 }
1943 
1944 
1945 ostream&
1946 Ref::dumpme(ostream& os, uint oFlags, const char* prefix) const
1947 {
1948  ACodeNode::dumpme(os, oFlags, prefix);
1949  os << " pos:" << begPos << "-" << endPos;
1950  return os;
1951 }
1952 
1953 
1954 void
1956 {
1957  ostream& os = std::cerr;
1958 
1959  os << "Procedure map\n";
1960  for (VMAToProcMap::const_iterator it = m_procMap->begin();
1961  it != m_procMap->end(); ++it) {
1962  it->first.dump(os);
1963  os << " --> " << hex << "Ox" << it->second << dec << endl;
1964  }
1965 
1966  os << endl;
1967 
1968  os << "Statement map\n";
1969  for (VMAToStmtRangeMap::const_iterator it = m_stmtMap->begin();
1970  it != m_stmtMap->end(); ++it) {
1971  it->first.dump(os);
1972  os << " --> " << hex << "Ox" << it->second << dec << endl;
1973  }
1974 }
1975 
1976 
1977 //***************************************************************************
1978 // Ref specific methods
1979 //***************************************************************************
1980 
1981 void
1983 {
1984  Ref* prev = dynamic_cast<Ref*>(prevSibling());
1985  Ref* next = dynamic_cast<Ref*>(nextSibling());
1986  DIAG_Assert((prevSibling() == prev) && (nextSibling() == next), "");
1987  if (((!prev) || (prev->endPos <= begPos)) &&
1988  ((!next) || (next->begPos >= endPos))) {
1989  return;
1990  }
1991  ANode* prnt = parent();
1992  unlink();
1993  if (prnt->firstChild() == NULL) {
1994  link(prnt);
1995  }
1996  else {
1997  // insert after sibling with sibling->endPos < begPos
1998  // or iff that does not exist insert as first in sibling list
1999  ACodeNode* sibling;
2000  for (sibling = dynamic_cast<ACodeNode*>(prnt->lastChild());
2001  sibling; sibling = dynamic_cast<ACodeNode*>(sibling->prevSibling())) {
2002  Ref *ref = dynamic_cast<Ref*>(sibling);
2003  DIAG_Assert(ref == sibling, "");
2004  if (ref->endPos < begPos) {
2005  break;
2006  }
2007  }
2008  if (sibling != NULL) {
2009  Ref *nxt = dynamic_cast<Ref*>(sibling->nextSibling());
2010  DIAG_Assert((nxt == NULL) || (nxt->begPos > endPos), "");
2011  linkAfter(sibling);
2012  }
2013  else {
2014  linkBefore(prnt->FirstChild());
2015  }
2016  }
2017 }
2018 
2019 //***************************************************************************
2020 
2021 } // namespace Struct
2022 } // namespace Prof
2023 
#define DBG_FILE
Definition: Struct-Tree.cpp:98
void insertFileMap(File *file)
LM * findLM(const char *nm) const
virtual std::string XMLLineRange(uint oFlags) const
void ddumpXML() const
void Ctor(const char *filenm, ANode *parent)
My_t::iterator iterator
bool overlaps(VMAInterval x) const
virtual std::ostream & writeXML(std::ostream &os=std::cout, uint oFlags=0, const char *pre="") const
virtual void CSV_dump(const Root &root, std::ostream &os=std::cout, const char *file_name=NULL, const char *proc_name=NULL, int lLevel=0) const
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
Group * ancestorGroup() const
virtual std::string codeName() const
ANode * parent() const
unsigned int ln
Definition: SrcFile.hpp:66
static const std::string & ANodeTyToName(ANodeTy tp)
bfd_vma VMA
Definition: ISATypes.hpp:79
virtual std::string toXML(uint oFlags=0) const
void merge(const VMAIntervalSet &x)
string toStr(const int x, int base)
Definition: StrUtil.cpp:243
void checkLineRange(SrcFile::ln begLn, SrcFile::ln endLn)
std::string codeName_LM_F() const
std::string m_name
std::string toString_id(uint oFlags=0) const
virtual std::string codeName() const
void insertProcMap(Proc *proc)
ACodeNode * ACodeNodeWithLine(SrcFile::ln ln) const
virtual std::string toXML(uint oFlags=0) const
#define dyn_cast_return(base, derived, expr)
ANode * ancestor(ANodeTy type) const
Proc & operator=(const Proc &x)
LM & operator=(const LM &x)
void expandLineRange(SrcFile::ln begLn, SrcFile::ln endLn, int propagate=1)
bool include(SrcFile::ln beg1, SrcFile::ln end1, SrcFile::ln beg2, SrcFile::ln end2)
Definition: SrcFile.hpp:91
static ANodeTy IntToANodeTy(long i)
ACodeNode * nextSiblingNonOverlapping() const
virtual std::string codeName() const
const char * DIAG_Unimplemented
virtual std::string codeName() const
NonUniformDegreeTreeNode * FirstChild() const
bool isValid(SrcFile::ln line)
Definition: SrcFile.hpp:70
File & operator=(const File &x)
virtual const std::string & name() const
virtual std::string codeName() const
void insertLMMap(LM *lm)
bool equiv(bool p, bool q)
Definition: Logic.hpp:93
void linkBefore(NonUniformDegreeTreeNode *sibling)
virtual std::string toXML(uint oFlags=0) const
void setLineRange(SrcFile::ln begLn, SrcFile::ln endLn, int propagate=1)
static bool verifyMap(VMAIntervalMap< T > *mp, const char *map_nm)
double metric(size_t mId) const
virtual const std::string & name() const
bool hasMetrics(uint mBegId=Metric::IData::npos, uint mEndId=Metric::IData::npos) const
void Ctor(ACodeNode *parent, const char *filenm, const char *procnm, const char *displaynm)
static RealPathMgr & singleton()
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
virtual std::ostream & writeXML(std::ostream &os=std::cout, uint oFlags=0, const char *pre="") const
map< VMA, ProcInfo * > ProcMap
Definition: Struct-Skel.hpp:84
std::string m_name
ACodeNode * ACodeNodeParent() const
std::ostream & writeXML(std::ostream &os=std::cerr, uint oFlags=0) const
virtual const std::string & name() const
static File * demand(LM *lm, const std::string &filenm)
ANode * nextSibling() const
int compare(SrcFile::ln x, SrcFile::ln y)
Definition: SrcFile.hpp:80
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
std::string lineRange() const
const ANodeFilter ANodeTyFilter[ANode::TyNUMBER]
virtual std::string toXML(uint oFlags=0) const
virtual std::string toXML(uint oFlags=0) const
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
virtual std::ostream & writeXML(std::ostream &os=std::cout, uint oFlags=0, const char *pre="") const
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
uint numMetrics() const
const std::string & linkName() const
Root * root() const
virtual std::string toXML(uint oFlags=0) const
void setFile(std::string filenm)
std::string m_name
std::string MakeAttrStr(const char *x, int flags=ESC_TRUE)
Definition: xml.hpp:216
virtual std::string codeName() const
virtual std::string codeName() const
static char * prefix
Definition: common.c:164
Definition: xml.cpp:127
void(* T)(int code, va_list_box *box, int put(int c, void *cl), void *cl, unsigned char flags[256], int width, int precision)
Definition: fmt.h:62
File * findFile(const char *nm) const
virtual std::string codeName() const
Proc * findProc(const char *name, const char *linkname=NULL) const
static int compare(const ACodeNode *x, const ACodeNode *y)
bool realpath(std::string &pathNm) const
unsigned int uint
Definition: uint.h:124
virtual std::string XMLVMAIntervals(uint oFlags) const
map< VMA, GroupInfo * > GroupMap
Definition: Struct-Skel.hpp:83
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
void Ctor(const char *n, ACodeNode *parent, const char *ln, bool hasSym)
Stmt * findStmt(VMA vma) const
void CSV_DumpSelf(const Root &root, std::ostream &os=std::cout) const
static const std::string ScopeNames[TyNUMBER]
static int distance(ANode *ancestor, ANode *descendent)
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
Alien * ancestorAlien() const
SrcFile::ln begLine() const
VMAIntervalSet m_vmaSet
void ddump() const
Root & operator=(const Root &x)
void insertGroupMap(Group *grp)
Group * findGroup(const char *nm) const
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
std::string name() const
void link(NonUniformDegreeTreeNode *parent)
virtual void CSV_dump(const Root &root, std::ostream &os=std::cout, const char *file_name=NULL, const char *proc_name=NULL, int lLevel=0) const
void dumpmaps() const
virtual const std::string & name() const
Root * ancestorRoot() const
File * ancestorFile() const
bool isVisible() const
bool hasMetric(size_t mId) const
static bool mergePaths(ANode *lca, ANode *node_dst, ANode *node_src)
void linkAfter(NonUniformDegreeTreeNode *sibling)
virtual std::string toXML(uint oFlags=0) const
static int cmpByLine(const void *x, const void *y)
Proc * findProc(VMA vma) const
void aggregateMetrics(uint mBegId, uint mEndId)
std::string toString() const
ANode * firstChild() const
Loop * ancestorLoop() const
const VMAIntervalSet & vmaSet() const
#define DIAG_DevMsg(level,...)
Definition: diagnostics.h:246
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
bool verifyStmtMap() const
My_t::const_iterator const_iterator
void Ctor(const char *nm)
virtual void CSV_dump(const Root &root, std::ostream &os=std::cout, const char *file_name=NULL, const char *proc_name=NULL, int lLevel=0) const
map< string, FileInfo * > FileMap
Definition: Struct-Skel.hpp:80
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
std::string toStringXML(uint oFlags=0, const char *pre="") const
Ref(ACodeNode *parent, int _begPos, int _endPos, const char *refName)
virtual std::string toXML(uint oFlags=0) const
ANode * lastChild() const
bool found
Definition: cct.c:129
std::string toStringMe(uint oFlags=0, const char *pre="") const
ANode * prevSibling() const
RealPathMgr & s_realpathMgr
void Ctor(const char *nm, ANode *parent)
static LM * demand(Root *pgm, const std::string &lm_fnm)
double demandMetric(size_t mId, size_t size=0) const
virtual std::string toXML(uint oFlags=0) const
static bool isMergable(ANode *node_dst, ANode *node_src)
static ANode * leastCommonAncestor(ANode *n1, ANode *n2)
ACodeNode * ancestorProcCtxt() const
virtual void CSV_dump(const Root &root, std::ostream &os=std::cout, const char *file_name=NULL, const char *proc_name=NULL, int lLevel=0) const
virtual NonUniformDegreeTreeNode * Current() const
static const string XMLelements[ANode::TyNUMBER]
std::list< ANode * > ANodeList
Definition: Struct-Tree.hpp:96
std::string m_displaynm
SrcFile::ln endLine() const
static bool arePathsOverlapping(ANode *lca, ANode *desc1, ANode *desc2)
Stmt * ancestorStmt() const
#define NULL
Definition: ElfHelper.cpp:85
static int cmpByName(const void *x, const void *y)
virtual const std::string & name() const
std::string MakeAttrNum(int x)
Definition: xml.hpp:228
static const std::string & ANodeTyToXMLelement(ANodeTy tp)
void insertStmtMap(Stmt *stmt)
std::string toString() const
Definition: VMAInterval.cpp:93
std::ostream & dump(std::ostream &os=std::cerr, uint oFlags=0) const
Alien & operator=(const Alien &x)
ACodeNode * findByVMA(VMA vma) const
iterator find(const key_type &toFind)
std::ostream & dump(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
virtual NonUniformDegreeTreeNode * Current() const
LM * ancestorLM() const
string basename(const char *fName)
Definition: FileUtil.cpp:90
std::string m_linkname
void Ctor(const char *nm, ANode *parent)
virtual void CSV_dump(const Root &root, std::ostream &os=std::cout, const char *file_name=NULL, const char *proc_name=NULL, int lLevel=0) const
virtual std::ostream & dumpme(std::ostream &os=std::cerr, uint oFlags=0, const char *pre="") const
NonUniformDegreeTreeNode * Parent() const
bool containsLine(SrcFile::ln ln) const
#define DIAG_Die(...)
Definition: diagnostics.h:267
virtual std::string toXML(uint oFlags=0) const
virtual std::string toString(uint oFlags=0, const char *pre="") const
bool writeXML_pre(std::ostream &os=std::cout, uint oFlags=0, const char *prefix="") const
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
static Group * demand(Root *pgm, const std::string &nm, ANode *parent)
void linkAndSetLineRange(ACodeNode *parent)
virtual std::string toXML(uint oFlags=0) const
std::ostream & writeMetricsXML(std::ostream &os, const Mgr *metricMgr, uint mBegId=Metric::IData::npos, uint mEndId=Metric::IData::npos, int oFlags=0, const char *pfx="") const
<!-- ********************************************************************--> n<!-- HPCToolkit Experiment DTD --> n<!-- Version 2.1 --> n<!-- ********************************************************************--> n<!ELEMENT HPCToolkitExperiment(Header,(SecCallPathProfile|SecFlatProfile) *)> n<!ATTLIST HPCToolkitExperiment\n version CDATA #REQUIRED > n n<!-- ******************************************************************--> n n<!-- Info/NV:flexible name-value pairs:(n) ame;(t) ype;(v) alue --> n<!ELEMENT Info(NV *)> n<!ATTLIST Info\n n CDATA #IMPLIED > n<!ELEMENT NV EMPTY > n<!ATTLIST NV\n n CDATA #REQUIRED\n t CDATA #IMPLIED\n v CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Header --> n<!-- ******************************************************************--> n<!ELEMENT Header(Info *)> n<!ATTLIST Header\n n CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Section Header --> n<!-- ******************************************************************--> n<!ELEMENT SecHeader(MetricTable?, MetricDBTable?, TraceDBTable?, LoadModuleTable?, FileTable?, ProcedureTable?, Info *)> n n<!-- MetricTable:--> n<!ELEMENT MetricTable(Metric) * > n n<!-- Metric:(i) d;(n) ame --> n<!--(v) alue-type:transient type of values --> n<!--(t) ype:persistent type of metric --> n<!-- fmt:format;show;--> n<!ELEMENT Metric(MetricFormula *, Info?)> n<!ATTLIST Metric\n i CDATA #REQUIRED\n n CDATA #REQUIRED\n es CDATA #IMPLIED\n em CDATA #IMPLIED\n ep CDATA #IMPLIED\n v(raw|final|derived-incr|derived) \"raw\\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ fmt CDATA #IMPLIED\ show (1|0) \1\\ show-percent (1|0) \1> n n<!-- MetricFormula represents derived metrics: (t)ype; (frm): formula --> n<!ELEMENT MetricFormula (Info?)> n<!ATTLIST MetricFormula\ t (combine|finalize) \finalize\\ i CDATA #IMPLIED\ frm CDATA #REQUIRED> n n<!-- Metric data, used in sections: (n)ame [from Metric]; (v)alue --> n<!ELEMENT M EMPTY> n<!ATTLIST M\ n CDATA #REQUIRED\ v CDATA #REQUIRED> n n<!-- MetricDBTable: --> n<!ELEMENT MetricDBTable (MetricDB)*> n n<!-- MetricDB: (i)d; (n)ame --> n<!-- (t)ype: persistent type of metric --> n<!-- db-glob: file glob describing files in metric db --> n<!-- db-id: id within metric db --> n<!-- db-num-metrics: number of metrics in db --> n<!-- db-header-sz: size (in bytes) of a db file header --> n<!ELEMENT MetricDB EMPTY> n<!ATTLIST MetricDB\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ db-glob CDATA #IMPLIED\ db-id CDATA #IMPLIED\ db-num-metrics CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- TraceDBTable: --> n<!ELEMENT TraceDBTable (TraceDB)> n n<!-- TraceDB: (i)d --> n<!-- db-min-time: min beginning time stamp (global) --> n<!-- db-max-time: max ending time stamp (global) --> n<!ELEMENT TraceDB EMPTY> n<!ATTLIST TraceDB\ i CDATA #REQUIRED\ db-glob CDATA #IMPLIED\ db-min-time CDATA #IMPLIED\ db-max-time CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- LoadModuleTable assigns a short name to a load module --> n<!ELEMENT LoadModuleTable (LoadModule)*> n n<!ELEMENT LoadModule (Info?)> n<!ATTLIST LoadModule\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- FileTable assigns a short name to a file --> n<!ELEMENT FileTable (File)*> n n<!ELEMENT File (Info?)> n<!ATTLIST File\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- ProcedureTable assigns a short name to a procedure --> n<!ELEMENT ProcedureTable (Procedure)*> n n<!-- Info/NV: flexible name-value pairs: (n)ame; (t)ype; (v)alue --> n<!-- f: family of the procedure (fake, root, ...)--> n<!ELEMENT Procedure (Info?)> n<!ATTLIST Procedure\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ f CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Call path profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecCallPathProfile (SecHeader, SecCallPathProfileData)> n<!ATTLIST SecCallPathProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecCallPathProfileData (PF|M)*> n<!-- Procedure frame --> n<!-- (i)d: unique identifier for cross referencing --> n<!-- (s)tatic scope id --> n<!-- (n)ame: a string or an id in ProcedureTable --> n<!-- (lm) load module: a string or an id in LoadModuleTable --> n<!-- (f)ile name: a string or an id in LoadModuleTable --> n<!-- (l)ine range: \beg-end\ (inclusive range) --> n<!-- (a)lien: whether frame is alien to enclosing P --> n<!-- (str)uct: hpcstruct node id --> n<!-- (t)ype: hpcrun node type: memory access, variable declaration, ... --> n<!-- (v)ma-range-set: \{[beg-end), [beg-end)...}\ --> n<!ELEMENT PF (PF|Pr|L|C|S|M)*> n<!ATTLIST PF\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Procedure (static): GOAL: replace with 'P' --> n<!ELEMENT Pr (Pr|L|C|S|M)*> n<!ATTLIST Pr\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ a (1|0) \0\\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Callsite (a special StatementRange) --> n<!ELEMENT C (PF|M)*> n<!ATTLIST C\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Flat profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecFlatProfile (SecHeader, SecFlatProfileData)> n<!ATTLIST SecFlatProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecFlatProfileData (LM|M)*> n<!-- Load module: (i)d; (n)ame; (v)ma-range-set --> n<!ELEMENT LM (F|P|M)*> n<!ATTLIST LM\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ v CDATA #IMPLIED> n<!-- File --> n<!ELEMENT F (P|L|S|M)*> n<!ATTLIST F\ i CDATA #IMPLIED\ n CDATA #REQUIRED> n<!-- Procedure (Note 1) --> n<!ELEMENT P (P|A|L|S|C|M)*> n<!ATTLIST P\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Alien (Note 1) --> n<!ELEMENT A (A|L|S|C|M)*> n<!ATTLIST A\ i CDATA #IMPLIED\ f CDATA #IMPLIED\ n CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Loop (Note 1,2) --> n<!ELEMENT L (A|Pr|L|S|C|M)*> n<!ATTLIST L\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ f CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Statement (Note 2) --> n<!-- (it): trace record identifier --> n<!ELEMENT S (S|M)*> n<!ATTLIST S\ i CDATA #IMPLIED\ it CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Note 1: Contained Cs may not contain PFs --> n<!-- Note 2: The 's' attribute is not used for flat profiles --> n
virtual const std::string & name() const
Proc * ancestorProc() const
ACodeNode(ANodeTy ty, ANode *parent=NULL, SrcFile::ln begLn=ln_NULL, SrcFile::ln endLn=ln_NULL, VMA begVMA=0, VMA endVMA=0)
void buildMap(VMAIntervalMap< T > *&mp, ANode::ANodeTy ty) const
void CSV_TreeDump(std::ostream &os=std::cout) const
static bool merge(ANode *node_dst, ANode *node_src)
ANodeTy type() const
const ln ln_NULL
Definition: SrcFile.hpp:67
static Proc * demand(File *file, const std::string &name, const std::string &linkname, SrcFile::ln begLn=ln_NULL, SrcFile::ln endLn=ln_NULL, bool *didCreate=NULL)
static const uint npos
void writeXML_post(std::ostream &os=std::cout, uint oFlags=0, const char *prefix="") const