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

tudasc / TypeART / 25177145272

30 Apr 2026 04:30PM UTC coverage: 84.647% (-5.6%) from 90.246%
25177145272

Pull #188

github

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

127 of 259 new or added lines in 19 files covered. (49.03%)

200 existing lines in 18 files now uncovered.

4510 of 5328 relevant lines covered (84.65%)

27776.73 hits per line

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

89.0
/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) {
39,585✔
57
  using namespace dimeta;
58
  const auto& quals = type.qual;
39,585✔
59
  const int count =
39,585✔
60
      llvm::count_if(quals, [](auto& qual) { return qual == Qualifier::kPtr || qual == Qualifier::kRef; });
57,874✔
61

62
  if constexpr (std::is_same_v<Type, typename dimeta::QualifiedFundamental>) {
63
    switch (type.type.encoding) {
24,085✔
64
      case FundamentalType::Encoding::kVtablePtr:
65
        return {TYPEART_VTABLE_POINTER, count};
135✔
66
      case FundamentalType::Encoding::kNullptr:
67
        return {TYPEART_NULLPOINTER, count};
15✔
68
      case FundamentalType::Encoding::kVoid:
69
        return {TYPEART_VOID, count};
674✔
70
      default:
71
        break;
23,261✔
72
    }
73
  }
74
  if (count > 0) {
38,761✔
75
    return {{TYPEART_POINTER}, count};
6,750✔
76
  }
77

78
  return {{}, count};
32,011✔
79
}
39,585✔
80

81
namespace detail {
82

83
template <typename Type, typename Func>
84
auto apply_function(const Type& type, Func&& handle_qualified_type) {
76,308✔
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);
47,114✔
90
  } else {
91
    return std::visit(
29,194✔
92
        [&](auto&& qualified_type) {
58,388✔
93
          return apply_function(qualified_type, std::forward<Func>(handle_qualified_type));
29,194✔
94
        },
95
        type);
29,194✔
96
  }
97
}
98

99
}  // namespace detail
100

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

125
void remove_pointer_level(const llvm::AllocaInst* alloc, dimeta::LocatedType& val) {
9,721✔
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()) {
9,721✔
132
    LOG_DEBUG("Alloca is not a pointer type: " << *alloc->getAllocatedType())
133
    detail::remove_pointer_level_impl(val);
9,051✔
134
  }
9,051✔
135
}
9,721✔
136

NEW
137
void remove_pointer_level(const llvm::CallBase* call, dimeta::LocatedType& val) {
×
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
NEW
140
  detail::remove_pointer_level_impl(val);
×
NEW
141
}
×
142

143
}  // namespace workaround
144

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

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

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

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

210
    return array_size_factor;
30,924✔
211
  });
30,999✔
212
}
213

214
template <typename Type>
215
std::string name_or_typedef_of(const Type& type) {
15,980✔
216
  return detail::apply_function(type, [](const auto& qual_type) {
31,960✔
217
    const bool no_name = qual_type.type.name.empty();
15,980✔
218
    if constexpr (std::is_same_v<Type, typename dimeta::QualifiedCompound>) {
219
      const bool no_identifier = qual_type.type.identifier.empty();
15,980✔
220
      const bool no_typedef    = qual_type.typedef_name.empty();
15,980✔
221
      if (no_identifier && no_name && no_typedef) {
15,980✔
222
        return get_anon_struct_identifier(qual_type);
600✔
223
      }
224
      if (no_identifier && no_name) {
15,380✔
225
        return qual_type.typedef_name;
120✔
226
      }
227
      if (no_identifier) {
15,260✔
228
        return qual_type.type.name;
2,565✔
229
      }
230
      return qual_type.type.identifier;
12,695✔
231
    }
232

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

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

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

247
  const auto extent   = type.type.extent;
19,734✔
248
  const auto encoding = type.type.encoding;
19,734✔
249

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

255
  switch (encoding) {
19,719✔
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;
263✔
262
    case FundamentalType::kNullptr:
263
      return TYPEART_NULLPOINTER;
15✔
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,105✔
279
    case FundamentalType::Encoding::kUnsignedChar:
280
      return TYPEART_UCHAR_8;
45✔
281
    case FundamentalType::Encoding::kBool:
282
      return TYPEART_BOOL;
230✔
283
    case FundamentalType::Encoding::kUnsignedInt: {
284
      switch (extent) {
6,330✔
285
        case 4:
286
          return TYPEART_UINT_32;
2,840✔
287
        case 8:
288
          return TYPEART_UINT_64;
3,460✔
289
        case 2:
290
          return TYPEART_UINT_16;
30✔
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) {
5,755✔
301
        case 4:
302
          return TYPEART_INT_32;
5,485✔
303
        case 8:
304
          return TYPEART_INT_64;
180✔
305
        case 2:
306
          return TYPEART_INT_16;
90✔
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) {
90✔
317
        case 8:
318
          return TYPEART_COMPLEX_64;
30✔
319
        case 16:
320
          return TYPEART_COMPLEX_128;
30✔
321
        case 32:
322
          return TYPEART_COMPLEX_256;
30✔
323
        default:
324
          return TYPEART_UNKNOWN_TYPE;
×
325
      }
326
    }
327
    case FundamentalType::Encoding::kFloat: {
328
      switch (extent) {
1,886✔
329
        case 4:
330
          return TYPEART_FLOAT_32;
681✔
331
        case 8:
332
          return TYPEART_FLOAT_64;
1,175✔
333
        case 2:
334
          return TYPEART_FLOAT_16;
×
335
        case 16:
336
          return TYPEART_FLOAT_128;
30✔
337
        default:
338
          return TYPEART_UNKNOWN_TYPE;
×
339
      }
340
    }
341
    default:
342
      break;
×
343
  }
344

345
  return TYPEART_UNKNOWN_TYPE;
×
346
}
24,085✔
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) {
14,950✔
356
    if (auto it = structMap.find(name); it != structMap.end()) {
14,950✔
357
      const auto type_id = it->second;
6,510✔
358
      return type_id;
6,510✔
359
    }
360
    return {};
8,440✔
361
  }
14,950✔
362

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

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

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

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

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

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

396
    return id;
135✔
397
  }
