172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
272c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//
372c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//                     The LLVM Compiler Infrastructure
472c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//
572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer// This file is distributed under the University of Illinois Open Source
672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer// License. See LICENSE.TXT for details.
772c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//
872c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer//===----------------------------------------------------------------------===//
972c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
1172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer#include "llvm/Support/Format.h"
1272c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer#include "llvm/Support/raw_ostream.h"
1372c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramerusing namespace llvm;
1472c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
15dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesDWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
1672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  clear();
17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
19dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid DWARFAbbreviationDeclarationSet::clear() {
20dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Offset = 0;
21dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  FirstAbbrCode = 0;
22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Decls.clear();
23dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
24dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
25dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
26dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                              uint32_t *OffsetPtr) {
27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  clear();
28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const uint32_t BeginOffset = *OffsetPtr;
29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Offset = BeginOffset;
30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  DWARFAbbreviationDeclaration AbbrDecl;
31dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  uint32_t PrevAbbrCode = 0;
32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  while (AbbrDecl.extract(Data, OffsetPtr)) {
33dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (FirstAbbrCode == 0) {
34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      FirstAbbrCode = AbbrDecl.getCode();
3572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer    } else {
36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // Codes are not consecutive, can't do O(1) lookups.
38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        FirstAbbrCode = UINT32_MAX;
39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      }
4072c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer    }
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    PrevAbbrCode = AbbrDecl.getCode();
4237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    Decls.push_back(std::move(AbbrDecl));
4372c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return BeginOffset != *OffsetPtr;
4572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
4672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
4772c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramervoid DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const auto &Decl : Decls)
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Decl.dump(OS);
5072c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
5172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesconst DWARFAbbreviationDeclaration *
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesDWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    uint32_t AbbrCode) const {
55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (FirstAbbrCode == UINT32_MAX) {
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const auto &Decl : Decls) {
57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (Decl.getCode() == AbbrCode)
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return &Decl;
5972c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer    }
60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
6172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return &Decls[AbbrCode - FirstAbbrCode];
6572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
6672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesDWARFDebugAbbrev::DWARFDebugAbbrev() {
68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  clear();
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
7072c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
71dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid DWARFDebugAbbrev::clear() {
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AbbrDeclSets.clear();
73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  PrevAbbrOffsetPos = AbbrDeclSets.end();
74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
7572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid DWARFDebugAbbrev::extract(DataExtractor Data) {
77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  clear();
7872c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
79dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  uint32_t Offset = 0;
80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  DWARFAbbreviationDeclarationSet AbbrDecls;
81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  while (Data.isValidOffset(Offset)) {
82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    uint32_t CUAbbrOffset = Offset;
83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!AbbrDecls.extract(Data, &Offset))
8472c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer      break;
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    AbbrDeclSets[CUAbbrOffset] = std::move(AbbrDecls);
8672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
8772c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
8872c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
8972c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramervoid DWARFDebugAbbrev::dump(raw_ostream &OS) const {
90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (AbbrDeclSets.empty()) {
9172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer    OS << "< EMPTY >\n";
9272c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer    return;
9372c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
9472c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
95dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  for (const auto &I : AbbrDeclSets) {
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    I.second.dump(OS);
9872c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
9972c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
10072c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
10172c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramerconst DWARFAbbreviationDeclarationSet*
102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesDWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const auto End = AbbrDeclSets.end();
104dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
1054aa3fea8b13b91800c908f8e7d74fad96adba69aBenjamin Kramer    return &(PrevAbbrOffsetPos->second);
10672c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer  }
10772c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (Pos != End) {
110dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    PrevAbbrOffsetPos = Pos;
111dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return &(Pos->second);
112dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
113dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
114dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return nullptr;
11572c0d7fdd3d0930c7507060e96aec7d7429a8190Benjamin Kramer}
116