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

daisytuner / docc / 25823993703

13 May 2026 08:16PM UTC coverage: 60.954% (-4.8%) from 65.785%
25823993703

push

github

web-flow
Merge pull request #710 from daisytuner/publish-llvm-frontend

Publish LLVM (C/C++) frontend

2664 of 8267 new or added lines in 27 files covered. (32.22%)

35005 of 57429 relevant lines covered (60.95%)

11126.36 hits per line

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

50.63
/llvm/src/lifting/utils.cpp
1
#include "docc/lifting/utils.h"
2

3
#include <llvm/IR/Constants.h>
4
#include <llvm/IR/DataLayout.h>
5
#include <llvm/IR/DerivedTypes.h>
6
#include <llvm/IR/GlobalVariable.h>
7
#include <llvm/IR/TypedPointerType.h>
8
#include <llvm/IR/Value.h>
9
#include <llvm/Support/Casting.h>
10
#include <llvm/Support/raw_ostream.h>
11
#include <sdfg/codegen/language_extensions/cpp_language_extension.h>
12
#include <sdfg/types/type.h>
13

14
#include <algorithm>
15
#include <cstddef>
16
#include <string>
17
#include <vector>
18
#include "docc/utils.h"
19
#include "sdfg/element.h"
20

21
namespace docc {
22
namespace lifting {
23
namespace utils {
24

25
std::string get_name(const llvm::Value* value) {
503✔
26
    std::string llvm_name;
503✔
27

28
    if (!value->getName().empty()) {
503✔
29
        llvm_name = std::string(value->getName());
408✔
30
    }
408✔
31

32
    if (llvm_name.empty()) {
503✔
33
        llvm::raw_string_ostream OS(llvm_name);
95✔
34
        value->printAsOperand(OS, false);
95✔
35
    }
95✔
36

37
    return normalize_name(llvm_name);
503✔
38
}
503✔
39

40
std::string normalize_name(const std::string value) {
518✔
41
    std::string normalized_name = value;
518✔
42
    std::replace(normalized_name.begin(), normalized_name.end(), '.', '_');
518✔
43
    std::replace(normalized_name.begin(), normalized_name.end(), ':', '_');
518✔
44
    std::replace(normalized_name.begin(), normalized_name.end(), '-', '_');
518✔
45
    std::replace(normalized_name.begin(), normalized_name.end(), '%', '_');
518✔
46
    std::replace(normalized_name.begin(), normalized_name.end(), '@', '_');
518✔
47
    std::replace(normalized_name.begin(), normalized_name.end(), '(', '_');
518✔
48
    std::replace(normalized_name.begin(), normalized_name.end(), ')', '_');
518✔
49
    std::replace(normalized_name.begin(), normalized_name.end(), '&', '_');
518✔
50

51
    std::string tmp;
518✔
52
    std::remove_copy(normalized_name.begin(), normalized_name.end(), std::back_inserter(tmp), '<');
518✔
53
    normalized_name = tmp;
518✔
54
    tmp.clear();
518✔
55

56
    std::remove_copy(normalized_name.begin(), normalized_name.end(), std::back_inserter(tmp), '>');
518✔
57
    normalized_name = tmp;
518✔
58
    tmp.clear();
518✔
59

60
    std::remove_copy(normalized_name.begin(), normalized_name.end(), std::back_inserter(tmp), ' ');
518✔
61
    normalized_name = tmp;
518✔
62
    tmp.clear();
518✔
63

64
    std::remove_copy(normalized_name.begin(), normalized_name.end(), std::back_inserter(tmp), '*');
518✔
65
    normalized_name = tmp;
518✔
66
    tmp.clear();
518✔
67

68
    std::remove_copy(normalized_name.begin(), normalized_name.end(), std::back_inserter(tmp), ',');
518✔
69
    normalized_name = tmp;
518✔
70
    tmp.clear();
518✔
71

72
    if (normalized_name == "badref") {
518✔
NEW
73
        return "";
×
NEW
74
    }
×
75

76
    if (normalized_name == "this") {
518✔
NEW
77
        return "self";
×
NEW
78
    }
×
79

80
    return normalized_name;
518✔
81
}
518✔
82

83
bool is_literal(const llvm::Value* value) {
146✔
84
    return llvm::isa<llvm::ConstantData>(value) || llvm::isa<llvm::ConstantAggregate>(value);
146✔
85
}
146✔
86

87
bool is_null_pointer(const llvm::Value* value) { return llvm::dyn_cast<llvm::ConstantPointerNull>(value) != nullptr; }
31✔
88

89
bool is_symbol(const llvm::Value* value) {
18✔
90
    return llvm::isa<llvm::ConstantInt>(value) || llvm::isa<llvm::ConstantPointerNull>(value);
18✔
91
}
18✔
92

93
std::string as_literal(const llvm::ConstantData* value) {
68✔
94
    if (auto integer = llvm::dyn_cast<llvm::ConstantInt>(value)) {
68✔
95
        if (integer->getBitWidth() == 1) {
21✔
96
            return integer->isZero() ? "0" : "1";
5✔
97
        }
5✔
98

99
        llvm::SmallVector<char> val;
16✔
100
        if (!integer->getValue().isSignBitSet()) {
16✔
101
            integer->getValue().toStringUnsigned(val);
16✔
102
        } else {
16✔
NEW
103
            integer->getValue().toStringSigned(val);
×
NEW
104
        }
×
105

106
        return std::string(val.begin(), val.end());
16✔
107
    }
21✔
108

109
    if (auto fp = llvm::dyn_cast<llvm::ConstantFP>(value)) {
47✔
110
        if (fp->isInfinity()) {
42✔
NEW
111
            if (fp->isNegative()) {
×
NEW
112
                return "-INFINITY";
×
NEW
113
            } else {
×
NEW
114
                return "INFINITY";
×
NEW
115
            }
×
116
        } else if (fp->isNaN()) {
42✔
NEW
117
            return "NAN";
×
NEW
118
        }
×
119

120
        llvm::SmallVector<char> val;
42✔
121
        fp->getValue().toString(val);
42✔
122
        std::string tmp = std::string(val.begin(), val.end());
42✔
123
        if (tmp.find('.') == std::string::npos) {
42✔
124
            tmp += ".0";
42✔
125
        }
42✔
126

127
        if (fp->getType()->isFloatTy()) {
42✔
128
            tmp += "f";
38✔
129
        }
38✔
130

131
        return tmp;
42✔
132
    }
42✔
133

134
    if (auto undef = llvm::dyn_cast<llvm::UndefValue>(value)) {
5✔
135
        if (undef->getType()->isIntegerTy()) {
3✔
136
            return "0";
1✔
137
        } else if (undef->getType()->isFloatingPointTy()) {
2✔
NEW
138
            return "0.0";
×
139
        } else if (undef->getType()->isPointerTy()) {
2✔
140
            return sdfg::symbolic::__nullptr__()->get_name();
2✔
141
        }
2✔
142

NEW
143
        throw NotImplementedException(
×
NEW
144
            "UndefValue of unsupported type", docc::utils::bestEffortLoc(*value), docc::utils::toIRString(*value)
×
NEW
145
        );
×
146
    }
3✔
147

148
    if (llvm::dyn_cast<llvm::ConstantPointerNull>(value)) {
2✔
149
        return sdfg::symbolic::__nullptr__()->get_name();
2✔
150
    }
2✔
151

NEW
152
    throw NotImplementedException(
×
NEW
153
        "Unsupported constant data type", docc::utils::bestEffortLoc(*value), docc::utils::toIRString(*value)
×
NEW
154
    );
×
155
}
2✔
156

157
sdfg::symbolic::Expression as_symbol(const llvm::Constant* value) {
19✔
158
    if (auto const_int = llvm::dyn_cast<llvm::ConstantInt>(value)) {
19✔
159
        if (const_int->getBitWidth() == 1) {
19✔
NEW
160
            if (const_int->isZero()) {
×
NEW
161
                return sdfg::symbolic::__false__();
×
NEW
162
            } else {
×
NEW
163
                return sdfg::symbolic::__true__();
×
NEW
164
            }
×
NEW
165
        }
×
166

167
        if (!const_int->getValue().isSignBitSet()) {
19✔
168
            return sdfg::symbolic::integer(const_int->getZExtValue());
19✔
169
        } else {
19✔
NEW
170
            return sdfg::symbolic::integer(const_int->getSExtValue());
×
NEW
171
        }
×
172
    }
19✔
173

NEW
174
    if (llvm::dyn_cast<llvm::ConstantPointerNull>(value)) {
×
NEW
175
        return sdfg::symbolic::__nullptr__();
×
NEW
176
    }
×
177

NEW
178
    throw std::runtime_error("Not a symbolic expression");
×
NEW
179
}
×
180

NEW
181
std::string get_initializer(const llvm::GlobalVariable& global) {
×
NEW
182
    if (!has_initializer(global)) {
×
NEW
183
        return "";
×
NEW
184
    }
×
185

NEW
186
    return as_initializer(global.getInitializer());
×
NEW
187
}
×
188

NEW
189
bool has_initializer(const llvm::GlobalVariable& global) {
×
NEW
190
    if (!global.hasInitializer()) {
×
NEW
191
        return false;
×
NEW
192
    }
×
NEW
193
    auto initializer = global.getInitializer();
×
NEW
194
    if (!initializer) {
×
NEW
195
        return false;
×
NEW
196
    }
×
NEW
197
    if (initializer->isNullValue()) {
×
NEW
198
        return false;
×
NEW
199
    }
×
NEW
200
    if (llvm::dyn_cast<llvm::UndefValue>(initializer)) {
×
NEW
201
        return false;
×
NEW
202
    }
×
203

NEW
204
    return true;
×
NEW
205
}
×
206

207
std::string as_initializer(const llvm::Constant* initializer) {
32✔
208
    /*───────────────────
209
     *  Scalars
210
     *───────────────────*/
211
    if (auto* const_int = llvm::dyn_cast<llvm::ConstantInt>(initializer)) {
32✔
212
        return as_literal(const_int);
8✔
213
    } else if (auto* const_fp = llvm::dyn_cast<llvm::ConstantFP>(initializer)) {
24✔
214
        return as_literal(const_fp);
8✔
215
    } else if (auto* const_null = llvm::dyn_cast<llvm::ConstantPointerNull>(initializer)) {
16✔
216
        return as_literal(const_null);
1✔
217
    } else if (auto* const_undef = llvm::dyn_cast<llvm::UndefValue>(initializer)) {
15✔
218
        return as_literal(const_undef);
3✔
219
    }
3✔
220

221
    /*───────────────────
222
     *  Explicit aggregates (already contain their elements)
223
     *───────────────────*/
224
    else if (auto* const_array = llvm::dyn_cast<llvm::ConstantArray>(initializer)) {
12✔
NEW
225
        std::string result = "{";
×
NEW
226
        for (size_t i = 0; i < const_array->getNumOperands(); ++i) {
×
NEW
227
            result += as_initializer(const_array->getOperand(i));
×
NEW
228
            if (i + 1 < const_array->getNumOperands()) result += ", ";
×
NEW
229
        }
×
NEW
230
        return result + "}";
×
231
    } else if (auto* const_struct = llvm::dyn_cast<llvm::ConstantStruct>(initializer)) {
12✔
232
        std::string result = "{";
1✔
233
        for (size_t i = 0; i < const_struct->getNumOperands(); ++i) {
3✔
234
            result += as_initializer(const_struct->getOperand(i));
2✔
235
            if (i + 1 < const_struct->getNumOperands()) result += ", ";
2✔
236
        }
2✔
237
        return result + "}";
1✔
238
    } else if (auto* const_vector = llvm::dyn_cast<llvm::ConstantVector>(initializer)) {
11✔
NEW
239
        std::string result = "{";
×
NEW
240
        for (size_t i = 0; i < const_vector->getNumOperands(); ++i) { // FIX ①
×
NEW
241
            result += as_initializer(const_vector->getOperand(i));
×
NEW
242
            if (i + 1 < const_vector->getNumOperands()) result += ", "; // FIX ②
×
NEW
243
        }
×
NEW
244
        return result + "}";
×
NEW
245
    }
×
246

247
    /*───────────────────
248
     *  ConstantData* – raw bitcasts of scalars that LLVM keeps
249
     *───────────────────*/
250
    else if (auto* const_data_array = llvm::dyn_cast<llvm::ConstantDataArray>(initializer)) {
11✔
NEW
251
        std::string result = "{";
×
NEW
252
        llvm::Type* elemTy = const_data_array->getElementType();
×
253

NEW
254
        if (elemTy->isIntegerTy()) {
×
NEW
255
            for (unsigned i = 0; i < const_data_array->getNumElements(); ++i) {
×
NEW
256
                auto element = const_data_array->getElementAsConstant(i);
×
NEW
257
                result += as_literal(llvm::dyn_cast<llvm::ConstantData>(element));
×
NEW
258
                if (i + 1 < const_data_array->getNumElements()) result += ", ";
×
NEW
259
            }
×
NEW
260
        } else if (elemTy->isFloatingPointTy()) {
×
NEW
261
            for (unsigned i = 0; i < const_data_array->getNumElements(); ++i) {
×
NEW
262
                auto element = const_data_array->getElementAsConstant(i);
×
NEW
263
                result += as_literal(llvm::dyn_cast<llvm::ConstantData>(element));
×
NEW
264
                if (i + 1 < const_data_array->getNumElements()) result += ", ";
×
NEW
265
            }
×
NEW
266
        } else {
×
NEW
267
            throw NotImplementedException(
×
NEW
268
                "Unsupported ConstantDataArray element type",
×
NEW
269
                docc::utils::bestEffortLoc(*initializer),
×
NEW
270
                docc::utils::toIRString(*initializer)
×
NEW
271
            );
×
NEW
272
        }
×
NEW
273
        return result + "}";
×
274
    } else if (auto* const_data_vector = llvm::dyn_cast<llvm::ConstantDataVector>(initializer)) {
11✔
275
        std::string result = "{";
8✔
276
        llvm::Type* elemTy = const_data_vector->getElementType();
8✔
277

278
        if (elemTy->isIntegerTy()) {
8✔
279
            for (unsigned i = 0; i < const_data_vector->getNumElements(); ++i) {
10✔
280
                auto element = const_data_vector->getElementAsConstant(i);
8✔
281
                result += as_literal(llvm::dyn_cast<llvm::ConstantData>(element));
8✔
282
                if (i + 1 < const_data_vector->getNumElements()) result += ", ";
8✔
283
            }
8✔
284
        } else if (elemTy->isFloatingPointTy()) {
6✔
285
            for (unsigned i = 0; i < const_data_vector->getNumElements(); ++i) {
30✔
286
                auto element = const_data_vector->getElementAsConstant(i);
24✔
287
                result += as_literal(llvm::dyn_cast<llvm::ConstantData>(element));
24✔
288
                if (i + 1 < const_data_vector->getNumElements()) result += ", ";
24✔
289
            }
24✔
290
        } else {
6✔
NEW
291
            throw NotImplementedException(
×
NEW
292
                "Unsupported ConstantDataVector element type",
×
NEW
293
                docc::utils::bestEffortLoc(*initializer),
×
NEW
294
                docc::utils::toIRString(*initializer)
×
NEW
295
            );
×
NEW
296
        }
×
297
        return result + "}";
8✔
298
    }
8✔
299

300
    /*───────────────────
301
     *  zeroinitializer  → ConstantAggregateZero
302
     *───────────────────*/
303
    else if (auto* const_zero = llvm::dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
3✔
304
        llvm::Type* ty = const_zero->getType();
3✔
305

306
        // Helper lambda: fabricate the same “zero” as an explicit Constant
307
        auto null_of = [&](llvm::Type* subTy) -> llvm::Constant* { return llvm::Constant::getNullValue(subTy); };
12✔
308

309
        if (auto* arrTy = llvm::dyn_cast<llvm::ArrayType>(ty)) {
3✔
NEW
310
            std::string result = "{";
×
NEW
311
            for (uint64_t i = 0; i < arrTy->getNumElements(); ++i) {
×
NEW
312
                result += as_initializer(null_of(arrTy->getElementType()));
×
NEW
313
                if (i + 1 < arrTy->getNumElements()) result += ", ";
×
NEW
314
            }
×
NEW
315
            return result + "}";
×
316
        } else if (auto* structTy = llvm::dyn_cast<llvm::StructType>(ty)) {
3✔
NEW
317
            std::string result = "{";
×
NEW
318
            for (unsigned i = 0; i < structTy->getNumElements(); ++i) {
×
NEW
319
                result += as_initializer(null_of(structTy->getElementType(i)));
×
NEW
320
                if (i + 1 < structTy->getNumElements()) result += ", ";
×
NEW
321
            }
×
NEW
322
            return result + "}";
×
323
        } else if (auto* vecTy = llvm::dyn_cast<llvm::VectorType>(ty)) {
3✔
324
            std::string result = "{";
3✔
325
            for (unsigned i = 0; i < vecTy->getElementCount().getFixedValue(); ++i) {
15✔
326
                result += as_initializer(null_of(vecTy->getElementType()));
12✔
327
                if (i + 1 < vecTy->getElementCount().getFixedValue()) result += ", ";
12✔
328
            }
12✔
329
            return result + "}";
3✔
330
        }
3✔
331
        // Should never get here – AggregateZero is only array/struct/vector.
332
    }
3✔
333

334
    /*───────────────────
335
     *  Other Global Variables (e.g., bitcasted, nested)
336
     *───────────────────*/
NEW
337
    else if (auto global_var = llvm::dyn_cast<llvm::GlobalVariable>(initializer)) {
×
NEW
338
        return utils::get_name(global_var);
×
NEW
339
    }
×
340

341

342
    /*───────────────────
343
     *  Fallback
344
     *───────────────────*/
NEW
345
    throw NotImplementedException(
×
NEW
346
        "Unsupported initializer", docc::utils::bestEffortLoc(*initializer), docc::utils::toIRString(*initializer)
×
NEW
347
    );
×
348
}
32✔
349

350
std::string create_const_name_to_sdfg_name(
351
    sdfg::builder::SDFGBuilder& builder,
352
    std::unordered_map<const llvm::Value*, std::string>& constants_mapping,
353
    const llvm::Value* llvm_ptr
NEW
354
) {
×
NEW
355
    if (constants_mapping.find(llvm_ptr) == constants_mapping.end()) {
×
NEW
356
        constants_mapping[llvm_ptr] = builder.find_new_name();
×
NEW
357
    }
×
358

NEW
359
    return constants_mapping[llvm_ptr];
×
NEW
360
}
×
361

362
std::string find_const_name_to_sdfg_name(
363
    std::unordered_map<const llvm::Value*, std::string>& constants_mapping, const llvm::Value* llvm_ptr
364
) {
135✔
365
    if (constants_mapping.find(llvm_ptr) != constants_mapping.end()) {
135✔
NEW
366
        return constants_mapping[llvm_ptr];
×
NEW
367
    }
×
368

369
    return get_name(llvm_ptr);
135✔
370
}
135✔
371

372
/**** Deprecated API ****/
373

374
std::unique_ptr<sdfg::types::IType> get_type(
375
    sdfg::builder::SDFGBuilder& builder,
376
    std::unordered_map<const llvm::Type*, std::string>& anonymous_types_mapping,
377
    const llvm::DataLayout& DL,
378
    llvm::Type* type,
379
    sdfg::types::StorageType storage_type,
380
    const std::string& initializer
381
) {
523✔
382
    size_t alignment = 0;
523✔
383

384
    if (type->isVoidTy()) {
523✔
385
        return std::make_unique<
102✔
386
            sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Void);
102✔
387
    } else if (type->isIntegerTy()) {
421✔
388
        llvm::Align abi = DL.getABITypeAlign(type);
198✔
389
        alignment = abi.value();
198✔
390

391
        auto integer_type = llvm::dyn_cast<llvm::IntegerType>(type);
198✔
392
        switch (integer_type->getBitWidth()) {
198✔
393
            case 1:
32✔
394
                return std::make_unique<
32✔
395
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Bool);
32✔
NEW
396
            case 8:
×
NEW
397
                return std::make_unique<
×
NEW
398
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Int8);
×
399
            case 16:
1✔
400
                return std::make_unique<
1✔
401
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Int16);
1✔
402
            case 32:
152✔
403
                return std::make_unique<
152✔
404
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Int32);
152✔
405
            case 64:
13✔
406
                return std::make_unique<
13✔
407
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Int64);
13✔
NEW
408
            case 128:
