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

ahueck / llvm-dimeta / 15096846644

18 May 2025 02:18PM UTC coverage: 83.355% (+0.06%) from 83.296%
15096846644

push

github

web-flow
Merge PR #44 from ahueck/devel

1153 of 1664 branches covered (69.29%)

Branch coverage included in aggregate %.

200 of 218 new or added lines in 14 files covered. (91.74%)

1 existing line in 1 file now uncovered.

2112 of 2253 relevant lines covered (93.74%)

4268.46 hits per line

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

81.75
/lib/type/SourceLocType.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
#include "Dimeta.h"
10
#include "DimetaData.h"
11
#include "DimetaParse.h"
12
#include "support/Logger.h"
13

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

16
#include <llvm/ADT/STLExtras.h>
17
#include <optional>
18

19
namespace dimeta {
20

21
namespace scope {
22

23
std::optional<llvm::DILocalScope*> get_parent_function(const llvm::DILocation& loc) {
2,775✔
24
  auto start_scope = loc.getScope();
2,775✔
25
  return start_scope->getSubprogram();
2,775✔
26
}
2,775✔
27

28
std::string get_parent_function_name(const llvm::DILocation& loc) {
2,775✔
29
  auto sub_prog = scope::get_parent_function(loc);
2,775✔
30
  if (sub_prog) {
2,775!
31
    return std::string{sub_prog.value()->getName()};
2,775✔
32
  }
NEW
33
  return std::string{};
×
34
}
2,775✔
35

36
}  // namespace scope
37

38
std::optional<location::SourceLocation> location_for(const DimetaData& data) {
2,946✔
39
  if (data.di_location) {
2,946✔
40
    auto loc = data.di_location.value();
2,775✔
41
    return location::SourceLocation{std::string{loc->getFilename()},        //
8,325✔
42
                                    scope::get_parent_function_name(*loc),  //
2,775✔
43
                                    loc->getLine()};
2,775✔
44
  }
2,775✔
45
  if (!data.di_variable) {
171✔
46
    return {};
8✔
47
  }
48

49
  const auto make_source_loc = [](const auto* variable) {
326✔
50
    const auto file           = std::string{variable->getFilename()};
163✔
51
    const auto function_scope = [](const auto alloc) -> std::string {
489✔
52
      const auto* scope = alloc->getScope();
163✔
53
      if (scope) {
163!
54
        return std::string{scope->getName()};
157✔
55
      }
56
      return "";
6✔
57
    }(variable);
326✔
58
    return location::SourceLocation{file,            //
489✔
59
                                    function_scope,  //
163✔
60
                                    variable->getLine()};
163✔
61
  };
163✔
62

63
  if (const auto gv = std::get_if<llvm::DIGlobalVariable*>(&data.di_variable.value())) {
326!
64
    const auto* global_var = *gv;
163✔
65
    return make_source_loc(global_var);
163✔
66
  }
163✔
67

68
  if (const auto alloc_var = std::get_if<llvm::DILocalVariable*>(&data.di_variable.value())) {
×
69
    const auto* alloc = *alloc_var;
×
70
    return make_source_loc(alloc);
×
71
  }
×
72

73
  return {};
×
74
}
2,946✔
75

76
namespace detail {
77
template <class... Ts>
78
struct overload : Ts... {
79
  using Ts::operator()...;
80
};
81
template <class... Ts>
82
overload(Ts...) -> overload<Ts...>;
83

84
template <typename Type>
85
void reset_pointer_qualifier(Type& type, int ptr_level) {
2,938✔
86
  // "new" can have type_data.pointer_level != metadata pointer level -> if that is the case, we add that qualifier to
87
  // begin of list
88
  const auto add_pointer = [&](auto& f) {
5,876✔
89
    auto count = llvm::count_if(f.qual, [](auto& qual) { return qual == Qualifier::kPtr; });
5,272✔
90
    if (count < ptr_level) {
2,938✔
91
      const auto begin = f.qual.begin();
201✔
92
      f.qual.insert(begin, Qualifier{Qualifier::kPtr});
201✔
93
    }
201✔
94
  };
2,938✔
95
  std::visit(overload{[&](dimeta::QualifiedFundamental& f) -> void { add_pointer(f); },
7,713✔
96
                      [&](dimeta::QualifiedCompound& q) -> void { add_pointer(q); }},
4,039✔
97
             type);
2,938✔
98
}
2,938✔
99

100
}  // namespace detail
101

102
std::optional<LocatedType> located_type_for(const DimetaData& type_data) {
2,946✔
103
  auto loc = location_for(type_data);
2,946✔
104
  if (!loc) {
2,946✔
105
    LOG_DEBUG("Could not determine source location.");
106
    return {};
8✔
107
  }
108

109
  if (!type_data.entry_type) {
2,938!
110
    LOG_DEBUG("Could not determine type (missing entry type).");
111
    return {};
×
112
  }
113

114
  assert(type_data.entry_type.has_value() && "Parsing stack type requires entry type.");
5,876!
115

116
  // If a member is the entry type, we ignore that:
117
  auto* type = type_data.entry_type.value();
2,938✔
118
  if (const auto* derived_member_maybe = llvm::dyn_cast<llvm::DIDerivedType>(type)) {
4,845✔
119
    if (di::util::is_member(*derived_member_maybe)) {
1,907✔
120
      type = derived_member_maybe->getBaseType();
25✔
121
    }
25✔
122
  }
1,907✔
123

124
  auto dimeta_result = parser::make_dimetadata(type);
2,938✔
125
  if (!dimeta_result) {
2,938!
126
    return {};
×
127
  }
128

129
  detail::reset_pointer_qualifier(dimeta_result->type_, type_data.pointer_level);
2,938✔
130
  return LocatedType{dimeta_result->type_, loc.value()};
2,938✔
131
}
2,946✔
132

133
template <typename IRNode>
134
std::optional<LocatedType> get_located_type(const IRNode* node) {
7,519✔
135
  auto type_data = type_for(node);
7,519✔
136
  if (!type_data) {
7,519!
137
    LOG_DEBUG("Could not determine type.");
138
    return {};
4,573✔
139
  }
140
  return located_type_for(type_data.value());
2,946✔
141
}
7,519✔
142

143
std::optional<LocatedType> located_type_for(const llvm::AllocaInst* ai) {
1,905✔
144
  return get_located_type(ai);
1,905✔
145
}
146

147
std::optional<LocatedType> located_type_for(const llvm::CallBase* cb) {
5,451✔
148
  return get_located_type(cb);
5,451✔
149
}
150

151
std::optional<LocatedType> located_type_for(const llvm::GlobalVariable* gv) {
163✔
152
  return get_located_type(gv);
163✔
153
}
154

155
}  // namespace dimeta
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