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

daisytuner / sdfglib / 21026754920

15 Jan 2026 09:45AM UTC coverage: 62.594% (+0.3%) from 62.264%
21026754920

Pull #446

github

web-flow
Merge 8638fa3d4 into eaabb9b4d
Pull Request #446: Fix arg capturing

265 of 396 new or added lines in 7 files covered. (66.92%)

11 existing lines in 4 files now uncovered.

15902 of 25405 relevant lines covered (62.59%)

96.77 hits per line

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

70.93
/src/types/utils.cpp
1
#include "sdfg/types/utils.h"
2
#include <memory>
3
#include <string>
4

5
#include "sdfg/codegen/utils.h"
6
#include "sdfg/function.h"
7
#include "sdfg/symbolic/symbolic.h"
8

9
#include "sdfg/types/structure.h"
10
#include "sdfg/types/type.h"
11

12
namespace sdfg {
13
namespace types {
14

15
const types::IType&
16
infer_type_internal(const sdfg::Function& function, const types::IType& type, const data_flow::Subset& subset) {
2,196✔
17
    if (subset.empty()) {
2,196✔
18
        return type;
1,581✔
19
    }
1,581✔
20

21
    if (type.type_id() == TypeID::Scalar) {
615✔
22
        if (!subset.empty()) {
×
23
            throw InvalidSDFGException("Scalar type must have no subset");
×
24
        }
×
25

26
        return type;
×
27
    } else if (type.type_id() == TypeID::Array) {
615✔
28
        auto& array_type = static_cast<const types::Array&>(type);
604✔
29

30
        data_flow::Subset element_subset(subset.begin() + 1, subset.end());
604✔
31
        return infer_type_internal(function, array_type.element_type(), element_subset);
604✔
32
    } else if (type.type_id() == TypeID::Structure) {
604✔
33
        auto& structure_type = static_cast<const types::Structure&>(type);
11✔
34

35
        data_flow::Subset element_subset(subset.begin() + 1, subset.end());
11✔
36

37
        auto& definition = function.structure(structure_type.name());
11✔
38
        if (definition.is_vector()) {
11✔
39
            return infer_type_internal(function, definition.vector_element_type(), element_subset);
10✔
40
        }
10✔
41
        auto member = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(subset.at(0));
1✔
42
        return infer_type_internal(function, definition.member_type(member), element_subset);
1✔
43
    } else if (type.type_id() == TypeID::Pointer) {
11✔
44
        throw InvalidSDFGException("Subset references non-contiguous memory");
×
45
    }
×
46

47
    throw InvalidSDFGException("Type inference failed because of unknown type");
×
48
};
615✔
49

50
const types::IType& infer_type(const sdfg::Function& function, const types::IType& type, const data_flow::Subset& subset) {
3,669✔
51
    if (subset.empty()) {
3,669✔
52
        return type;
2,088✔
53
    }
2,088✔
54

55
    if (type.type_id() == TypeID::Pointer) {
1,581✔
56
        auto& pointer_type = static_cast<const types::Pointer&>(type);
1,213✔
57
        if (!pointer_type.has_pointee_type()) {
1,213✔
58
            throw InvalidSDFGException("Opaque pointer with non-empty subset");
×
59
        }
×
60

61
        auto& pointee_type = pointer_type.pointee_type();
1,213✔
62
        data_flow::Subset element_subset(subset.begin() + 1, subset.end());
1,213✔
63
        return infer_type_internal(function, pointee_type, element_subset);
1,213✔
64
    } else {
1,213✔
65
        return infer_type_internal(function, type, subset);
368✔
66
    }
368✔
67
};
1,581✔
68

69
std::unique_ptr<types::IType> recombine_array_type(const types::IType& type, uint depth, const types::IType& inner_type) {
14✔
70
    if (depth == 0) {
14✔
71
        return inner_type.clone();
6✔
72
    } else {
8✔
73
        if (auto atype = dynamic_cast<const types::Array*>(&type)) {
8✔
74
            return std::make_unique<types::Array>(
8✔
75
                atype->storage_type(),
8✔
76
                atype->alignment(),
8✔
77
                atype->initializer(),
8✔
78
                *recombine_array_type(atype->element_type(), depth - 1, inner_type).get(),
8✔
79
                atype->num_elements()
8✔
80
            );
8✔
81
        } else {
8✔
82
            throw std::runtime_error("construct_type: Non array types are not supported yet!");
×
83
        }
×
84
    }
8✔
85
};
14✔
86

87
const IType& peel_to_innermost_element(const IType& type, int follow_ptr) {
43✔
88
    int next_follow = follow_ptr;
43✔
89
    if (follow_ptr == PEEL_TO_INNERMOST_ELEMENT_FOLLOW_ONLY_OUTER_PTR) {
43✔
90
        next_follow = 0; // only follow an outermost pointer
25✔
91
    }
25✔
92

93
    switch (type.type_id()) {
43✔
94
        case TypeID::Array:
6✔
95
            return peel_to_innermost_element(dynamic_cast<const types::Array&>(type).element_type(), next_follow);
6✔
96
        case TypeID::Reference:
×
97
            return peel_to_innermost_element(dynamic_cast<const codegen::Reference&>(type).reference_type(), next_follow);
×
98
        case TypeID::Pointer:
9✔
99
            if (follow_ptr != 0) {
9✔
100
                if (follow_ptr != PEEL_TO_INNERMOST_ELEMENT_FOLLOW_ONLY_OUTER_PTR) {
8✔
101
                    next_follow = follow_ptr - 1; // follow one less pointer
×
102
                }
×
103

104
                auto& pointer_type = dynamic_cast<const types::Pointer&>(type);
8✔
105
                if (pointer_type.has_pointee_type()) {
8✔
106
                    return peel_to_innermost_element(pointer_type.pointee_type(), next_follow);
8✔
107
                } else {
8✔
108
                    return type;
×
109
                }
×
110
            }
8✔
111
            // fall back to cut-off if we did not follow the pointer
112
        default:
29✔
113
            return type;
29✔
114
    }
43✔
115
}
43✔
116

117
symbolic::Expression get_contiguous_element_size(const types::IType& type, bool allow_comp_time_eval) {
17✔
118
    // need to peel explicitly, primitive_type() would follow ALL pointers, even ***, even though this is not contiguous
119
    auto& innermost = peel_to_innermost_element(type, PEEL_TO_INNERMOST_ELEMENT_FOLLOW_ONLY_OUTER_PTR);
17✔
120
    return get_type_size(innermost, allow_comp_time_eval);
17✔
121
}
17✔
122

123
symbolic::Expression get_type_size(const types::IType& type, bool allow_comp_time_eval) {
32✔
124
    bool only_symbolic = false;
32✔
125

126
    auto id = type.type_id();
32✔
127
    if (id == TypeID::Pointer || id == TypeID::Reference || id == TypeID::Function) {
32✔
128
        return symbolic::integer(8); // assume 64-bit pointers
3✔
129
    } else if (id == TypeID::Structure) {
29✔
130
        // TODO if we have the target definition, we could evaluate the StructureDefinition to a size
131
        only_symbolic = true;
5✔
132
    } else if (id == TypeID::Array) {
24✔
133
        auto& arr = dynamic_cast<const types::Array&>(type);
1✔
134
        auto inner_element_size = get_type_size(arr.element_type(), allow_comp_time_eval);
1✔
135
        if (!inner_element_size.is_null()) {
1✔
136
            return symbolic::mul(inner_element_size, arr.num_elements());
1✔
137
        } else {
1✔
138
            return {};
×
139
        }
×
140
    }
1✔
141

142
    if (only_symbolic) {
28✔
143
        // Could not statically figure out the size
144
        // Could be struct we could evaluate by its definition or sth. we do not understand here
145
        if (allow_comp_time_eval) {
5✔
146
            return symbolic::size_of_type(type);
4✔
147
        } else { // size unknown
4✔
148
            return {};
1✔
149
        }
1✔
150
    } else { // should just be a primitive type
23✔
151
        auto prim_type = type.primitive_type();
23✔
152

153
        long size_of_type = static_cast<long>(types::bit_width(prim_type)) / 8;
23✔
154
        if (size_of_type != 0) {
23✔
155
            return symbolic::integer(size_of_type);
23✔
156
        } else {
23✔
157
            return {};
×
158
        }
×
159
    }
23✔
160
}
28✔
161

162
const types::IType* peel_to_next_element(const types::IType& type) {
11✔
163
    switch (type.type_id()) {
11✔
164
        case TypeID::Array:
5✔
165
            return &dynamic_cast<const types::Array&>(type).element_type();
5✔
166
        case TypeID::Reference:
×
167
            return &dynamic_cast<const codegen::Reference&>(type).reference_type();
×
168
        case TypeID::Pointer: {
5✔
169
            auto& pointer_type = dynamic_cast<const types::Pointer&>(type);
5✔
170
            if (pointer_type.has_pointee_type()) {
5✔
171
                return &pointer_type.pointee_type();
5✔
172
            } else {
5✔
173
                return nullptr;
×
174
            }
×
175
        }
5✔
176
        default:
1✔
177
            return &type;
1✔
178
    }
11✔
179
}
11✔
180

181
bool is_contiguous_type(const types::IType& base_type, StructuredSDFG& sdfg) {
4✔
182
    auto& type = types::peel_to_innermost_element(base_type);
4✔
183
    if (type.type_id() == types::TypeID::Pointer) {
4✔
NEW
184
        return false;
×
NEW
185
    }
×
186

187
    // Check for distant nests
188
    if (type != types::peel_to_innermost_element(base_type, -1)) {
4✔
NEW
189
        return false;
×
NEW
190
    }
×
191

192
    // Check for nested structures
193
    if (type.type_id() == types::TypeID::Structure) {
4✔
NEW
194
        std::list<types::Structure> structures;
×
NEW
195
        std::unordered_set<std::string> visited_structures;
×
NEW
196
        structures.push_back(dynamic_cast<const types::Structure&>(type));
×
NEW
197
        while (structures.size() > 0) {
×
NEW
198
            auto structure = structures.front();
×
NEW
199
            structures.pop_front();
×
NEW
200
            if (visited_structures.contains(structure.name())) {
×
NEW
201
                return false; // infinitely nested structures are not supported
×
NEW
202
            }
×
203

NEW
204
            visited_structures.insert(structure.name());
×
NEW
205
            auto& definition = sdfg.structure(structure.name());
×
NEW
206
            for (size_t i = 0; i < definition.num_members(); i++) {
×
NEW
207
                auto& member_type = definition.member_type(symbolic::integer(i));
×
NEW
208
                if (member_type.type_id() == types::TypeID::Structure) {
×
NEW
209
                    structures.push_back(dynamic_cast<const types::Structure&>(member_type));
×
NEW
210
                } else if (member_type.type_id() == types::TypeID::Pointer) {
×
NEW
211
                    return false; // pointers in structures are not supported
×
NEW
212
                }
×
NEW
213
            }
×
NEW
214
        }
×
NEW
215
    }
×
216
    return true;
4✔
217
}
4✔
218

219
} // namespace types
220
} // namespace sdfg
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