×
NEW
409
                return std::make_unique<
×
NEW
410
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Int128);
×
NEW
411
            default:
×
NEW
412
                throw NotImplementedException(
×
NEW
413
                    "Unsupported integer type", sdfg::DebugInfo(), docc::utils::toIRString(*type)
×
NEW
414
                );
×
415
        }
198✔
416
    } else if (type->isFloatingPointTy()) {
223✔
417
        llvm::Align abi = DL.getABITypeAlign(type);
71✔
418
        alignment = abi.value();
71✔
419

420
        switch (type->getTypeID()) {
71✔
NEW
421
            case llvm::Type::HalfTyID:
×
NEW
422
                return std::make_unique<
×
NEW
423
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Half);
×
NEW
424
            case llvm::Type::BFloatTyID:
×
NEW
425
                return std::make_unique<
×
NEW
426
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::BFloat);
×
427
            case llvm::Type::FloatTyID:
55✔
428
                return std::make_unique<
55✔
429
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Float);
55✔
430
            case llvm::Type::DoubleTyID:
16✔
431
                return std::make_unique<
16✔
432
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::Double);
16✔
NEW
433
            case llvm::Type::X86_FP80TyID:
×
NEW
434
                return std::make_unique<
×
NEW
435
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::X86_FP80);
×
NEW
436
            case llvm::Type::FP128TyID:
×
NEW
437
                return std::make_unique<
×
NEW
438
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::FP128);
×
NEW
439
            case llvm::Type::PPC_FP128TyID:
×
NEW
440
                return std::make_unique<
×
NEW
441
                    sdfg::types::Scalar>(storage_type, alignment, initializer, sdfg::types::PrimitiveType::PPC_FP128);
×
NEW
442
            default:
×
NEW
443
                throw NotImplementedException(
×
NEW
444
                    "Unsupported floating point type", sdfg::DebugInfo(), docc::utils::toIRString(*type)
×
NEW
445
                );
×
446
        }
71✔
447
    } else if (type->isArrayTy()) {
152✔
NEW
448
        llvm::Align abi = DL.getABITypeAlign(type);
×
NEW
449
        alignment = abi.value();
×
450

NEW
451
        return std::make_unique<sdfg::types::Array>(
×
NEW
452
            storage_type,
×
NEW
453
            alignment,
×
NEW
454
            initializer,
×
NEW
455
            *get_type(builder, anonymous_types_mapping, DL, type->getArrayElementType(), storage_type),
×
NEW
456
            sdfg::symbolic::integer(type->getArrayNumElements())
×
NEW
457
        );
×
458
    } else if (auto vec_type = llvm::dyn_cast<llvm::FixedVectorType>(type)) {
152✔
459
        llvm::Align abi = DL.getABITypeAlign(type);
48✔
460
        alignment = abi.value();
48✔
461

462
        auto num_elements = vec_type->getNumElements();
48✔
463
        auto element_type = vec_type->getElementType();
48✔
464
        auto element_sdfg_type = get_type(builder, anonymous_types_mapping, DL, element_type, storage_type);
48✔
465
        assert(element_sdfg_type->type_id() == sdfg::types::TypeID::Scalar && "Vector element type must be a scalar");
48✔
466

467
        return builder.create_vector_type(static_cast<const sdfg::types::Scalar&>(*element_sdfg_type), num_elements);
48✔
468
    } else if (auto typed_ptr_type = llvm::dyn_cast<llvm::TypedPointerType>(type)) {
104✔
NEW
469
        llvm::Align abi = DL.getABITypeAlign(type);
×
NEW
470
        alignment = abi.value();
×
471

NEW
472
        auto pointee_type = typed_ptr_type->getElementType();
×
NEW
473
        return std::make_unique<sdfg::types::Pointer>(
×
NEW
474
            storage_type,
×
NEW
475
            alignment,
×
NEW
476
            initializer,
×
NEW
477
            *get_type(builder, anonymous_types_mapping, DL, pointee_type, storage_type)
×
NEW
478
        );
×
479
    } else if (type->isPointerTy()) {
104✔
480
        llvm::Align abi = DL.getABITypeAlign(type);
89✔
481
        alignment = abi.value();
89✔
482

483
        return std::make_unique<sdfg::types::Pointer>(storage_type, alignment, initializer);
89✔
484
    } else if (type->isStructTy()) {
89✔
485
        llvm::Align abi = DL.getABITypeAlign(type);
3✔
486
        alignment = abi.value();
3✔
487

488
        auto structure_type = llvm::dyn_cast<llvm::StructType>(type);
3✔
489
        auto structure_name = normalize_name(structure_type->getName().str());
3✔
490
        if (structure_name.empty()) {
3✔
491
            if (anonymous_types_mapping.find(type) != anonymous_types_mapping.end()) {
3✔
NEW
492
                structure_name = anonymous_types_mapping[type];
×
493
            } else {
3✔
494
                structure_name = "__daisy_anonymous_struct" + std::to_string(anonymous_types_mapping.size());
3✔
495
                anonymous_types_mapping[type] = structure_name;
3✔
496
            }
3✔
497
        }
3✔
498

499
        // Create the actual type.
500
        auto sdfg_structure_type =
3✔
501
            std::make_unique<sdfg::types::Structure>(storage_type, alignment, initializer, structure_name);
3✔
502

503
        // Define structure if necessary
504
        auto defined_structures = builder.subject().structures();
3✔
505
        if (std::find(defined_structures.begin(), defined_structures.end(), structure_name) ==
3✔
506
            defined_structures.end()) {
3✔
507
            auto& structure_definition = builder.add_structure(structure_name, structure_type->isPacked());
3✔
508
            for (auto elem : structure_type->elements()) {
6✔
509
                structure_definition.add_member(*get_type(builder, anonymous_types_mapping, DL, elem, storage_type));
6✔
510
            }
6✔
511
        }
3✔
512

513
        return sdfg_structure_type;
3✔
514
    } else if (type->isFunctionTy()) {
12✔
515
        auto function_type = llvm::dyn_cast<llvm::FunctionType>(type);
12✔
516
        auto return_type = get_type(builder, anonymous_types_mapping, DL, function_type->getReturnType(), storage_type);
12✔
517
        auto sdfg_function_type = std::make_unique<
12✔
518
            sdfg::types::Function>(storage_type, alignment, initializer, *return_type, function_type->isVarArg());
12✔
519
        for (auto param : function_type->params()) {
46✔
520
            auto param_type = get_type(builder, anonymous_types_mapping, DL, param, storage_type);
46✔
521
            sdfg_function_type->add_param(*param_type);
46✔
522
        }
46✔
523
        return sdfg_function_type;
12✔
524
    }
12✔
525

NEW
526
    throw NotImplementedException("Unsupported type", sdfg::DebugInfo(), docc::utils::toIRString(*type));
×
527
}
523✔
528

529
sdfg::types::StorageType get_storage_type(sdfg::FunctionType target_type, size_t address_space) {
411✔
530
    if (target_type == sdfg::FunctionType_CPU) {
411✔
531
        switch (address_space) {
411✔
532
            case 0:
411✔
533
                return sdfg::types::StorageType::CPU_Stack();
411✔
NEW
534
            default:
×
NEW
535
                throw NotImplementedException(
×
NEW
536
                    "Unsupported CPU address space: " + std::to_string(address_space), sdfg::DebugInfo(), ""
×
NEW
537
                );
×
538
        }
411✔
539
    } else if (target_type == sdfg::FunctionType_NV_GLOBAL) {
411✔
NEW
540
        switch (address_space) {
×
NEW
541
            case 0:
×
NEW
542
                return sdfg::types::StorageType::NV_Generic();
×
NEW
543
            case 1:
×
NEW
544
                return sdfg::types::StorageType::NV_Global();
×
NEW
545
            case 3:
×
NEW
546
                return sdfg::types::StorageType::NV_Shared();
×
NEW
547
            case 4:
×
NEW
548
                return sdfg::types::StorageType::NV_Constant();
×
NEW
549
            default:
×
NEW
550
                throw NotImplementedException(
×
NEW
551
                    "Unsupported GPU address space: " + std::to_string(address_space), sdfg::DebugInfo(), ""
×
NEW
552
                );
×
NEW
553
        }
×
NEW
554
    }
×
555

NEW
556
    throw NotImplementedException(
×
NEW
557
        "Unsupported function type: " + target_type.value(), sdfg::DebugInfo(), target_type.value()
×
NEW
558
    );
×
559
}
411✔
560

561

562
std::pair<std::string, sdfg::data_flow::Subset>
NEW
563
get_memlet(std::unordered_map<const llvm::Value*, std::string>& constants_mapping, const llvm::GEPOperator* gep) {
×
NEW
564
    auto ptr = gep->getPointerOperand();
×
565

NEW
566
    std::string data = find_const_name_to_sdfg_name(constants_mapping, ptr);
×
NEW
567
    if (!llvm::dyn_cast<llvm::GlobalVariable>(ptr) && llvm::dyn_cast<llvm::GlobalValue>(ptr)) {
×
NEW
568
        throw NotImplementedException(
×
NEW
569
            "Unsupported global value: " + ptr->getName().str(),
×
NEW
570
            docc::utils::bestEffortLoc(*ptr),
×
NEW
571
            docc::utils::toIRString(*ptr)
×
NEW
572
        );
×
NEW
573
    }
×
574

NEW
575
    if (utils::is_null_pointer(ptr)) {
×
NEW
576
        data = sdfg::symbolic::__nullptr__()->get_name();
×
NEW
577
    }
×
578

NEW
579
    sdfg::data_flow::Subset subset;
×
NEW
580
    for (auto it = gep->idx_begin(); it != gep->idx_end(); ++it) {
×
NEW
581
        if (auto const_int = llvm::dyn_cast<llvm::ConstantInt>(*it)) {
×
NEW
582
            auto start = sdfg::symbolic::integer(const_int->getZExtValue());
×
NEW
583
            subset.push_back(start);
×
NEW
584
        } else {
×
NEW
585
            auto start = sdfg::symbolic::symbol(utils::get_name(*it));
×
NEW
586
            subset.push_back(start);
×
NEW
587
        }
×
NEW
588
    }
×
589

NEW
590
    return {data, subset};
×
NEW
591
}
×
592

NEW
593
std::vector<llvm::GlobalVariable*> add_nested_global(const llvm::ConstantExpr* expr) {
×
NEW
594
    std::vector<llvm::GlobalVariable*> result;
×
NEW
595
    for (auto& op : expr->operands()) {
×
NEW
596
        if (auto global = llvm::dyn_cast<llvm::GlobalVariable>(op)) {
×
NEW
597
            result.push_back(global);
×
NEW
598
        } else if (auto const_expr = llvm::dyn_cast<llvm::ConstantExpr>(op)) {
×
NEW
599
            auto nested_result = add_nested_global(const_expr);
×
NEW
600
            result.insert(result.end(), nested_result.begin(), nested_result.end());
×
NEW
601
        } else {
×
NEW
602
            throw NotImplementedException(
×
NEW
603
                "Unsupported operand", docc::utils::bestEffortLoc(*expr), docc::utils::toIRString(*expr)
×
NEW
604
            );
×
NEW
605
        }
×
NEW
606
    }
×
NEW
607
    return result;
×
NEW
608
}
×
609

610
} // namespace utils
611
} // namespace lifting
612
} // namespace docc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc