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

ahueck / llvm-dimeta / 15703160060

17 Jun 2025 09:13AM UTC coverage: 82.212% (-1.1%) from 83.355%
15703160060

Pull #45

github

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

1226 of 1777 branches covered (68.99%)

Branch coverage included in aggregate %.

197 of 203 new or added lines in 6 files covered. (97.04%)

48 existing lines in 5 files now uncovered.

2208 of 2400 relevant lines covered (92.0%)

7493.4 hits per line

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

88.7
/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,905✔
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,905✔
59
}
6,905✔
60

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

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

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

74
  if (enum_data_.is_enum) {
10,520✔
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,493✔
82

83
  return true;
10,493✔
84
}
10,520✔
85

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

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

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

99
  const auto tag = derived_type->getTag();
26,789✔
100
  switch (tag) {
26,789✔
101
    case DW_TAG_member: {
102
      make_member(derived_type);
8,311✔
103
      break;
8,311✔
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()) {
136!
109
        LOG_WARNING("Variable is not a static member. " << *derived_type)
×
110
      } else {
×
111
        make_member(derived_type);
136✔
112
      }
113
      break;
136✔
114
    }
115
    case DW_TAG_typedef:
116
      current_.typedef_names.emplace_back(derived_type->getName());
8,028✔
117
      break;
8,028✔
118
    case DW_TAG_inheritance:
119
      current_.is_base_class = true;
1,212✔
120
      current_.member_offset = derived_type->getOffsetInBits() / 8;
1,212✔
121
      break;
1,212✔
122
    case DW_TAG_pointer_type:
123
      current_.dwarf_tags.emplace_back(tag);
8,423✔
124
      // array of pointers:
125
      if (!current_.arrays.empty()) {
8,423✔
126
        current_.arrays.back().array_of_pointer = derived_type->getSizeInBits();
315✔
127
      }
315✔
128
      break;
8,423✔
129
    default:
130
      current_.dwarf_tags.emplace_back(tag);
679✔
131
  }
679✔
132

133
  if (tag == DW_TAG_pointer_type && derived_type->getBaseType() == nullptr) {
26,789✔
134
    // void* pointer has no basetype
135
    current_.type        = const_cast<llvm::DIDerivedType*>(derived_type);
560✔
136
    current_.is_void_ptr = true;
560✔
137
    events_.make_void_ptr(current_);
560✔
138
    current_ = state::MetaData{};
560✔
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,229✔
144
    assert(!stack_.empty() && "Vtable requires composite on stack");
546!
145
    // Create vtbl_ptr_type member to containing compound (first on stack)
146
    current_.type = const_cast<llvm::DIDerivedType*>(derived_type);
273✔
147
    //    current_.state = state::Entity::member;
148
    events_.make_vtable(current_);
273✔
149
    current_ = state::MetaData{};
273✔
150
  }
111✔
151

152
  return true;
26,229✔
153
}
26,789✔
154

155
bool DIEventVisitor::visitNode(const llvm::DINode* node) {
1,538✔
156
  if (const auto* enumerator = llvm::dyn_cast<llvm::DIEnumerator>(node)) {
3,076✔
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,022✔
165
    assert(!current_.arrays.empty() && "Subrange requires array composite on stack");
2,350!
166

167
    const auto subrange_constant = [&sub_range]() -> std::optional<const llvm::ConstantInt*> {
2,350✔
168
#if LLVM_VERSION_MAJOR > 19
169
      if (llvm::isa<llvm::ConstantInt*>(sub_range->getCount())) {
230!
170
        auto* count = llvm::cast<llvm::ConstantInt*>(sub_range->getCount());
230✔
171
        return count;
230✔
172
      }
230✔
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,175✔
181

182
    if (subrange_constant.has_value()) {
1,175!
183
      const auto* count = subrange_constant.value();
1,175✔
184
      auto& array       = current_.arrays.back();
1,175✔
185
      if (!count->getValue().isNegative()) {
1,175✔
186
        auto range_count = count->getValue().getLimitedValue();
1,166✔
187
        array.subranges.push_back(range_count);
1,166✔
188
      } else {
1,166✔
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,175✔
195
  } else if (const auto* sub_routine = llvm::dyn_cast<llvm::DISubroutineType>(node)) {
1,793!
196
    // LOG_FATAL(sub_routine);
197
    current_.type = const_cast<llvm::DISubroutineType*>(sub_routine);
309✔
198
    events_.make_function_ptr(current_);
309✔
199
  }
309✔
200
  return true;
1,538✔
201
}
202

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

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

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

222
  events_.make_composite(current_);
5,175✔
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,175✔
229
  current_ = state::MetaData{};
5,175✔
230

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

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

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

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

245
  if (meta_for_composite.is_member) {
5,175✔
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");
2,952!
248
    //    composite_e = state::Entity::member;
249
  }
1,476✔
250

251
  if (meta_for_composite.is_base_class) {
5,175✔
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,424!
255
    //    composite_e = state::Entity::base;
256
  }
1,212✔
257

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

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

267
  enum_data_ = EnumMeta{};
5,175✔
268
}
6,296✔
269

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

274
void DIEventVisitor::leaveNode(const llvm::DINode* node) {
1,538✔
275
  if (llvm::isa<llvm::DISubroutineType>(node)) {
1,538✔
276
    current_ = state::MetaData{};
309✔
277
  }
123✔
278
}
1,538✔
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,905✔
290
  DIEventVisitor event_visitor{event_handler};
6,905✔
291
  const bool result = event_visitor.traverseNode(node);
6,905✔
292
  if (!result) {
6,905!
293
    LOG_DEBUG("Did not parse properly: " << log::ditype_str(node));
294
  }
×
295
}
6,905✔
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