• 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

88.71
/lib/passes/instrumentation/MemOpArgCollector.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 "MemOpArgCollector.h"
14

15
#include "Instrumentation.h"
16
#include "InstrumentationHelper.h"
17
#include "configuration/Configuration.h"
18
#include "support/ConfigurationBase.h"
19
#include "support/Logger.h"
20
#include "support/TypeUtil.h"
21
#include "support/Util.h"
22
#include "typegen/TypeGenerator.h"
23
#include "typelib/TypeInterface.h"
24

25
#include "llvm/IR/Constants.h"
26
#include "llvm/IR/Instructions.h"
27
#include "llvm/IR/Module.h"
28
#include "llvm/IR/Type.h"
29
#include "llvm/Support/raw_ostream.h"
30

31
#include <cassert>
32
#include <cstddef>
33

34
namespace llvm {
35
class DataLayout;
36
class Value;
37
}  // namespace llvm
38

39
namespace tu = typeart::util::type;
40
using namespace llvm;
41

42
namespace typeart {
43

44
MemOpArgCollector::MemOpArgCollector(const config::Configuration& typeart_conf, TypeGenerator* tm,
4,042✔
45
                                     InstrumentationHelper& instr)
46
    : ArgumentCollector(), typeart_config(typeart_conf), type_m(tm), instr_helper(&instr) {
4,042✔
47
}
4,042✔
48

49
HeapArgList MemOpArgCollector::collectHeap(const MallocDataList& mallocs) {
1,940✔
50
  HeapArgList list;
1,940✔
51
  list.reserve(mallocs.size());
1,940✔
52

53
  TypegenImplementation type_gen = typeart_config[config::ConfigStdArgs::typegen];
1,940✔
54
  const bool is_llvm_ir_type     = static_cast<int>(type_gen) == static_cast<int>(TypegenImplementation::IR);
1,940✔
55

56
  for (const MallocData& mdata : mallocs) {
4,365✔
57
    ArgMap arg_map;
2,425✔
58
    const auto malloc_call = mdata.call;
2,425✔
59

60
    const auto [type_id, num_elements] = type_m->getOrRegisterType(mdata);
2,425✔
61

62
    if (type_id == TYPEART_UNKNOWN_TYPE) {
2,425✔
63
      LOG_DEBUG("Target type of casted allocation is unknown. Not instrumenting. " << util::dump(*malloc_call));
64
      continue;
30✔
65
    }
66

67
    auto type_size = type_m->getTypeDatabase().getTypeSize(type_id);
3,832✔
68

69
    LOG_DEBUG("Type " << type_id << " with " << type_size << " and num elems " << num_elements)
70

71
    auto* type_id_const    = instr_helper->getConstantFor(IType::type_id, type_id);
3,832✔
72
    Value* type_size_const = instr_helper->getConstantFor(IType::extent, type_size);
2,395✔
73

74
    Value* element_count{nullptr};
2,395✔
75
    Value* byte_count{nullptr};
2,395✔
76
    Value* realloc_ptr{nullptr};
2,395✔
77
    Value* pointer = malloc_call;
2,395✔
78

79
    switch (mdata.kind) {
2,395✔
80
      case MemOpKind::NewLike:
81
        [[fallthrough]];
82
      case MemOpKind::MallocLike:
83
        if (mdata.array_cookie) {
2,155✔
84
          auto array_cookie_data = mdata.array_cookie.value();
165✔
85
          element_count          = array_cookie_data.cookie_store->getValueOperand();
165✔
86
          pointer                = array_cookie_data.array_ptr_gep;
165✔
87
        }
165✔
88

89
        byte_count = malloc_call->getOperand(0);
2,155✔
90

91
        break;
2,155✔
92
      case MemOpKind::CallocLike: {
93
        if (mdata.primary == nullptr && is_llvm_ir_type) {
105✔
94
          // we need the second arg when the calloc type is identified as void* to calculate total bytes allocated
UNCOV
95
          type_size_const = malloc_call->getOperand(1);
×
UNCOV
96
        }
×
97
        element_count = malloc_call->getOperand(0);
105✔
98
        break;
105✔
99
      }
100
      case MemOpKind::ReallocLike:
101
        realloc_ptr = malloc_call->getOperand(0);
75✔
102
        byte_count  = malloc_call->getOperand(1);
75✔
103
        break;
75✔
104
      case MemOpKind::AlignedAllocLike:
105
        byte_count = malloc_call->getArgOperand(1);
60✔
106
        break;
60✔
107
      case MemOpKind::CudaMallocLike:
108
        [[fallthrough]];
109
      case MemOpKind::HipMallocLike:
NEW
110
        byte_count = malloc_call->getArgOperand(1);
×
NEW
111
        if (mdata.primary != nullptr) {
×
NEW
112
          pointer = mdata.primary->getOperand(0);
×
NEW
113
        } else {
×
NEW
114
          pointer = malloc_call->getArgOperand(0);
×
115
        }
NEW
116
        break;
×
117
      default:
118
        LOG_ERROR("Unknown malloc kind. Not instrumenting. " << util::dump(*malloc_call));
×
119
        // TODO see above continues
120
        continue;
×
121
    }
122

123
    arg_map[ArgMap::ID::pointer]       = pointer;
2,395✔
124
    arg_map[ArgMap::ID::type_id]       = type_id_const;
2,395✔
125
    arg_map[ArgMap::ID::type_size]     = type_size_const;
2,395✔
126
    arg_map[ArgMap::ID::byte_count]    = byte_count;
2,395✔
127
    arg_map[ArgMap::ID::element_count] = element_count;
2,395✔
128
    arg_map[ArgMap::ID::realloc_ptr]   = realloc_ptr;
2,395✔
129
    list.emplace_back(HeapArgList::value_type{mdata, arg_map});
2,395✔
130
  }
2,425✔
131

132
  return list;
1,940✔
133
}
1,940✔
134

135
FreeArgList MemOpArgCollector::collectFree(const FreeDataList& frees) {
1,455✔
136
  FreeArgList list;
1,455✔
137
  list.reserve(frees.size());
1,455✔
138

139
  for (const FreeData& fdata : frees) {
3,290✔
140
    ArgMap arg_map;
1,835✔
141
    auto free_call = fdata.call;
1,835✔
142

143
    Value* free_arg{nullptr};
1,835✔
144
    switch (fdata.kind) {
1,835✔
145
      case MemOpKind::DeleteLike:
146
        [[fallthrough]];
147
      case MemOpKind::FreeLike:
148
        free_arg =
1,835✔
149
            fdata.array_cookie_gep ? fdata.array_cookie_gep.value()->getPointerOperand() : free_call->getOperand(0);
1,835✔
150
        break;
1,835✔
151
      default:
152
        LOG_ERROR("Unknown free kind. Not instrumenting. " << util::dump(*free_call));
×
153
        continue;
×
154
    }
155

156
    arg_map[ArgMap::ID::pointer] = free_arg;
1,835✔
157
    list.emplace_back(FreeArgList::value_type{fdata, arg_map});
1,835✔
158
  }
1,835✔
159

160
  return list;
1,455✔
161
}
1,455✔
162

163
StackArgList MemOpArgCollector::collectStack(const AllocaDataList& allocs) {
4,096✔
164
  using namespace llvm;
165
  StackArgList list;
4,096✔
166
  list.reserve(allocs.size());
4,096✔
167

168
  for (const AllocaData& adata : allocs) {
16,187✔
169
    ArgMap arg_map;
12,091✔
170
    auto alloca = adata.alloca;
12,091✔
171

172
    const auto [type_id, num_elements] = type_m->getOrRegisterType(adata);
17,923✔
173

174
    if (type_id == TYPEART_UNKNOWN_TYPE) {
12,091✔
175
      LOG_DEBUG("Unknown stack type. Not instrumenting. " << util::dump(*alloca));
176
      continue;
2,370✔
177
    }
178

179
    auto type_size = type_m->getTypeDatabase().getTypeSize(type_id);
15,553✔
180
    if (type_id == TYPEART_VOID) {
9,721✔
181
      type_size = 1;
×
182
    }
×
183

184
    LOG_DEBUG("Alloca Type " << type_id << " with " << type_size << " and num elems " << num_elements)
185

186
    Value* num_elements_val{nullptr};
9,721✔
187
    // The length can be specified statically through the array type or as a separate argument.
188
    // Both cases are handled here.
189
    if (adata.is_vla) {
9,721✔
190
      LOG_DEBUG("Found VLA array allocation")
191
      // This should not happen in generated IR code
192
      assert(!alloca->getAllocatedType()->isArrayTy() && "VLAs of array types are currently not supported.");
270✔
193
      num_elements_val = alloca->getArraySize();
135✔
194
    } else {
135✔
195
      num_elements_val = instr_helper->getConstantFor(IType::extent, num_elements);
15,337✔
196
    }
197

198
    auto* type_id_constant = instr_helper->getConstantFor(IType::type_id, type_id);
15,553✔
199

200
    arg_map[ArgMap::ID::pointer]       = alloca;
9,721✔
201
    arg_map[ArgMap::ID::type_id]       = type_id_constant;
9,721✔
202
    arg_map[ArgMap::ID::element_count] = num_elements_val;
9,721✔
203

204
    list.emplace_back(StackArgList::value_type{adata, arg_map});
9,721✔
205
  }
12,091✔
206

207
  return list;
4,096✔
208
}
4,096✔
209

210
GlobalArgList MemOpArgCollector::collectGlobal(const GlobalDataList& globals) {
740✔
211
  GlobalArgList list;
740✔
212
  list.reserve(globals.size());
740✔
213

214
  for (const GlobalData& gdata : globals) {
8,553✔
215
    ArgMap arg_map;
7,813✔
216
    auto global = gdata.global;
7,813✔
217

218
    const auto [type_id, num_elements] = type_m->getOrRegisterType(gdata);
7,813✔
219

220
    if (type_id == TYPEART_UNKNOWN_TYPE) {
7,813✔
221
      LOG_DEBUG("Unknown global type. Not instrumenting. " << util::dump(*global));
222
      continue;
2,935✔
223
    }
224

225
    auto type_size = type_m->getTypeDatabase().getTypeSize(type_id);
7,746✔
226
    if (type_id == TYPEART_VOID) {
4,878✔
227
      type_size = 1;
98✔
228
    }
98✔
229

230
    LOG_DEBUG("Global Type " << type_id << " with " << type_size << " and num elems " << num_elements)
231

232
    auto* type_id_const      = instr_helper->getConstantFor(IType::type_id, type_id);
7,746✔
233
    auto* num_elements_const = instr_helper->getConstantFor(IType::extent, num_elements);
7,746✔
234
    // auto globalPtr         = IRB.CreateBitOrPointerCast(global, instr.getTypeFor(IType::ptr));
235

236
    arg_map[ArgMap::ID::pointer]       = global;
4,878✔
237
    arg_map[ArgMap::ID::type_id]       = type_id_const;
4,878✔
238
    arg_map[ArgMap::ID::element_count] = num_elements_const;
4,878✔
239

240
    list.emplace_back(GlobalArgList::value_type{gdata, arg_map});
4,878✔
241
  }
7,813✔
242

243
  return list;
740✔
244
}
740✔
245

246
}  // namespace typeart
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