• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ahueck / llvm-dimeta / 17232807523

26 Aug 2025 08:40AM UTC coverage: 72.7% (-10.7%) from 83.355%
17232807523

Pull #45

github

web-flow
Merge e7ef0be60 into c60847ea6
Pull Request #45: Disable TBAA for all cases

1701 of 2973 branches covered (57.21%)

Branch coverage included in aggregate %.

207 of 213 new or added lines in 8 files covered. (97.18%)

56 existing lines in 6 files now uncovered.

2219 of 2419 relevant lines covered (91.73%)

7456.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.85
/lib/type/DIParser.cpp
1
//  llvm-dimeta library
2
//  Copyright (c) 2022-2025 llvm-dimeta authors
3
//  Distributed under the BSD 3-Clause license.
4
//  (See accompanying file LICENSE)
5
//  SPDX-License-Identifier: BSD-3-Clause
6
//
7

8
#include "DIParser.h"
9

10
#include "DIVisitor.h"
11
#include "DimetaData.h"
12
#include "support/Logger.h"
13

14
#include <cassert>
15
#include <cstdlib>
16
#include <llvm/BinaryFormat/Dwarf.h>
17
#include <llvm/IR/Constants.h>
18
#include <llvm/IR/DebugInfoMetadata.h>
19
#include <llvm/Support/Casting.h>
20
#include <optional>
21

