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

daisytuner / sdfglib / 17117701247

21 Aug 2025 05:09AM UTC coverage: 61.329% (-4.2%) from 65.536%
17117701247

Pull #200

github

web-flow
Merge 4222c2d61 into a4938ca29
Pull Request #200: Type inference as analysis

97 of 130 new or added lines in 2 files covered. (74.62%)

256 existing lines in 7 files now uncovered.

9349 of 15244 relevant lines covered (61.33%)

119.41 hits per line

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

75.78
/src/analysis/type_analysis.cpp
1
#include "sdfg/analysis/type_analysis.h"
2

3
#include "sdfg/analysis/users.h"
4
#include "sdfg/codegen/language_extensions/c_language_extension.h"
5
#include "sdfg/exceptions.h"
6

7
namespace sdfg {
8
namespace analysis {
9

10
void TypeAnalysis::run(analysis::AnalysisManager& analysis_manager) {
8✔
11
    std::vector<std::string> containers;
8✔
12
    for (auto container : this->sdfg_.containers()) {
22✔
13
        if (sdfg_.type(container).type_id() == sdfg::types::TypeID::Pointer) {
14✔
14
            auto pointer_type = static_cast<const sdfg::types::Pointer*>(&sdfg_.type(container));
11✔
15
            if (!pointer_type->has_pointee_type()) {
11✔
16
                containers.push_back(container);
10✔
17
            }
10✔
18
        }
11✔
19
    }
14✔
20

21
    auto& users = analysis_manager.get<Users>();
8✔
22
    codegen::CLanguageExtension c_lang;
8✔
23

24
    for (auto container : containers) {
18✔
25
        // iterate over writes
26
        for (auto user : users.writes(container)) {
12✔
27
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
2✔
28
            if (access_node == nullptr) {
2✔
NEW
29
                continue;
×
30
            }
31

32
            for (auto& memlet : user->parent()->in_edges(*access_node)) {
4✔
33
                auto base_type = &memlet.base_type();
2✔
34
                if (base_type->type_id() == types::TypeID::Pointer) {
2✔
35
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
36
                    if (!pointer_type->has_pointee_type()) {
2✔
NEW
37
                        continue;
×
38
                    }
39
                }
2✔
40

41
                if (memlet.type() == data_flow::MemletType::Dereference_Src) {
2✔
NEW
42
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
NEW
43
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
NEW
44
                        base_type = &pointer_type->pointee_type();
×
45

NEW
46
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
×
47
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
48
                        base_type = &array_type->element_type();
49
                    } */
50

NEW
51
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
NEW
52
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
NEW
53
                        if (!inner_pointer_type->has_pointee_type()) {
×
NEW
54
                            continue;
×
55
                        }
NEW
56
                    }
×
NEW
57
                }
×
58

59
                if (this->type_map_.find(container) == this->type_map_.end()) {
2✔
60
                    this->type_map_.insert({container, base_type});
2✔
61
                    continue;
2✔
62
                }
63

64
                /* if (*this->type_map_.at(container) != *base_type) {
65
                    throw InvalidSDFGException(
66
                        "Type mismatch for container '" + container + "': expected " +
67
                        c_lang.declaration("", *this->type_map_.at(container)) + ", got " +
68
                        c_lang.declaration("", *base_type)
69
                    );
70
                } */
71
            }
72
        }
73

74
        // iterate over reads
75
        for (auto user : users.reads(container)) {
13✔
76
            // Pointers may be used in symbolic conditions
77
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
78
            if (access_node == nullptr) {
3✔
NEW
79
                continue;
×
80
            }
81

82
            for (auto& memlet : user->parent()->out_edges(*access_node)) {
6✔
83
                auto base_type = &memlet.base_type();
3✔
84
                if (base_type->type_id() == types::TypeID::Pointer) {
3✔
85
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
3✔
86
                    if (!pointer_type->has_pointee_type()) {
3✔
NEW
87
                        continue;
×
88
                    }
89
                }
3✔
90

91
                if (memlet.type() == data_flow::MemletType::Dereference_Dst) {
3✔
NEW
92
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
NEW
93
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
NEW
94
                        base_type = &pointer_type->pointee_type();
×
95

NEW
96
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
×
97
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
98
                        base_type = &array_type->element_type();
99
                    } */
100

NEW
101
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
NEW
102
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
NEW
103
                        if (!inner_pointer_type->has_pointee_type()) {
×
NEW
104
                            continue;
×
105
                        }
NEW
106
                    }
×
NEW
107
                }
×
108
                if (this->type_map_.find(container) == this->type_map_.end()) {
3✔
109
                    this->type_map_.insert({container, base_type});
3✔
110
                    continue;
3✔
111
                }
112

113
                /* if (*this->type_map_.at(container) != *base_type) {
114
                    throw InvalidSDFGException(
115
                        "Type mismatch for container '" + container + "': expected " +
116
                        c_lang.declaration("", *this->type_map_.at(container)) + ", got " +
117
                        c_lang.declaration("", *base_type)
118
                    );
119
                } */
120
            }
121
        }
122

123
        // iterate over views
124
        for (auto user : users.views(container)) {
13✔
125
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
126
            if (access_node == nullptr) {
3✔
NEW
127
                continue;
×
128
            }
129
            for (auto& memlet : user->parent()->out_edges(*access_node)) {
6✔
130
                auto base_type = &memlet.base_type();
3✔
131
                if (base_type->type_id() == types::TypeID::Pointer) {
3✔
132
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
3✔
133
                    if (!pointer_type->has_pointee_type()) {
3✔
NEW
134
                        continue;
×
135
                    }
136
                }
3✔
137

138
                if (memlet.type() == data_flow::MemletType::Dereference_Dst) {
3✔
139
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
140
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
141
                        base_type = &pointer_type->pointee_type();
2✔
142

143
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
2✔
144
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
145
                        base_type = &array_type->element_type();
146
                    } */
147

148
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
149
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
150
                        if (!inner_pointer_type->has_pointee_type()) {
2✔
NEW
151
                            continue;
×
152
                        }
153
                    }
2✔
154
                }
2✔
155
                if (this->type_map_.find(container) == this->type_map_.end()) {
3✔
156
                    this->type_map_.insert({container, base_type});
3✔
157
                    continue;
3✔
158
                }
159
            }
160
        }
161

162
        // iterate over moves
163
        for (auto user : users.moves(container)) {
13✔
164
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
165
            if (access_node == nullptr) {
3✔
NEW
166
                continue;
×
167
            }
168
            for (auto& memlet : user->parent()->in_edges(*access_node)) {
7✔
169
                auto base_type = &memlet.base_type();
4✔
170
                if (base_type->type_id() == types::TypeID::Pointer) {
4✔
171
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
4✔
172
                    if (!pointer_type->has_pointee_type()) {
4✔
NEW
173
                        continue;
×
174
                    }
175
                }
4✔
176

177
                if (memlet.type() == data_flow::MemletType::Dereference_Src) {
4✔
178
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
179
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
180
                        base_type = &pointer_type->pointee_type();
2✔
181

182
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
2✔
183
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
184
                        base_type = &array_type->element_type();
185
                    } */
186

187
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
188
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
189
                        if (!inner_pointer_type->has_pointee_type()) {
2✔
NEW
190
                            continue;
×
191
                        }
192
                    }
2✔
193
                }
2✔
194
                if (this->type_map_.find(container) == this->type_map_.end()) {
4✔
195
                    this->type_map_.insert({container, base_type});
2✔
196
                    continue;
2✔
197
                }
198
            }
199
        }
200
    }
10✔
201
}
8✔
202

203
TypeAnalysis::TypeAnalysis(StructuredSDFG& sdfg) : Analysis(sdfg) {}
8✔
204

205
const sdfg::types::IType* TypeAnalysis::get_outer_type(const std::string& container) const {
28✔
206
    if (sdfg_.type(container).type_id() == sdfg::types::TypeID::Pointer) {
28✔
207
        auto pointer_type = static_cast<const sdfg::types::Pointer*>(&sdfg_.type(container));
22✔
208
        if (pointer_type->has_pointee_type()) {
22✔
209
            return pointer_type;
2✔
210
        }
211
    } else {
20✔
212
        return &sdfg_.type(container);
6✔
213
    }
214

215
    auto it = type_map_.find(container);
20✔
216
    if (it != type_map_.end()) {
20✔
217
        return it->second;
20✔
218
    }
NEW
219
    return nullptr;
×
220
}
28✔
221

222
} // namespace analysis
223
} // 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