1226584Sdim//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim
10226584Sdim#include "DWARFDebugAbbrev.h"
11226584Sdim#include "llvm/Support/Format.h"
12226584Sdim#include "llvm/Support/raw_ostream.h"
13226584Sdimusing namespace llvm;
14226584Sdim
15226584Sdimbool DWARFAbbreviationDeclarationSet::extract(DataExtractor data,
16226584Sdim                                              uint32_t* offset_ptr) {
17226584Sdim  const uint32_t beginOffset = *offset_ptr;
18226584Sdim  Offset = beginOffset;
19226584Sdim  clear();
20226584Sdim  DWARFAbbreviationDeclaration abbrevDeclaration;
21226584Sdim  uint32_t prevAbbrAode = 0;
22226584Sdim  while (abbrevDeclaration.extract(data, offset_ptr)) {
23226584Sdim    Decls.push_back(abbrevDeclaration);
24226584Sdim    if (IdxOffset == 0) {
25226584Sdim      IdxOffset = abbrevDeclaration.getCode();
26226584Sdim    } else {
27226584Sdim      if (prevAbbrAode + 1 != abbrevDeclaration.getCode())
28226584Sdim        IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups
29226584Sdim    }
30226584Sdim    prevAbbrAode = abbrevDeclaration.getCode();
31226584Sdim  }
32226584Sdim  return beginOffset != *offset_ptr;
33226584Sdim}
34226584Sdim
35226584Sdimvoid DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
36226584Sdim  for (unsigned i = 0, e = Decls.size(); i != e; ++i)
37226584Sdim    Decls[i].dump(OS);
38226584Sdim}
39226584Sdim
40226584Sdimconst DWARFAbbreviationDeclaration*
41226584SdimDWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode)
42226584Sdim  const {
43226584Sdim  if (IdxOffset == UINT32_MAX) {
44226584Sdim    DWARFAbbreviationDeclarationCollConstIter pos;
45226584Sdim    DWARFAbbreviationDeclarationCollConstIter end = Decls.end();
46226584Sdim    for (pos = Decls.begin(); pos != end; ++pos) {
47226584Sdim      if (pos->getCode() == abbrCode)
48226584Sdim        return &(*pos);
49226584Sdim    }
50226584Sdim  } else {
51226584Sdim    uint32_t idx = abbrCode - IdxOffset;
52226584Sdim    if (idx < Decls.size())
53226584Sdim      return &Decls[idx];
54226584Sdim  }
55226584Sdim  return NULL;
56226584Sdim}
57226584Sdim
58226584SdimDWARFDebugAbbrev::DWARFDebugAbbrev() :
59226584Sdim  AbbrevCollMap(),
60226584Sdim  PrevAbbrOffsetPos(AbbrevCollMap.end()) {}
61226584Sdim
62226584Sdim
63226584Sdimvoid DWARFDebugAbbrev::parse(DataExtractor data) {
64226584Sdim  uint32_t offset = 0;
65226584Sdim
66226584Sdim  while (data.isValidOffset(offset)) {
67226584Sdim    uint32_t initial_cu_offset = offset;
68226584Sdim    DWARFAbbreviationDeclarationSet abbrevDeclSet;
69226584Sdim
70226584Sdim    if (abbrevDeclSet.extract(data, &offset))
71226584Sdim      AbbrevCollMap[initial_cu_offset] = abbrevDeclSet;
72226584Sdim    else
73226584Sdim      break;
74226584Sdim  }
75226584Sdim  PrevAbbrOffsetPos = AbbrevCollMap.end();
76226584Sdim}
77226584Sdim
78226584Sdimvoid DWARFDebugAbbrev::dump(raw_ostream &OS) const {
79226584Sdim  if (AbbrevCollMap.empty()) {
80226584Sdim    OS << "< EMPTY >\n";
81226584Sdim    return;
82226584Sdim  }
83226584Sdim
84226584Sdim  DWARFAbbreviationDeclarationCollMapConstIter pos;
85226584Sdim  for (pos = AbbrevCollMap.begin(); pos != AbbrevCollMap.end(); ++pos) {
86234353Sdim    OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", pos->first);
87226584Sdim    pos->second.dump(OS);
88226584Sdim  }
89226584Sdim}
90226584Sdim
91226584Sdimconst DWARFAbbreviationDeclarationSet*
92226584SdimDWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const {
93226584Sdim  DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end();
94226584Sdim  DWARFAbbreviationDeclarationCollMapConstIter pos;
95226584Sdim  if (PrevAbbrOffsetPos != end &&
96226584Sdim      PrevAbbrOffsetPos->first == cu_abbr_offset) {
97226584Sdim    return &(PrevAbbrOffsetPos->second);
98226584Sdim  } else {
99226584Sdim    pos = AbbrevCollMap.find(cu_abbr_offset);
100226584Sdim    PrevAbbrOffsetPos = pos;
101226584Sdim  }
102226584Sdim
103226584Sdim  if (pos != AbbrevCollMap.end())
104226584Sdim    return &(pos->second);
105226584Sdim  return NULL;
106226584Sdim}
107