210✔
398

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

408
    const auto& compound            = q.type;
44,980✔
409
    const auto [ptr_type_id, count] = typeid_if_ptr(q);
53,671✔
410

411
    if ((top_level && count > 1) || (!top_level && count > 0)) {
15,500✔
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();
15,500✔
416
    }
417

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

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

443
    struct_info.extent = compound.extent;
8,325✔
444

445
    size_t num_bases{0};
8,325✔
446
    for (const auto& base : compound.bases) {
10,820✔
447
      if (base->is_empty_base_class) {
2,495✔
448
        continue;
690✔
449
      }
450
      num_bases++;
1,805✔
451
      struct_info.member_types.push_back(getOrRegister(base->base));
1,805✔
452
      struct_info.array_sizes.push_back(array_size(base->base));
1,805✔
453
      struct_info.offsets.push_back(base->offset);
1,805✔
454
    }
455

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

461
    for (const auto& member : compound.members) {
20,525✔
462
      struct_info.member_types.push_back(getOrRegister(member->member));
12,200✔
463
      struct_info.array_sizes.push_back(array_size(member->member));
12,200✔
464
    }
465

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

470
    return id;
8,325✔
471
  }
74,940✔
472

473
  int getOrRegister(const dimeta::QualifiedType& type, bool top_level = false) {
40,140✔
474
    auto type_id = std::visit(
40,140✔
475
        overload{[&](const dimeta::QualifiedFundamental& f) -> int {
64,300✔
476
                   LOG_DEBUG("QualifiedFundamental \"" << f.type.name << "\"");
477
                   if (f.is_vector) {
24,160✔
478
                     return registerVectorType(f, top_level);
210✔
479
                   }
480
                   return get_builtin_typeid(f, top_level).value();
23,950✔
481
                 },
24,160✔
482
                 [&](const dimeta::QualifiedCompound& q) -> int { return registerStructType(q, top_level); }},
56,120✔
483
        type);
40,140✔
484

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

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

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

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

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

508
        return {getOrRegister(val->type, true), array_size(val->type)};
2,395✔
509
      }
2,395✔
510
    } else if (auto* alloc = llvm::dyn_cast<llvm::AllocaInst>(type)) {
22,329✔
511
      LOG_DEBUG("Alloca found")
512
      auto val = dimeta::located_type_for(alloc);
12,091✔
513
      if (val) {
12,091✔
514
        LOG_DEBUG("Registering alloca")
515
        workaround::remove_pointer_level(alloc, val.value());
9,721✔
516
        const auto type_id        = getOrRegister(val->type, false);
9,721✔
517
        const auto array_size_val = array_size(val->type);
9,721✔
518
        LOG_DEBUG("Array size of alloca " << array_size_val)
519
        return {type_id, array_size_val};
9,721✔
520
      }
521
    } else if (auto* global = llvm::dyn_cast<llvm::GlobalVariable>(type)) {
19,904✔
522
      auto val = dimeta::located_type_for(global);
7,813✔
523
      if (val) {
7,813✔
524
        LOG_DEBUG("Registering global")
525

526
        return {getOrRegister(val->type, true), array_size(val->type)};
4,878✔
527
      }
528
    }
7,813✔
529
    return {TYPEART_UNKNOWN_TYPE, 0};
5,335✔
530
  }
22,329✔
531

532
  bool registerModule(ModuleData& module) override {
4,042✔
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{});
4,042✔
537

538
    std::vector<TypeIdentifier> cu_types;
4,042✔
539
    for (const auto& cu : cu_types_list) {
8,069✔
540
      const QualifiedTypeList& list = cu.types;
4,027✔
541
      for (const auto& cu_type : list) {
13,168✔
542
        cu_types.emplace_back(TypeIdentifier{getOrRegister(cu_type)});
9,141✔
543
      }
544
    }
545
    const bool has_cu_types = !cu_types.empty();
4,042✔
546
    module.types_list       = std::move(cu_types);
4,042✔
547
    LOG_DEBUG("Done: Register module types")
548
    return has_cu_types;
4,042✔
549
  }
4,042✔
550

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

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

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

567
  ~DimetaTypeManager() = default;
8,084✔
568
};
569

570
std::unique_ptr<typeart::TypeGenerator> make_dimeta_typeidgen(std::string_view file,
4,042✔
571
                                                              std::unique_ptr<TypeDatabase> database_of_types) {
572
  return std::make_unique<typeart::types::DimetaTypeManager>(std::string{file}, std::move(database_of_types));
4,042✔
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