22
namespace dimeta::diparser {
23

24
class DIEventVisitor : public visitor::DINodeVisitor<DIEventVisitor> {
25
  // TODO visitVariable
26
 private:
27
  state::MetaData current_;
28
  state::MetaStack stack_;
29
  DIParseEvents& events_;
30
  struct EnumMeta {
31
    llvm::DIType* enum_base{nullptr};
32
    bool is_enum{false};
33
  };
34
  EnumMeta enum_data_{};
6,985✔
35

36
 public:
37
  explicit DIEventVisitor(DIParseEvents& events);
38
  ~DIEventVisitor();
39

40
  bool visitBasicType(const llvm::DIBasicType*);
41

42
  bool visitDerivedType(const llvm::DIDerivedType*);
43

44
  bool visitCompositeType(const llvm::DICompositeType*);
45

46
  bool visitNode(const llvm::DINode* node);
47
  void leaveNode(const llvm::DINode* node);
48

49
  bool visitRecurringCompositeType(const llvm::DICompositeType*);
50

51
  void leaveBasicType(const llvm::DIBasicType*);
52

53
  void leaveCompositeType(const llvm::DICompositeType*);
54

55
  void leaveRecurringCompositeType(const llvm::DICompositeType*);
56
};
57

58
DIEventVisitor::DIEventVisitor(DIParseEvents& events) : events_{events} {
6,985!
59
}
6,985✔
60

61
DIEventVisitor::~DIEventVisitor() = default;
6,985✔
62

63
bool DIEventVisitor::visitBasicType(const llvm::DIBasicType* basic_type) {
10,625✔
64
  //  state::Entity fundamental_e{state::Entity::freestanding};
65
  current_.type = const_cast<llvm::DIBasicType*>(basic_type);
10,625✔
66

67
  if (current_.is_member) {
10,625✔
68
    assert(!stack_.empty() && "Free standing fundamental requires empty stack");
12,648!
69
    //    fundamental_e = state::Entity::member;
70
  }
6,324✔
71
  // create (free-standing) fundamental (finished recursion)
72
  //  current_.state = fundamental_e;
73

74
  if (enum_data_.is_enum) {
10,625✔
75
    // pattern matches enum types
76
    //    events.make_enum_member()
77
    enum_data_.enum_base = current_.type;
27✔
78
    return true;
27✔
79
  }
80

81
  events_.make_fundamental(current_);
10,598✔
82

83
  return true;
10,598✔
84
}
10,625✔
85

86
bool DIEventVisitor::visitDerivedType(const llvm::DIDerivedType* derived_type) {
27,047✔
87
  using namespace llvm::dwarf;
88

89
  const auto make_member = [&](const auto* derived) {
35,603✔
90
    current_.member_name      = derived_type->getName();
8,556✔
91
    current_.is_member        = true;
8,556✔
92
    current_.member_offset    = derived_type->getOffsetInBits() / 8;
8,556✔
93
    current_.member_size      = derived_type->getSizeInBits() / 8;
8,556✔
94
    current_.is_member_static = derived->isStaticMember();
8,556✔
95
  };
8,556✔
96

97
  current_.derived_size = derived_type->getSizeInBits() / 8;
27,047✔
98

99
  const auto tag = derived_type->getTag();
27,047✔
100
  switch (tag) {
27,047✔
101
    case DW_TAG_member: {
102
      make_member(derived_type);
8,415✔
103
      break;
8,415✔
104
    }
105
    case DW_TAG_variable: {
106
      // see test ir/02_mpicxx.ll: Datatype has a static member,
107
      // which is encoded as a variable, and not as a member (variable)
108
      if (!derived_type->isStaticMember()) {
141!
109
        LOG_WARNING("Variable is not a static member. " << *derived_type)
×
110
      } else {
×
111
        make_member(derived_type);
141✔
112
      }
113
      break;
141✔
114
    }
115
    case DW_TAG_typedef:
116
      current_.typedef_names.emplace_back(derived_type->getName());
8,113✔
117
      break;
8,113✔
118
    case DW_TAG_inheritance:
119
      current_.is_base_class = true;
1,218✔
120
      current_.member_offset = derived_type->getOffsetInBits() / 8;
1,218✔
121
      break;
1,218✔
122
    case DW_TAG_pointer_type:
123
      current_.dwarf_tags.emplace_back(tag);
8,476✔
124
      // array of pointers:
125
      if (!current_.arrays.empty()) {
8,476✔
126
        current_.arrays.back().array_of_pointer = derived_type->getSizeInBits();
315✔
127
      }
315✔
128
      break;
8,476✔
129
    default:
130
      current_.dwarf_tags.emplace_back(tag);
684✔
131
  }
684✔
132

133
  if (tag == DW_TAG_pointer_type && derived_type->getBaseType() == nullptr) {
27,047✔
134
    // void* pointer has no basetype
135
    current_.type        = const_cast<llvm::DIDerivedType*>(derived_type);
562✔
136
    current_.is_void_ptr = true;
562✔
137
    events_.make_void_ptr(current_);
562✔
138
    current_ = state::MetaData{};
562!
139
    return true;
186✔
140
  }
141

142
  // FIXME: hacky (current_.clear()) so vtable pointer -> pointer is not applied to vtable type.
143
  if (derived_type->getName() == "__vtbl_ptr_type") {
26,485✔
144
    assert(!stack_.empty() && "Vtable requires composite on stack");
552!
145
    // Create vtbl_ptr_type member to containing compound (first on stack)
146
    current_.type = const_cast<llvm::DIDerivedType*>(derived_type);
276✔
147
    //    current_.state = state::Entity::member;
148
    events_.make_vtable(current_);
276✔
149
    current_ = state::MetaData{};
276!
150
  }
111✔
151

152
  return true;
26,485✔
153
}
27,047✔
154

155
bool DIEventVisitor::visitNode(const llvm::DINode* node) {
1,613✔
156
  if (const auto* enumerator = llvm::dyn_cast<llvm::DIEnumerator>(node)) {
3,226✔
157
    assert(enum_data_.enum_base != nullptr && "Enumerator needs a base type.");
108!
158
    current_.member_name   = enumerator->getName();
54✔
159
    current_.member_offset = 0;
54✔
160
    current_.member_size   = enum_data_.enum_base->getSizeInBits() / 8;
54✔
161
    current_.type          = enum_data_.enum_base;
54✔
162
    current_.is_member     = true;
54✔
163
    events_.make_enum_member(current_);
54✔
164
  } else if (const auto* sub_range = llvm::dyn_cast<llvm::DISubrange>(node)) {
3,172✔
165
    assert(!current_.arrays.empty() && "Subrange requires array composite on stack");
2,494!
166

167
    const auto subrange_constant = [&sub_range]() -> std::optional<const llvm::ConstantInt*> {
2,494✔
168
#if LLVM_VERSION_MAJOR > 19
169
      if (llvm::isa<llvm::ConstantInt*>(sub_range->getCount())) {
302!
170
        auto* count = llvm::cast<llvm::ConstantInt*>(sub_range->getCount());
302✔
171
        return count;
302✔
172
      }
302✔
173
#else
174
      if (sub_range->getCount().is<llvm::ConstantInt*>()) {
945!
175
        auto* count = sub_range->getCount().get<llvm::ConstantInt*>();
945✔
176
        return count;
945✔
177
      }
945✔
178
#endif
NEW
179
      return {};
×
180
    }();
1,247✔
181

182
    if (subrange_constant.has_value()) {
1,247!
183
      const auto* count = subrange_constant.value();
1,247✔
184
      auto& array       = current_.arrays.back();
1,247✔
185
      if (!count->getValue().isNegative()) {
1,247✔
186
        auto range_count = count->getValue().getLimitedValue();
1,238✔
187
        array.subranges.push_back(range_count);
1,238✔
188
      } else {
1,238✔
189
        // see test cpp/stack_static_members_array.cpp
190
        // static int[] equals subrange(count: -1), we set simply to 0 for neg. numbers
191
        array.subranges.push_back(0);
9✔
192
      }
193
      // LOG_FATAL(range_count);
194
    }
1,247✔
195
  } else if (const auto* sub_routine = llvm::dyn_cast<llvm::DISubroutineType>(node)) {
1,871!
196
    // LOG_FATAL(sub_routine);
197
    current_.type = const_cast<llvm::DISubroutineType*>(sub_routine);
312✔
198
    events_.make_function_ptr(current_);
312✔
199
  }
312✔
200
  return true;
1,613✔
201
}
202

203
bool DIEventVisitor::visitCompositeType(const llvm::DICompositeType* composite_type) {
6,453✔
204
  // See, e.g., pass/c/stack_struct_array.c:
205
  if (composite_type->getTag() == llvm::dwarf::DW_TAG_array_type) {
6,453✔
206
    current_.is_vector = composite_type->isVector();
1,193✔
207
    current_.dwarf_tags.emplace_back(current_.is_vector ? static_cast<unsigned>(state::CustomDwarfTag::kVector)
1,193✔
208
                                                        : static_cast<unsigned>(llvm::dwarf::DW_TAG_array_type));
209
    current_.arrays.emplace_back(
1,193!
210
        state::MetaData::ArrayData{composite_type->getSizeInBits(), Extent{0}, {}, composite_type->isVector()});
1,193!
211
    // current_.array_size_bits =composite_type->getSizeInBits();
212
    return true;
1,193✔
213
  }
214

215
  current_.type            = const_cast<llvm::DICompositeType*>(composite_type);
5,260✔
216
  current_.has_vtable      = composite_type->getVTableHolder() == composite_type;
5,260✔
217
  current_.is_forward_decl = composite_type->isForwardDecl();
5,260✔
218

219
  enum_data_.is_enum = composite_type->getTag() == llvm::dwarf::DW_TAG_enumeration_type;
5,260✔
220
  //  current_.state      = state::Entity::Undef;  // determined in "leave" function
221

222
  events_.make_composite(current_);
5,260✔
223

224
  // "open" a composite type parsing (everything in the follow-up depth search gets added to that
225
  // current composite, such as members).
226
  // The so-far collected current_ metadata is used when leaving the opened composite:
227
  // Clear current_, as that meta info applied to the "composite_type"
228
  stack_.emplace_back(current_);
5,260✔
229
  current_ = state::MetaData{};
5,260!
230

231
  return true;
1,701✔
232
}
2,024✔
233

234
void DIEventVisitor::leaveCompositeType(const llvm::DICompositeType* composite_type) {
6,453✔
235
  // See, e.g., pass/c/stack_struct_array.c:
236
  if (composite_type->getTag() == llvm::dwarf::DW_TAG_array_type) {
6,453✔
237
    return;
1,193✔
238
  }
239

240
  assert(!stack_.empty() && "Required metadata is missing!");
10,520!
241

242
  //  state::Entity composite_e{state::Entity::freestanding};
243
  auto meta_for_composite = stack_.pop_back_val();
5,260✔
244

245
  if (meta_for_composite.is_member) {
5,260✔
246
    // add as member with current_meta data, and add it to current back_val() composite type.
247
    assert(!stack_.empty() && "Member composite requires composite on stack");
3,048!
248
    //    composite_e = state::Entity::member;
249
  }
1,524✔
250

251
  if (meta_for_composite.is_base_class) {
5,260✔
252
    // add as base class to back_val() composite type
253
    //    assert(composite_e != state::Entity::member);
254
    assert(!stack_.empty() && "Base composite requires composite on stack");
2,436!
255
    //    composite_e = state::Entity::base;
256
  }
1,218✔
257

258
  if (!(meta_for_composite.is_member || meta_for_composite.is_base_class)) {
5,260✔
259
    // create (free-standing) compound (finished recursion)
260
    assert(stack_.empty() && "Free standing composite requires empty stack");
5,036!
261
    //    assert(composite_e == state::Entity::freestanding);
262
  }
2,518✔
263

264
  //  meta_for_composite.state = composite_e;
265
  events_.finalize_composite(meta_for_composite);
5,260!
266

267
  enum_data_ = EnumMeta{};
5,260✔
268
}
6,453✔
269

270
void DIEventVisitor::leaveBasicType(const llvm::DIBasicType*) {
10,625✔
271
  current_ = state::MetaData{};
10,625!
272
}
3,462✔
273

274
void DIEventVisitor::leaveNode(const llvm::DINode* node) {
1,613✔
275
  if (llvm::isa<llvm::DISubroutineType>(node)) {
1,613✔
276
    current_ = state::MetaData{};
312!
277
  }
123✔
278
}
1,613✔
279

280
bool DIEventVisitor::visitRecurringCompositeType(const llvm::DICompositeType* recurring_composite) {
297✔
281
  current_.is_recurring = true;
297✔
282
  return this->visitCompositeType(recurring_composite);
297✔
283
}
284

285
void DIEventVisitor::leaveRecurringCompositeType(const llvm::DICompositeType* recurring_composite) {
297✔
286
  this->leaveCompositeType(recurring_composite);
297✔
287
}
297✔
288

289
void visit_node(const llvm::DINode* node, DIParseEvents& event_handler) {
6,985✔
290
  DIEventVisitor event_visitor{event_handler};
6,985✔
291
  const bool result = event_visitor.traverseNode(node);
6,985!
292
  if (!result) {
6,985!
293
    LOG_DEBUG("Did not parse properly: " << log::ditype_str(node));
294
  }
×
295
}
6,985✔
296

297
}  // namespace dimeta::diparser
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc