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

tudasc / TypeART / 23807897687

31 Mar 2026 04:21PM UTC coverage: 90.228% (-0.02%) from 90.245%
23807897687

Pull #184

github

web-flow
Merge ab63ddc36 into 8ae76f97d
Pull Request #184: Fix fwd declared types registering multiple times

28 of 28 new or added lines in 1 file covered. (100.0%)

2 existing lines in 2 files now uncovered.

4866 of 5393 relevant lines covered (90.23%)

33944.39 hits per line

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

95.61
/lib/runtime/GlobalTypeDefCallbacks.cpp
1
#include "GlobalTypeDefCallbacks.h"
2

3
#include "CallbackInterface.h"
4
#include "Runtime.h"
5
#include "RuntimeData.h"
6
#include "TypeInterface.h"
7
#include "support/Logger.h"
8
#include "typelib/TypeDatabase.h"
9

10
#include <cassert>
11
#include <cstddef>
12
#include <cstdint>
13
#include <sys/types.h>
14
#include <vector>
15

16
namespace typeart {
17

18
namespace global_types {
19
struct GlobalTypeInfoData {
20
 private:
21
  const char* name_;
22
  // Layout : [ num_member, flag, offsets...[num_member], array_sizes...[num_member] ]
23
  const std::uint16_t* data_;
24
  const GlobalTypeInfo** member_types_;
25

26
 public:
27
  [[nodiscard]] const char* name() const {
3,624✔
28
    assert(name_ != nullptr && "Name should not be NULL");
7,248✔
29
    return name_;
3,624✔
30
  }
31

32
  [[nodiscard]] const GlobalTypeInfo** member_types() const {
4,040✔
33
    return member_types_;
4,040✔
34
  }
35

36
  [[nodiscard]] uint16_t num_member() const {
5,852✔
37
    assert(data_ != nullptr && "Data should not be NULL");
11,704✔
38
    return data_[0];
5,852✔
39
  }
40

41
  [[nodiscard]] uint16_t flag() const {
1,812✔
42
    assert(data_ != nullptr && "Data should not be NULL");
3,624✔
43
    return data_[1];
1,812✔
44
  }
45

46
  [[nodiscard]] const uint16_t* offsets() const {
4,040✔
47
    return &data_[2];
4,040✔
48
  }
49

50
  [[nodiscard]] const uint16_t* array_sizes() const {
4,040✔
51
    return &data_[2 + num_member()];
4,040✔
52
  }
53
};
54
}  // namespace global_types
55

56
using namespace typeart::global_types;
57

58
class TypeInfoHandle {
59
 public:
60
  explicit TypeInfoHandle(const GlobalTypeInfo* info) : info_(info) {
6,884✔
61
  }
6,884✔
62

63
  [[nodiscard]] bool is_valid() const {
6,884✔
64
    return info_ != nullptr;
6,884✔
65
  }
66

67
  [[nodiscard]] const GlobalTypeInfo* handle() const {
11,516✔
68
    return info_;
11,516✔
69
  }
70

71
  [[nodiscard]] std::int32_t type_id() const {
4,836✔
72
    return info_->type_id;
4,836✔
73
  }
74

408✔
75
  [[nodiscard]] std::uint32_t extent() const {
1,812✔
76
    return info_->extent;
1,812✔
77
  }
78

79
  [[nodiscard]] bool is_builtin() const {
2,820✔
80
    return builtins::BuiltInQuery::is_builtin_type(type_id());
2,820✔
81
  }
82

83
  [[nodiscard]] bool has_metadata() const {
1,812✔
84
    return info_->data != nullptr;
1,812✔
85
  }
86

87
  [[nodiscard]] const char* name() const {
1,812✔
88
    return info_->data->name();
1,812✔
89
  }
90

91
  [[nodiscard]] std::uint16_t num_members() const {
1,812✔
92
    return info_->data->num_member();
1,812✔
93
  }
94

95
  [[nodiscard]] std::uint16_t flags() const {
1,812✔
96
    return info_->data->flag();
1,812✔
97
  }
98

99
  [[nodiscard]] TypeInfoHandle get_member_type(size_t index) const {
4,040✔
100
    return TypeInfoHandle(info_->data->member_types()[index]);
4,040✔
101
  }
102

103
  [[nodiscard]] std::uint16_t get_offset(size_t index) const {
4,040✔
104
    return info_->data->offsets()[index];
4,040✔
105
  }
106

107
  [[nodiscard]] std::uint16_t get_array_size(size_t index) const {
4,040✔
108
    return info_->data->array_sizes()[index];
4,040✔
109
  }
110

111
 private:
112
  const GlobalTypeInfo* info_;
113
};
114

115
#define unlikely(x)   __builtin_expect(!!(x), 0)
116
#define CONCAT_(x, y) x##y
117
#define CONCAT(x, y)  CONCAT_(x, y)
118
#define GUARDNAME     CONCAT(typeart_guard_, __LINE__)
119
#define TYPEART_RUNTIME_GUARD     \
120
  typeart::RTGuard GUARDNAME;     \
121
  if (!GUARDNAME.shouldTrack()) { \
122
    return;                       \
123
  }
124

125
class GlobalTypeTranslator::Impl {
126
  TypeDatabase& type_db_;
127
  RuntimeT::TypeLookupMapT& translator_map_;
128
  int struct_count{0};
1,216✔
129

130
 public:
131
  explicit Impl(TypeDatabase& db, RuntimeT::TypeLookupMapT& translator_map)
1,216✔
132
      : type_db_(db), translator_map_(translator_map) {
1,216✔
133
  }
1,216✔
134

135
  int next_type_id(const GlobalTypeInfo* type) {
1,812✔
136
    // a fwd_decl and the decl must have the same type_id:
137
    {
138
      const auto& struct_list            = type_db_.getStructList();
1,812✔
139
      const auto* const global_type_name = type->data->name();
1,812✔
140
      for (const auto& type_in_db : struct_list) {
18,312✔
141
        if (type_in_db.name == global_type_name) {
16,500✔
UNCOV
142
          return type_in_db.type_id;
×
143
        }
144
      }
16,500✔
145
    }
1,812✔
146
    const int id = static_cast<int>(TYPEART_NUM_RESERVED_IDS) + struct_count;
1,812✔
147
    ++struct_count;
1,812✔
148
    return id;
1,812✔
149
  }
1,812✔
150

151
  int register_t(TypeInfoHandle type_handle) {
6,884✔
152
    if (unlikely(!type_handle.is_valid())) {
6,884✔
153
      LOG_ERROR("Type descriptor is NULL, is it a weak extern global due to fwd decl?");
×
154
      return TYPEART_UNKNOWN_TYPE;
×
155
    }
156

157
    if (auto element = translator_map_.find(type_handle.handle()); element != translator_map_.end()) {
10,948✔
158
      return element->second;
4,064✔
159
    }
160

161
    if (type_handle.is_builtin()) {
2,820✔
162
      translator_map_.try_emplace(type_handle.handle(), type_handle.type_id());
1,008✔
163
      return type_handle.type_id();
1,008✔
164
    }
165

166
    assert(type_handle.has_metadata() && "Required metadata is NULL");
3,624✔
167

168
    StructTypeInfo type_descriptor;
1,812✔
169
    type_descriptor.type_id     = next_type_id(type_handle.handle());
1,812✔
170
    type_descriptor.name        = type_handle.name();
1,812✔
171
    type_descriptor.extent      = type_handle.extent();
1,812✔
172
    type_descriptor.num_members = type_handle.num_members();
1,812✔
173
    type_descriptor.flag        = static_cast<StructTypeFlag>(type_handle.flags());
1,812✔
174

175
    const auto member_count = type_descriptor.num_members;
1,812✔
176
    type_descriptor.array_sizes.reserve(member_count);
1,812✔
177
    type_descriptor.offsets.reserve(member_count);
1,812✔
178
    type_descriptor.member_types.reserve(member_count);
1,812✔
179

180
    for (size_t i = 0; i < member_count; ++i) {
5,852✔
181
      const auto member_id  = register_t(type_handle.get_member_type(i));
4,040✔
182
      const auto array_size = type_handle.get_array_size(i);
4,040✔
183
      const auto offset     = type_handle.get_offset(i);
4,040✔
184

185
      type_descriptor.array_sizes.emplace_back(array_size);
4,040✔
186
      type_descriptor.offsets.emplace_back(offset);
4,040✔
187
      type_descriptor.member_types.emplace_back(member_id);
4,040✔
188
    }
4,040✔
189

190
    const bool fwd_decl = type_descriptor.flag == StructTypeFlag::FWD_DECL;
1,812✔
191
    {
192
      LOG_DEBUG("StructTypeInfo Dump " << (fwd_decl ? "FWD" : "") << type_descriptor.name);
1,812✔
193
      LOG_DEBUG("  Type_id: " << type_descriptor.type_id);
1,812✔
194
      LOG_DEBUG("  Extent: " << type_descriptor.extent);
1,812✔
195
      LOG_DEBUG("  Num Members: " << type_descriptor.num_members);
1,812✔
196
      LOG_DEBUG("  Flag: " << static_cast<int>(type_descriptor.flag));
1,812✔
197
      for (uint32_t i = 0; i < type_descriptor.num_members; ++i) {
5,852✔
198
        LOG_DEBUG("  Member[" << i << "]: "
4,040✔
199
                              << "ID=" << type_db_.getTypeName(type_descriptor.member_types[i]) << ", Offset="
200
                              << type_descriptor.offsets[i] << ", ArraySize=" << type_descriptor.array_sizes[i]);
201
      }
4,040✔
202
    }
203

204
    type_db_.registerStruct(type_descriptor, not fwd_decl);
1,812✔
205
    translator_map_.try_emplace(type_handle.handle(), type_descriptor.type_id);
1,812✔
206

207
    return type_descriptor.type_id;
1,812✔
208
  }
6,884✔
209
};
210

211
GlobalTypeTranslator::GlobalTypeTranslator(TypeDatabase& db) : pImpl(std::make_unique<Impl>(db, translator_map)) {
1,216✔
212
}
1,216✔
213

214
GlobalTypeTranslator::~GlobalTypeTranslator() = default;
1,216✔
215

216
void GlobalTypeTranslator::register_type(const void* type) {
2,844✔
217
  const auto* info_struct                           = reinterpret_cast<const GlobalTypeInfo*>(type);
2,844✔
218
  const auto type_id                                = pImpl->register_t(TypeInfoHandle{info_struct});
2,844✔
219
  const_cast<GlobalTypeInfo*>(info_struct)->type_id = type_id;
2,844✔
220
}
2,844✔
221

222
}  // namespace typeart
223

224
void __typeart_register_type(const void* type_ptr) {
2,844✔
225
  TYPEART_RUNTIME_GUARD;
2,844✔
226
  if (unlikely(type_ptr == nullptr)) {
2,844✔
227
    LOG_FATAL("type_ptr is NULL\n");
×
228
    return;
×
229
  }
230
  typeart::RuntimeSystem::get().type_translator().register_type(type_ptr);
2,844✔
231
}
2,844✔
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