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

tudasc / TypeART / 25212948956

01 May 2026 11:37AM UTC coverage: 89.288% (-1.0%) from 90.246%
25212948956

Pull #188

github

web-flow
Merge f285f0e8f into 278119205
Pull Request #188: GPU memory allocation support

214 of 298 new or added lines in 20 files covered. (71.81%)

1 existing line in 1 file now uncovered.

5076 of 5685 relevant lines covered (89.29%)

43440.6 hits per line

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

91.07
/lib/passes/typegen/dimeta/DimetaTypeGen.cpp
1
// TypeART library
2
//
3
// Copyright (c) 2017-2026 TypeART Authors
4
// Distributed under the BSD 3-Clause license.
5
// (See accompanying file LICENSE.txt or copy at
6
// https://opensource.org/licenses/BSD-3-Clause)
7
//
8
// Project home: https://github.com/tudasc/TypeART
9
//
10
// SPDX-License-Identifier: BSD-3-Clause
11
//
12

13
#include "../TypeIDGenerator.h"
14
#include "Dimeta.h"
15
#include "DimetaData.h"
16
#include "analysis/MemOpData.h"
17
#include "support/GpuUtil.h"
18
#include "support/Logger.h"
19
#include "typegen/TypeGenerator.h"
20
#include "typelib/TypeDatabase.h"
21
#include "typelib/TypeInterface.h"
22

23
#include "llvm/ADT/StringExtras.h"
24
#include "llvm/Support/MD5.h"
25

26
#include <cassert>
27
#include <cstddef>
28
#include <cstdint>
29
#include <iterator>
30
#include <llvm/ADT/STLExtras.h>
31
#include <llvm/IR/GlobalVariable.h>
32
#include <llvm/IR/InstrTypes.h>
33
#include <llvm/IR/Instructions.h>
34
#include <llvm/Support/Casting.h>
35
#include <memory>
36
#include <string>
37
#include <type_traits>
38

39
namespace llvm {
40
class DataLayout;
41
class StructType;
42
class Type;
43
class VectorType;
44
}  // namespace llvm
45

46
namespace typeart::types {
47

48
template <class... Ts>
49
struct overload : Ts... {
50
  using Ts::operator()...;
51
};
52
template <class... Ts>
53
overload(Ts...) -> overload<Ts...>;
54

55
template <typename Type>
56
std::pair<std::optional<typeart_builtin_type>, int> typeid_if_ptr(const Type& type) {
52,104✔
57
  using namespace dimeta;
58
  const auto& quals = type.qual;
52,104✔
59
  const int count =
52,104✔
60
      llvm::count_if(quals, [](auto& qual) { return qual == Qualifier::kPtr || qual == Qualifier::kRef; });
74,763✔
61

62
  if constexpr (std::is_same_v<Type, typename dimeta::QualifiedFundamental>) {
63
    switch (type.type.encoding) {
31,149✔
64
      case FundamentalType::Encoding::kVtablePtr:
65
        return {TYPEART_VTABLE_POINTER, count};
180✔
66
      case FundamentalType::Encoding::kNullptr:
67
        return {TYPEART_NULLPOINTER, count};
20✔
68
      case FundamentalType::Encoding::kVoid:
69
        return {TYPEART_VOID, count};
962✔
70
      default:
71
        break;
29,987✔
72
    }
73
  }
74
  if (count > 0) {
50,942✔
75
    return {{TYPEART_POINTER}, count};
8,948✔
76
  }
77

78
  return {{}, count};
41,994✔
79
}
52,104✔
80

81
namespace detail {
82

83
template <typename Type, typename Func>
84
auto apply_function(const Type& type, Func&& handle_qualified_type) {
99,519✔
85
  using namespace dimeta;
86

87
  if constexpr (std::is_same_v<Type, typename dimeta::QualifiedCompound> ||
88
                std::is_same_v<Type, typename dimeta::QualifiedFundamental>) {
89
    return std::forward<Func>(handle_qualified_type)(type);
61,798✔
90
  } else {
91
    return std::visit(
37,721✔
92
        [&](auto&& qualified_type) {
75,442✔
93
          return apply_function(qualified_type, std::forward<Func>(handle_qualified_type));
37,721✔
94
        },
95
        type);
37,721✔
96
  }
97
}
98

99
}  // namespace detail
100

101
namespace workaround {
102
namespace detail {
103
void remove_pointer_level_impl(dimeta::LocatedType& val) {
12,385✔
104
  const auto remove_pointer_level = [](auto& qual) {
12,385✔
105
    auto pointer_like_iter = llvm::find_if(qual, [](auto qualifier) {
14,225✔
106
      switch (qualifier) {
1,840✔
107
        case dimeta::Qualifier::kPtr:
108
        case dimeta::Qualifier::kRef:
109
        case dimeta::Qualifier::kPtrToMember:
110
          return true;
346✔
111
        default:
112
          break;
1,494✔
113
      }
114
      return false;
1,494✔
115
    });
1,840✔
116
    if (pointer_like_iter != std::end(qual)) {
12,385✔
117
      LOG_DEBUG("Removing pointer level " << static_cast<int>(*pointer_like_iter))
118
      qual.erase(pointer_like_iter);
346✔
119
    }
346✔
120
  };
12,385✔
121
  std::visit([&](auto&& qualified_type) { remove_pointer_level(qualified_type.qual); }, val.type);
24,770✔
122
}
12,385✔
123
}  // namespace detail
124

125
void remove_pointer_level(const llvm::AllocaInst* alloc, dimeta::LocatedType& val) {
13,291✔
126
  // If the alloca instruction is not a pointer, but the located_type has a pointer-like qualifier, we remove it.
127
  // Workaround for inlining issue, see test typemapping/05_milc_inline_metadata.c
128
  // TODO Should be removed if dimeta fixes it.
129
  // Further refinement, array-like allocas to pointers stay untouched (second condition):
130
  // this will cause MPI handle arrays (typedef "ptr to opaque struct") to be considered a pointer
131
  if (!alloc->getAllocatedType()->isPointerTy() && !alloc->getAllocatedType()->isArrayTy()) {
13,291✔
132
    LOG_DEBUG("Alloca is not a pointer type: " << *alloc->getAllocatedType())
133
    detail::remove_pointer_level_impl(val);
12,379✔
134
  }
12,379✔
135
}
13,291✔
136

137
void remove_pointer_level(const llvm::CallBase* call, dimeta::LocatedType& val) {
6✔
138
  // If the call base is a templated cudaMalloc<...> call, current we need to remove a single pointer level to correct
139
  // determine the allocated type
140
  detail::remove_pointer_level_impl(val);
6✔
141
}
6✔
142

143
}  // namespace workaround
144

145
template <typename Type>
146
dimeta::ArraySize vector_num_elements(const Type& type) {
168✔
147
  return detail::apply_function(type, [](const auto& t) -> dimeta::Extent {
336✔
148
    if (t.is_vector) {
168✔
149
      int pos{-1};
168✔
150
      // Find kVector tag-position to determine vector size
151
      for (const auto& qualifier : t.qual) {
276✔
152
        if (qualifier == dimeta::Qualifier::kVector) {
276✔
153
          pos++;
168✔
154
          break;
168✔
155
        }
156
        if (qualifier == dimeta::Qualifier::kArray) {
108✔
157
          pos++;
48✔
158
        }
48✔
159
      }
160
      if (pos == -1) {
168✔
161
        return 1;
×
162
      }
163
      return t.array_size.at(pos);
168✔
164
    }
165

166
    return 1;
×
167
  });
168✔
168
}
169

170
std::string get_anon_struct_identifier(const dimeta::QualifiedCompound& compound) {
858✔
171
  llvm::MD5 compound_hash;
858✔
172
  if (compound.type.members.empty()) {
858✔
173
    LOG_WARNING("Anonymous struct has no members")
738✔
174
  }
738✔
175
  for (const auto& [member, offset, size] :
1,278✔
176
       llvm::zip(compound.type.members, compound.type.offsets, compound.type.sizes)) {
858✔
177
    compound_hash.update(member->name);
420✔
178
    compound_hash.update(offset);
420✔
179
    compound_hash.update(size);
420✔
180
    compound_hash.update(std::visit(overload{[&](const dimeta::QualifiedFundamental& member_fundamental) {
904✔
181
                                               return std::to_string(
400✔
182
                                                          static_cast<int>(member_fundamental.type.encoding)) +
800✔
183
                                                      std::to_string(static_cast<int>(member_fundamental.type.extent));
400✔
184
                                             },
×
185
                                             [&](const dimeta::QualifiedCompound& member_compound) {
20✔
186
                                               return get_anon_struct_identifier(member_compound);
20✔
187
                                             }},
188
                                    member->member));
420✔
189
    compound_hash.update("\0");
420✔
190
  }
191
  compound_hash.update(compound.type.extent);
858✔
192
  compound_hash.update("\0");
858✔
193
  llvm::MD5::MD5Result hash_result;
194
  compound_hash.final(hash_result);
858✔
195
  return "anonymous_compound_" + std::string(hash_result.digest().str());
858✔
196
}
×
197

198
template <typename Type>
199
dimeta::ArraySize array_size(const Type& type) {
39,997✔
200
  return detail::apply_function(type, [](const auto& t) -> dimeta::Extent {
79,994✔
201
    if (t.array_size.size() > 1 || (t.is_vector && t.array_size.size() > 2)) {
39,997✔
202
      LOG_ERROR("Unsupported array size number count > 1 for array type or > 2 for vector")
120✔
203
    }
120✔
204
    // Vector array-size does not count towards array type-size
205
    if (t.is_vector && t.array_size.size() == 1) {
39,997✔
206
      return 1;
100✔
207
    }
208
    const auto array_size_factor = t.array_size.empty() ? 1 : t.array_size.at(0);
39,897✔
209

210
    return array_size_factor;
39,897✔
211
  });
39,997✔
212
}
213

214
template <typename Type>
215
std::string name_or_typedef_of(const Type& type) {
21,633✔
216
  return detail::apply_function(type, [](const auto& qual_type) {
43,266✔
217
    const bool no_name = qual_type.type.name.empty();
21,633✔
218
    if constexpr (std::is_same_v<Type, typename dimeta::QualifiedCompound>) {
219
      const bool no_identifier = qual_type.type.identifier.empty();
21,633✔
220
      const bool no_typedef    = qual_type.typedef_name.empty();
21,633✔
221
      if (no_identifier && no_name && no_typedef) {
21,633✔
222
        return get_anon_struct_identifier(qual_type);
838✔
223
      }
224
      if (no_identifier && no_name) {
20,795✔
225
        return qual_type.typedef_name;
176✔
226
      }
227
      if (no_identifier) {
20,619✔
228
        return qual_type.type.name;
3,321✔
229
      }
230
      return qual_type.type.identifier;
17,298✔
231
    }
232

233
    return no_name ? qual_type.typedef_name : qual_type.type.name;
234
  });
21,633✔
235
}
236

237
std::optional<typeart_builtin_type> get_builtin_typeid(const dimeta::QualifiedFundamental& type,
45,635✔
238
                                                       bool top_level = false) {
239
  using namespace dimeta;
240
  const auto [ptr_type_id, count] = typeid_if_ptr(type);
60,982✔
241

242
  if ((top_level && count > 1) || (!top_level && count > 0)) {
45,635✔
243
    LOG_DEBUG((top_level ? "Top level, ptr ptr" : "NOT Top level, ptr ptr"));
244
    return ptr_type_id.value();
41,945✔
245
  }
246

247
  const auto extent   = type.type.extent;
25,282✔
248
  const auto encoding = type.type.encoding;
25,282✔
249

250
  if (type.type.name == "wchar_t" || type.typedef_name == "wchar_t") {
25,282✔
251
    // Clang 18 typedef's wchar_t
252
    return TYPEART_WCHAR;
16✔
253
  }
254

255
  switch (encoding) {
25,266✔
256
    case FundamentalType::Encoding::kVtablePtr:
257
      return TYPEART_VTABLE_POINTER;
×
258
    case FundamentalType::Encoding::kUnknown:
259
      return TYPEART_UNKNOWN_TYPE;
×
260
    case FundamentalType::Encoding::kVoid:
261
      return TYPEART_VOID;
347✔
262
    case FundamentalType::kNullptr:
263
      return TYPEART_NULLPOINTER;
20✔
264
    case FundamentalType::Encoding::kUTFChar: {
265
      switch (extent) {
×
266
        case 4:
267
          return TYPEART_UTF_CHAR_32;
×
268
        case 2:
269
          return TYPEART_UTF_CHAR_16;
×
270
        case 1:
271
          return TYPEART_UTF_CHAR_8;
×
272
        default:
273
          return TYPEART_UNKNOWN_TYPE;
×
274
      }
275
    }
276
    case FundamentalType::Encoding::kChar:
277
    case FundamentalType::Encoding::kSignedChar:
278
      return TYPEART_CHAR_8;
5,596✔
279
    case FundamentalType::Encoding::kUnsignedChar:
280
      return TYPEART_UCHAR_8;
60✔
281
    case FundamentalType::Encoding::kBool:
282
      return TYPEART_BOOL;
304✔
283
    case FundamentalType::Encoding::kUnsignedInt: {
284
      switch (extent) {
8,374✔
285
        case 4:
286
          return TYPEART_UINT_32;
3,770✔
287
        case 8:
288
          return TYPEART_UINT_64;
4,564✔
289
        case 2:
290
          return TYPEART_UINT_16;
40✔
291
        case 1:
292
          return TYPEART_UINT_8;
×
293
        case 16:
294
          return TYPEART_UINT_128;
×
295
        default:
296
          return TYPEART_UNKNOWN_TYPE;
×
297
      }
298
    }
299
    case FundamentalType::Encoding::kSignedInt: {
300
      switch (extent) {
7,924✔
301
        case 4:
302
          return TYPEART_INT_32;
7,564✔
303
        case 8:
304
          return TYPEART_INT_64;
240✔
305
        case 2:
306
          return TYPEART_INT_16;
120✔
307
        case 1:
308
          return TYPEART_INT_8;
×
309
        case 16:
310
          return TYPEART_INT_128;
×
311
        default:
312
          return TYPEART_UNKNOWN_TYPE;
×
313
      }
314
    }
315
    case FundamentalType::Encoding::kComplex: {
316
      switch (extent) {
108✔
317
        case 8:
318
          return TYPEART_COMPLEX_64;
36✔
319
        case 16:
320
          return TYPEART_COMPLEX_128;
36✔
321
        case 32:
322
          return TYPEART_COMPLEX_256;
36✔
323
        default:
324
          return TYPEART_UNKNOWN_TYPE;
×
325
      }
326
    }
327
    case FundamentalType::Encoding::kFloat: {
328
      switch (extent) {
2,533✔
329
        case 4:
330
          return TYPEART_FLOAT_32;
926✔
331
        case 8:
332
          return TYPEART_FLOAT_64;
1,567✔
333
        case 2:
334
          return TYPEART_FLOAT_16;
×
335
        case 16:
336
          return TYPEART_FLOAT_128;
40✔
337
        default:
338
          return TYPEART_UNKNOWN_TYPE;
×
339
      }
340
    }
341
    default:
342
      break;
×
343
  }
344

345
  return TYPEART_UNKNOWN_TYPE;
×
346
}
31,149✔
347

348
class DimetaTypeManager final : public TypeIDGenerator {
349
 public:
350
  // explicit DimetaTypeManager(std::string file_) : TypeIDGenerator(std::move(file_)) {
351
  // }
352

353
  using TypeIDGenerator::TypeIDGenerator;
354

355
  std::optional<int> fetch_id(const std::string& name) {
20,308✔
356
    if (auto it = structMap.find(name); it != structMap.end()) {
20,308✔
357
      const auto type_id = it->second;
9,545✔
358
      return type_id;
9,545✔
359
    }
360
    return {};
10,763✔
361
  }
20,308✔
362

363
  int registerVectorType(const dimeta::QualifiedFundamental& f, bool top_level) {
280✔
364
    LOG_DEBUG("Vector-like type found")
365
    assert(!f.typedef_name.empty() && "Vector types need to be typedef'ed.");
560✔
366

367
    const auto vec_name    = f.typedef_name;
280✔
368
    const auto existing_id = fetch_id(vec_name);
280✔
369
    if (existing_id) {
280✔
370
      LOG_DEBUG("Registered type found with id " << existing_id.value())
371
      return existing_id.value();
112✔
372
    }
373

374
    const int id = reserveNextTypeId();
168✔
375
    StructTypeInfo struct_info;
168✔
376
    struct_info.type_id     = id;
168✔
377
    struct_info.name        = vec_name;
168✔
378
    const auto num_elements = vector_num_elements(f);
168✔
379
    struct_info.extent      = f.vector_size;  // f.type.extent * array_size_factor;
168✔
380

381
    const auto vec_member_id = get_builtin_typeid(f, top_level).value();
168✔
382
    // FIXME assume vector offsets are "packed":
383
    for (std::uint64_t i = 0; i < num_elements; ++i) {
780✔
384
      struct_info.offsets.push_back(i * f.type.extent);
612✔
385
      struct_info.array_sizes.push_back(1);
612✔
386
      struct_info.member_types.push_back(vec_member_id);
612✔
387
    }
612✔
388

389
    struct_info.num_members = num_elements;
168✔
390
    struct_info.flag        = StructTypeFlag::LLVM_VECTOR;
168✔
391

392
    LOG_DEBUG("Registering vector-like type with id " << id)
393
    typeDB->registerStruct(struct_info);
168✔
394
    structMap.insert({struct_info.name, id});
168✔
395

396
    return id;
168✔
397
  }
280✔
398

399
  int registerStructType(const dimeta::QualifiedCompound& q, bool top_level) {
61,689✔
400
    const std::string name_or_typedef = name_or_typedef_of(q);
61,689✔
401
    LOG_DEBUG("QualifiedCompound \"" << name_or_typedef << "\"");
402
    using namespace dimeta;
403
    if (q.type.name.empty() && q.type.type == CompoundType::Tag::kUnknown) {
61,689✔
404
      LOG_DEBUG("Potentially pointer to (member) function, skipping.")
405
      return TYPEART_UNKNOWN_TYPE;
678✔
406
    }
407

408
    const auto& compound            = q.type;
61,011✔
409
    const auto [ptr_type_id, count] = typeid_if_ptr(q);
73,497✔
410

411
    if ((top_level && count > 1) || (!top_level && count > 0)) {
20,955✔
412
      // First: if top level allocation then the first pointer can be ignored, but
413
      // the second is not. Second: if it's not a top level allocation, we assume
414
      // it's a pointer type
415
      return ptr_type_id.value();
20,955✔
416
    }
417

418
    bool is_forward_declaration = false;
×
419
    const auto existing_id      = fetch_id(name_or_typedef);
×
420
    if (existing_id) {
20,028✔
421
      const auto* struct_info = typeDB->getStructInfo(existing_id.value());
9,433✔
422
      if (struct_info->flag == StructTypeFlag::FWD_DECL) {
9,433✔
423
        is_forward_declaration = true;
70✔
424
      } else {
70✔
425
        return existing_id.value();
9,363✔
426
      }
427
    }
70✔
428

429
    const int id = is_forward_declaration ? existing_id.value() : reserveNextTypeId();
10,665✔
430
    StructTypeInfo struct_info;
10,665✔
431
    struct_info.type_id = id;
10,665✔
432
    struct_info.name    = name_or_typedef;
10,665✔
433
    if (q.is_forward_decl) {
10,665✔
434
      struct_info.flag = StructTypeFlag::FWD_DECL;
184✔
435
    } else {
184✔
436
      if (q.type.type == CompoundType::Tag::kUnion) {
10,481✔
437
        struct_info.flag = StructTypeFlag::UNION;
232✔
438
      } else {
232✔
439
        struct_info.flag = StructTypeFlag::USER_DEFINED;
10,249✔
440
      }
441
    }
442

443
    struct_info.extent = compound.extent;
10,665✔
444

445
    size_t num_bases{0};
10,665✔
446
    for (const auto& base : compound.bases) {
13,806✔
447
      if (base->is_empty_base_class) {
3,141✔
448
        continue;
865✔
449
      }
450
      num_bases++;
2,276✔
451
      struct_info.member_types.push_back(getOrRegister(base->base));
2,276✔
452
      struct_info.array_sizes.push_back(array_size(base->base));
2,276✔
453
      struct_info.offsets.push_back(base->offset);
2,276✔
454
    }
455

456
    struct_info.num_members = compound.members.size() + num_bases;
10,665✔
457
    struct_info.offsets.insert(std::end(struct_info.offsets),  //
10,665✔
458
                               std::begin(compound.offsets),   //
10,665✔
459
                               std::end(compound.offsets));
10,665✔
460

461
    for (const auto& member : compound.members) {
26,505✔
462
      struct_info.member_types.push_back(getOrRegister(member->member));
15,840✔
463
      struct_info.array_sizes.push_back(array_size(member->member));
15,840✔
464
    }
465

466
    LOG_DEBUG("Registering struct-like type with id " << id)
467
    typeDB->registerStruct(struct_info, is_forward_declaration);
10,665✔
468
    structMap.insert({struct_info.name, id});
10,665✔
469

470
    return id;
10,665✔
471
  }
101,745✔
472

473
  int getOrRegister(const dimeta::QualifiedType& type, bool top_level = false) {
52,894✔
474
    auto type_id = std::visit(
52,894✔
475
        overload{[&](const dimeta::QualifiedFundamental& f) -> int {
84,155✔
476
                   LOG_DEBUG("QualifiedFundamental \"" << f.type.name << "\"");
477
                   if (f.is_vector) {
31,261✔
478
                     return registerVectorType(f, top_level);
280✔
479
                   }
480
                   return get_builtin_typeid(f, top_level).value();
30,981✔
481
                 },
31,261✔
482
                 [&](const dimeta::QualifiedCompound& q) -> int { return registerStructType(q, top_level); }},
74,527✔
483
        type);
52,894✔
484

485
    LOG_DEBUG("Returning type-id " << type_id);
486
    return type_id;
52,894✔
487
  }
488

489
  [[nodiscard]] TypeIdentifier getOrRegisterTypeValue(llvm::Value* type) {
30,435✔
490
    if (auto call = llvm::dyn_cast<llvm::CallBase>(type)) {
30,435✔
491
      // LOG_DEBUG(*type)
492
      auto val = dimeta::located_type_for(call);
3,277✔
493

494
      if (val) {
3,277✔
495
        LOG_DEBUG("Registering malloc-like")
496

497
        const auto function_name = val->location.function;
3,237✔
498
        MemOps mem_operations;
3,237✔
499
        auto kind = call->getCalledFunction() != nullptr ? mem_operations.kind(call->getCalledFunction()->getName())
3,237✔
NEW
500
                                                         : std::nullopt;
×
501

502
        if (kind && is_kind(kind.value(), MemOpKind::GpuMallocLike) &&
3,265✔
503
            gpu::is_templated_malloc_like(function_name, kind.value())) {
28✔
504
          LOG_DEBUG("Workaround for pointer level of call base " << function_name)
505
          workaround::remove_pointer_level(call, val.value());
6✔
506
        }
6✔
507

508
        return {getOrRegister(val->type, true), array_size(val->type)};
3,237✔
509
      }
3,237✔
510
    } else if (auto* alloc = llvm::dyn_cast<llvm::AllocaInst>(type)) {
30,435✔
511
      LOG_DEBUG("Alloca found")
512
      auto val = dimeta::located_type_for(alloc);
16,603✔
513
      if (val) {
16,603✔
514
        LOG_DEBUG("Registering alloca")
515
        workaround::remove_pointer_level(alloc, val.value());
13,291✔
516
        const auto type_id        = getOrRegister(val->type, false);
13,291✔
517
        const auto array_size_val = array_size(val->type);
13,291✔
518
        LOG_DEBUG("Array size of alloca " << array_size_val)
519
        return {type_id, array_size_val};
13,291✔
520
      }
521
    } else if (auto* global = llvm::dyn_cast<llvm::GlobalVariable>(type)) {
27,158✔
522
      auto val = dimeta::located_type_for(global);
10,555✔
523
      if (val) {
10,555✔
524
        LOG_DEBUG("Registering global")
525

526
        return {getOrRegister(val->type, true), array_size(val->type)};
5,353✔
527
      }
528
    }
10,555✔
529
    return {TYPEART_UNKNOWN_TYPE, 0};
8,554✔
530
  }
30,435✔
531

532
  bool registerModule(ModuleData& module) override {
5,634✔
533
    using namespace dimeta;
534
    // std::optional<CompileUnitTypeList> compile_unit_types(const llvm::Module*)
535
    LOG_DEBUG("Register module types")
536
    auto cu_types_list = dimeta::compile_unit_types(module.module).value_or(dimeta::CompileUnitTypeList{});
5,634✔
537

538
    std::vector<TypeIdentifier> cu_types;
5,634✔
539
    for (const auto& cu : cu_types_list) {
11,248✔
540
      const QualifiedTypeList& list = cu.types;
5,614✔
541
      for (const auto& cu_type : list) {
18,511✔
542
        cu_types.emplace_back(TypeIdentifier{getOrRegister(cu_type)});
12,897✔
543
      }
544
    }
545
    const bool has_cu_types = !cu_types.empty();
5,634✔
546
    module.types_list       = std::move(cu_types);
5,634✔
547
    LOG_DEBUG("Done: Register module types")
548
    return has_cu_types;
5,634✔
549
  }
5,634✔
550

551
  TypeIdentifier getOrRegisterType(const MallocData& data) override {
3,277✔
552
    // LOG_INFO("Start register malloc-like \"" << *data.call << "\"")
553
    return getOrRegisterTypeValue(data.call);
3,277✔
554
  }
555

556
  TypeIdentifier getOrRegisterType(const AllocaData& data) override {
16,603✔
557
    // LOG_INFO("Start register alloca \"" << *data.alloca << "\"")
558
    const auto alloc_type = getOrRegisterTypeValue(data.alloca);
16,603✔
559
    return {alloc_type.type_id, alloc_type.num_elements};
16,603✔
560
  }
561

562
  TypeIdentifier getOrRegisterType(const GlobalData& data) override {
10,555✔
563
    // LOG_INFO("Start register global \"" << *data.global << IR"\"")
564
    return getOrRegisterTypeValue(data.global);
10,555✔
565
  }
566

567
  ~DimetaTypeManager() = default;
11,268✔
568
};
569

570
std::unique_ptr<typeart::TypeGenerator> make_dimeta_typeidgen(std::string_view file,
5,634✔
571
                                                              std::unique_ptr<TypeDatabase> database_of_types) {
572
  return std::make_unique<typeart::types::DimetaTypeManager>(std::string{file}, std::move(database_of_types));
5,634✔
573
}
×
574

575
}  // namespace typeart::types
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