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

ahueck / llvm-dimeta / 15704939135

17 Jun 2025 10:36AM UTC coverage: 82.212% (-1.1%) from 83.355%
15704939135

Pull #45

github

web-flow
Merge 4b9d36bb5 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%)

7661.86 hits per line

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

78.71
/lib/type/DIUtil.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 "DIUtil.h"
9

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

13
#include "llvm/IR/DebugInfoMetadata.h"
14
#include "llvm/IR/Metadata.h"
15

16
#include <llvm/BinaryFormat/Dwarf.h>
17
#include <optional>
18

19
namespace dimeta::di::util {
20

21
namespace printer {
22

23
class DIPrinter : public visitor::DINodeVisitor<DIPrinter> {
24
 private:
25
  llvm::raw_ostream& outp_;
26
  std::optional<const llvm::Module*> module_;
27

28
  std::string no_pointer_str(const llvm::Metadata& type) {
72✔
29
    std::string view;
72✔
30
    llvm::raw_string_ostream rso(view);
72✔
31
    type.print(rso, module_.value_or(nullptr));
72✔
32

33
    if (module_) {
72!
34
      return rso.str();
72✔
35
    }
36
    const llvm::StringRef ref(rso.str());
×
37
    const auto a_pos = ref.find("=");
×
38
    if (a_pos == llvm::StringRef::npos || (a_pos + 2) > ref.size()) {
×
39
      return ref.str();
×
40
    }
41

42
    return std::string{ref.substr(a_pos + 2)};
×
43
  }
72✔
44

45
  [[nodiscard]] unsigned width() const {
72✔
46
    return depth() == 1 ? 0 : depth();
72✔
47
  }
48

49
 public:
50
  explicit DIPrinter(llvm::raw_ostream& outp, const llvm::Module* mod = nullptr) : outp_(outp), module_(mod) {
9✔
51
  }
9✔
52

53
  bool visitVariable(const llvm::DIVariable* var) {
9✔
54
    outp_ << llvm::left_justify("", width()) << no_pointer_str(*var) << "\n";
9✔
55
    return true;
9✔
56
  }
57

58
  bool visitNode(const llvm::DINode* var) {
×
59
    outp_ << llvm::left_justify("", width() + 3) << no_pointer_str(*var) << "\n";
×
60
    return true;
×
61
  }
62

63
  bool visitBasicType(const llvm::DIBasicType* basic_type) {
×
64
    outp_ << llvm::left_justify("", width() + 3) << no_pointer_str(*basic_type) << "\n";
×
65
    return true;
×
66
  }
67

68
  bool visitDerivedType(const llvm::DIDerivedType* derived_type) {
36✔
69
    outp_ << llvm::left_justify("", width()) << no_pointer_str(*derived_type) << "\n";
36✔
70
    return true;
36✔
71
  }
72

73
  bool visitCompositeType(const llvm::DICompositeType* composite_type) {
18✔
74
    outp_ << llvm::left_justify("", width()) << no_pointer_str(*composite_type) << "\n";
18✔
75
    return true;
18✔
76
  }
77

78
  bool visitRecurringCompositeType(const llvm::DICompositeType* composite_type) {
9✔
79
    outp_ << llvm::left_justify("", width()) << "**" << no_pointer_str(*composite_type) << "\n";
9✔
80
    return true;
9✔
81
  }
82
};
83

84
}  // namespace printer
85

86
void print_dinode(llvm::DINode* node, llvm::raw_ostream& outs, llvm::Module* module) {
9✔
87
  printer::DIPrinter printer{outs, module};
9✔
88
  assert((llvm::isa<llvm::DIVariable>(node) || llvm::isa<llvm::DIType>(node)) && "Can only print variable or type");
18!
89
  printer.traverseNode(node);
9✔
90
}
9✔
91

92
struct DestructureComposite : visitor::DINodeVisitor<DestructureComposite> {
93
  explicit DestructureComposite(const size_t index) : byte_index_{index} {
496✔
94
  }
496✔
95

96
  [[nodiscard]] std::optional<StructMember> result() const {
496✔
97
    return this->outermost_candidate_;
496✔
98
  }
99

100
  bool visitCompositeType(const llvm::DICompositeType* composite) const {
1,194✔
101
    LOG_DEBUG("visitCompositeType: " << log::ditype_str(composite) << ": " << composite->getName()
102
                                     << " index: " << byte_index_ << " offset base: " << this->offset_base_);
103
    return true;
1,194✔
104
  }
105

106
  bool visitDerivedType(const llvm::DIDerivedType* derived_ty) {
3,438✔
107
    if (derived_ty->getTag() != llvm::dwarf::DW_TAG_member) {
3,438✔
108
      return true;
1,110✔
109
    }
110
    // assert(derived_ty->getTag() == llvm::dwarf::DW_TAG_member && "Expected member element in composite ty");
111
    LOG_DEBUG("looking @ member: " << derived_ty->getName() << " offset: " << derived_ty->getOffsetInBits() / 8
112
                                   << " size: " << derived_ty->getSizeInBits() / 8);
113

114
    const auto deriv_offset = (derived_ty->getOffsetInBits() / 8);
2,328✔
115
    const auto deriv_size   = (derived_ty->getSizeInBits() / 8);
2,328✔
116
    const auto offset       = this->offset_base_ + deriv_offset;
2,328✔
117
    const auto lower_bound  = offset;
2,328✔
118
    const auto upper_bound  = offset + deriv_size;
2,328✔
119

120
    if (byte_index_ >= lower_bound && byte_index_ < upper_bound) {
2,328✔
121
      auto* const member_base_type = derived_ty->getBaseType();
774✔
122

123
      LOG_DEBUG("saving candidate member type " << log::ditype_str(member_base_type));
124

125
      this->outermost_candidate_.emplace(StructMember{const_cast<llvm::DIDerivedType*>(derived_ty), member_base_type});
774✔
126

127
      if (is_pointer_like(*member_base_type) || member_base_type->getTag() == llvm::dwarf::DW_TAG_array_type) {
774✔
128
        LOG_DEBUG("Terminating recursion, found pointer-like "
129
                  << is_pointer_like(*member_base_type) << " or array-like "
130
                  << (member_base_type->getTag() == llvm::dwarf::DW_TAG_array_type))
131
        return false;  // if offset matches, and its a pointer-like, we do not need to recurse.
490✔
132
      }
133

134
      // We should only ever be able to recurse into one composite type where the offset condition holds, so
135
      // save the offset base for that member.
136
      if (llvm::isa<llvm::DICompositeType>(member_base_type)) {
284✔
137
        LOG_DEBUG("setting offset base to: " << offset);
138
        this->offset_base_ = offset;
246✔
139
      }
246✔
140
    }
774✔
141
    return true;
1,838✔
142
  }
3,438✔
143

144
 private:
145
  size_t byte_index_;
146
  size_t offset_base_{};
496✔
147
  std::optional<StructMember> outermost_candidate_{};
496✔
148
};
149

150
std::optional<StructMember> resolve_byte_offset_to_member_of(const llvm::DICompositeType* composite, size_t offset) {
496✔
151
  DestructureComposite visitor{offset};
496✔
152
  visitor.traverseCompositeType(composite);
496✔
153
  return visitor.result();
496✔
154
}
496✔
155

156
bool is_pointer(const llvm::DIType& di_type) {
4,548✔
157
  if (const auto* type = llvm::dyn_cast<llvm::DIDerivedType>(&di_type)) {
9,096!
158
    return type->getTag() == llvm::dwarf::DW_TAG_reference_type || type->getTag() == llvm::dwarf::DW_TAG_pointer_type;
4,548✔
159
  }
160
  return false;
×
161
}
4,548✔
162

163
bool is_pointer_like(const llvm::DIType& di_type) {
1,986✔
164
  if (const auto* type = llvm::dyn_cast<llvm::DIDerivedType>(&di_type)) {
3,566!
165
    return type->getTag() == llvm::dwarf::DW_TAG_array_type || type->getTag() == llvm::dwarf::DW_TAG_reference_type ||
3,160!
166
           type->getTag() == llvm::dwarf::DW_TAG_pointer_type ||
1,580✔
167
           type->getTag() == llvm::dwarf::DW_TAG_ptr_to_member_type;
50✔
168
  }
169
  return false;
406✔
170
}
1,986✔
171

172
bool is_non_static_member(const llvm::DINode& elem) {
5,730✔
173
  return elem.getTag() == llvm::dwarf::DW_TAG_member &&
9,452✔
174
         llvm::cast<llvm::DIType>(elem).getFlags() != llvm::DINode::DIFlags::FlagStaticMember;
3,722✔
175
}
176

177
bool is_member(const llvm::DINode& elem) {
7,746✔
178
  const auto* type = llvm::dyn_cast<llvm::DIType>(&elem);
7,746✔
179
  return elem.getTag() == llvm::dwarf::DW_TAG_member ||
13,398✔
180
         ((type != nullptr) && (type->getFlags() == llvm::DINode::DIFlags::FlagStaticMember));
5,652!
181
}
7,746✔
182

183
size_t get_num_composite_members(const llvm::DICompositeType& composite) {
18✔
184
  const auto num_members =
36✔
185
      llvm::count_if(composite.getElements(), [&](const auto* node) { return is_non_static_member(*node); });
132✔
186
  return num_members;
36✔
187
}
18✔
188

UNCOV
189
llvm::SmallVector<llvm::DIDerivedType*, 4> get_composite_members(const llvm::DICompositeType& composite) {
×
UNCOV
190
  llvm::SmallVector<llvm::DIDerivedType*, 4> members;
×
UNCOV
191
  for (auto* member : composite.getElements()) {
×
UNCOV
192
    if (is_non_static_member(*member)) {
×
UNCOV
193
      members.push_back(llvm::dyn_cast<llvm::DIDerivedType>(member));
×
UNCOV
194
    }
×
UNCOV
195
  }
×
UNCOV
196
  return members;
×
UNCOV
197
}
×
198

199
std::optional<llvm::DICompositeType*> desugar(llvm::DIType& qualified_composite, int pointer_level) {
1,522✔
200
  llvm::DIType* type = &qualified_composite;
1,522✔
201
  int reached_level{0};
1,522✔
202
  while (type && llvm::isa<llvm::DIDerivedType>(type)) {
4,402✔
203
    if (reached_level > pointer_level) {
3,134✔
204
      break;
254✔
205
    }
206
    auto* ditype = llvm::dyn_cast<llvm::DIDerivedType>(type);
2,880✔
207
    if (is_pointer(*ditype)) {
2,880✔
208
      reached_level++;
2,094✔
209
    }
2,094✔
210
    type = ditype->getBaseType();
2,880✔
211
  }
2,880✔
212

213
  if (auto* comp = llvm::dyn_cast_or_null<llvm::DICompositeType>(type)) {
1,844✔
214
    return comp;
322✔
215
  }
216
  return {};
1,200✔
217
}
1,522✔
218

219
// bool has_tbaa(const llvm::Instruction& inst) {
220
//   auto* access = inst.getMetadata(llvm::StringRef{"tbaa"});
221
//   return access != nullptr;
222
// }
223

224
bool is_array_member(const llvm::DINode& elem) {
3,772✔
225
  return is_member(elem) &&
5,704✔
226
         llvm::dyn_cast<llvm::DIDerivedType>(&elem)->getBaseType()->getTag() == llvm::dwarf::DW_TAG_array_type;
1,932✔
227
}
228

229
bool is_array(const llvm::DINode& elem) {
1,806✔
230
  auto comp = llvm::dyn_cast<llvm::DICompositeType>(&elem);
1,806✔
231
  return (comp != nullptr) && comp->getTag() == llvm::dwarf::DW_TAG_array_type;
1,806✔
232
}
1,806✔
233

234
}  // namespace dimeta::di::util
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