1ac7ddfbfSEd Maste //===-- StackID.cpp ---------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
104bb0738eSEd Maste #include "lldb/Target/StackID.h"
11ac7ddfbfSEd Maste #include "lldb/Symbol/Block.h"
12ac7ddfbfSEd Maste #include "lldb/Symbol/Symbol.h"
13ac7ddfbfSEd Maste #include "lldb/Symbol/SymbolContext.h"
14f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
15ac7ddfbfSEd Maste 
16ac7ddfbfSEd Maste using namespace lldb_private;
17ac7ddfbfSEd Maste 
Dump(Stream * s)18435933ddSDimitry Andric void StackID::Dump(Stream *s) {
19435933ddSDimitry Andric   s->Printf("StackID (pc = 0x%16.16" PRIx64 ", cfa = 0x%16.16" PRIx64
20435933ddSDimitry Andric             ", symbol_scope = %p",
210127ef0fSEd Maste             m_pc, m_cfa, static_cast<void *>(m_symbol_scope));
22435933ddSDimitry Andric   if (m_symbol_scope) {
23ac7ddfbfSEd Maste     SymbolContext sc;
24ac7ddfbfSEd Maste 
25ac7ddfbfSEd Maste     m_symbol_scope->CalculateSymbolContext(&sc);
26ac7ddfbfSEd Maste     if (sc.block)
27ac7ddfbfSEd Maste       s->Printf(" (Block {0x%8.8" PRIx64 "})", sc.block->GetID());
28ac7ddfbfSEd Maste     else if (sc.symbol)
29ac7ddfbfSEd Maste       s->Printf(" (Symbol{0x%8.8x})", sc.symbol->GetID());
30ac7ddfbfSEd Maste   }
31ac7ddfbfSEd Maste   s->PutCString(") ");
32ac7ddfbfSEd Maste }
33ac7ddfbfSEd Maste 
operator ==(const StackID & lhs,const StackID & rhs)34435933ddSDimitry Andric bool lldb_private::operator==(const StackID &lhs, const StackID &rhs) {
35ac7ddfbfSEd Maste   if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress())
36ac7ddfbfSEd Maste     return false;
37ac7ddfbfSEd Maste 
38ac7ddfbfSEd Maste   SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope();
39ac7ddfbfSEd Maste   SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope();
40ac7ddfbfSEd Maste 
414bb0738eSEd Maste   // Only compare the PC values if both symbol context scopes are nullptr
424bb0738eSEd Maste   if (lhs_scope == nullptr && rhs_scope == nullptr)
43ac7ddfbfSEd Maste     return lhs.GetPC() == rhs.GetPC();
44ac7ddfbfSEd Maste 
45ac7ddfbfSEd Maste   return lhs_scope == rhs_scope;
46ac7ddfbfSEd Maste }
47ac7ddfbfSEd Maste 
operator !=(const StackID & lhs,const StackID & rhs)48435933ddSDimitry Andric bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) {
49ac7ddfbfSEd Maste   if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress())
50ac7ddfbfSEd Maste     return true;
51ac7ddfbfSEd Maste 
52ac7ddfbfSEd Maste   SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope();
53ac7ddfbfSEd Maste   SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope();
54ac7ddfbfSEd Maste 
554bb0738eSEd Maste   if (lhs_scope == nullptr && rhs_scope == nullptr)
56ac7ddfbfSEd Maste     return lhs.GetPC() != rhs.GetPC();
57ac7ddfbfSEd Maste 
58ac7ddfbfSEd Maste   return lhs_scope != rhs_scope;
59ac7ddfbfSEd Maste }
60ac7ddfbfSEd Maste 
operator <(const StackID & lhs,const StackID & rhs)61435933ddSDimitry Andric bool lldb_private::operator<(const StackID &lhs, const StackID &rhs) {
62ac7ddfbfSEd Maste   const lldb::addr_t lhs_cfa = lhs.GetCallFrameAddress();
63ac7ddfbfSEd Maste   const lldb::addr_t rhs_cfa = rhs.GetCallFrameAddress();
64ac7ddfbfSEd Maste 
65435933ddSDimitry Andric   // FIXME: We are assuming that the stacks grow downward in memory.  That's not
66435933ddSDimitry Andric   // necessary, but true on
67435933ddSDimitry Andric   // all the machines we care about at present.  If this changes, we'll have to
68*4ba319b5SDimitry Andric   // deal with that.  The ABI is the agent who knows this ordering, but the
69*4ba319b5SDimitry Andric   // StackID has no access to the ABI. The most straightforward way to handle
70*4ba319b5SDimitry Andric   // this is to add a "m_grows_downward" bool to the StackID, and set it in the
71*4ba319b5SDimitry Andric   // constructor. But I'm not going to waste a bool per StackID on this till we
72*4ba319b5SDimitry Andric   // need it.
73ac7ddfbfSEd Maste 
74ac7ddfbfSEd Maste   if (lhs_cfa != rhs_cfa)
75ac7ddfbfSEd Maste     return lhs_cfa < rhs_cfa;
76ac7ddfbfSEd Maste 
77ac7ddfbfSEd Maste   SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope();
78ac7ddfbfSEd Maste   SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope();
79ac7ddfbfSEd Maste 
80435933ddSDimitry Andric   if (lhs_scope != nullptr && rhs_scope != nullptr) {
81ac7ddfbfSEd Maste     // Same exact scope, lhs is not less than (younger than rhs)
82ac7ddfbfSEd Maste     if (lhs_scope == rhs_scope)
83ac7ddfbfSEd Maste       return false;
84ac7ddfbfSEd Maste 
85ac7ddfbfSEd Maste     SymbolContext lhs_sc;
86ac7ddfbfSEd Maste     SymbolContext rhs_sc;
87ac7ddfbfSEd Maste     lhs_scope->CalculateSymbolContext(&lhs_sc);
88ac7ddfbfSEd Maste     rhs_scope->CalculateSymbolContext(&rhs_sc);
89ac7ddfbfSEd Maste 
90ac7ddfbfSEd Maste     // Items with the same function can only be compared
91435933ddSDimitry Andric     if (lhs_sc.function == rhs_sc.function && lhs_sc.function != nullptr &&
92435933ddSDimitry Andric         lhs_sc.block != nullptr && rhs_sc.function != nullptr &&
93435933ddSDimitry Andric         rhs_sc.block != nullptr) {
94ac7ddfbfSEd Maste       return rhs_sc.block->Contains(lhs_sc.block);
95ac7ddfbfSEd Maste     }
96ac7ddfbfSEd Maste   }
97ac7ddfbfSEd Maste   return false;
98ac7ddfbfSEd Maste }
99