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

daisytuner / sdfglib / 17316805645

29 Aug 2025 06:46AM UTC coverage: 60.01% (+0.2%) from 59.781%
17316805645

Pull #210

github

web-flow
Merge cd9cb386d into 18d34db1e
Pull Request #210: New debug info

351 of 562 new or added lines in 37 files covered. (62.46%)

15 existing lines in 8 files now uncovered.

9574 of 15954 relevant lines covered (60.01%)

115.01 hits per line

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

66.67
/src/builder/sdfg_builder.cpp
1
#include "sdfg/builder/sdfg_builder.h"
2
#include <cstddef>
3
#include <unordered_set>
4

5
#include "sdfg/types/utils.h"
6

7
namespace sdfg {
8
namespace builder {
9

10
DebugInfoRegion SDFGBuilder::fill_debug_info(const std::vector<DebugInfoElement>& debug_info_elements) {
127✔
11
    std::unordered_set<size_t> indices;
127✔
12
    for (const auto& element : debug_info_elements) {
127✔
NEW
13
        auto index = sdfg_->debug_info_.add_element(element);
×
NEW
14
        indices.insert(index);
×
15
    }
16
    return DebugInfoRegion{std::move(indices), sdfg_->debug_info_.instructions()};
127✔
17
}
127✔
18

19
Function& SDFGBuilder::function() const { return static_cast<Function&>(*this->sdfg_); };
233✔
20

21
SDFGBuilder::SDFGBuilder(std::unique_ptr<SDFG>& sdfg)
×
22
    : FunctionBuilder(), sdfg_(std::move(sdfg)) {
×
23

24
      };
×
25

26
SDFGBuilder::SDFGBuilder(const std::string& name, FunctionType type)
51✔
27
    : FunctionBuilder(), sdfg_(new SDFG(name, type)) {
51✔
28

29
      };
51✔
30

31
SDFG& SDFGBuilder::subject() const { return *this->sdfg_; };
14✔
32

33
std::unique_ptr<SDFG> SDFGBuilder::move() {
33✔
34
#ifndef NDEBUG
35
    this->sdfg_->validate();
33✔
36
#endif
37

38
    return std::move(this->sdfg_);
33✔
39
};
40

41
/***** Section: Control-Flow Graph *****/
42

43
control_flow::State& SDFGBuilder::add_state(bool is_start_state, const std::vector<DebugInfoElement>& debug_info_elements) {
61✔
44
    auto vertex = boost::add_vertex(this->sdfg_->graph_);
61✔
45
    auto res = this->sdfg_->states_.insert(
122✔
46
        {vertex,
61✔
47
         std::unique_ptr<control_flow::State>(
61✔
48
             new control_flow::State(this->new_element_id(), fill_debug_info(debug_info_elements), vertex)
61✔
49
         )}
50
    );
51

52
    assert(res.second);
61✔
53
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
61✔
54

55
    if (is_start_state) {
61✔
56
        this->sdfg_->start_state_ = (*res.first).second.get();
12✔
57
    }
12✔
58

59
    return *(*res.first).second;
61✔
60
};
×
61

62
control_flow::State& SDFGBuilder::add_state_before(
1✔
63
    const control_flow::State& state, bool is_start_state, const std::vector<DebugInfoElement>& debug_info_elements
64
) {
65
    auto& new_state = this->add_state(false, debug_info_elements);
1✔
66

67
    std::vector<const control_flow::InterstateEdge*> to_redirect;
1✔
68
    for (auto& e : this->sdfg_->in_edges(state)) to_redirect.push_back(&e);
2✔
69

70
    // Redirect control-flow
71
    for (auto edge : to_redirect) {
2✔
72
        this->add_edge(edge->src(), new_state, edge->condition());
1✔
73

74
        auto desc = edge->edge();
1✔
75
        this->sdfg_->edges_.erase(desc);
1✔
76
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
77
    }
78
    this->add_edge(new_state, state);
1✔
79

80
    if (is_start_state) {
1✔
81
        this->sdfg_->start_state_ = &new_state;
×
82
    }
×
83

84
    return new_state;
1✔
85
};
1✔
86

87
control_flow::State& SDFGBuilder::add_state_after(
5✔
88
    const control_flow::State& state, bool connect_states, const std::vector<DebugInfoElement>& debug_info_elements
89
) {
90
    auto& new_state = this->add_state(false, debug_info_elements);
5✔
91

92
    std::vector<const control_flow::InterstateEdge*> to_redirect;
5✔
93
    for (auto& e : this->sdfg_->out_edges(state)) to_redirect.push_back(&e);
6✔
94

95
    // Redirect control-flow
96
    for (auto& edge : to_redirect) {
6✔
97
        this->add_edge(new_state, edge->dst(), edge->condition());
1✔
98

99
        auto desc = edge->edge();
1✔
100
        this->sdfg_->edges_.erase(desc);
1✔
101
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
102
    }
103
    if (connect_states) {
5✔
104
        this->add_edge(state, new_state);
4✔
105
    }
4✔
106

107
    return new_state;
5✔
108
};
5✔
109

110
control_flow::InterstateEdge& SDFGBuilder::add_edge(
39✔
111
    const control_flow::State& src,
112
    const control_flow::State& dst,
113
    const std::vector<DebugInfoElement>& debug_info_elements
114
) {
115
    return this->add_edge(src, dst, control_flow::Assignments{}, SymEngine::boolTrue, debug_info_elements);
39✔
UNCOV
116
};
×
117

118
control_flow::InterstateEdge& SDFGBuilder::add_edge(
8✔
119
    const control_flow::State& src,
120
    const control_flow::State& dst,
121
    const symbolic::Condition condition,
122
    const std::vector<DebugInfoElement>& debug_info_elements
123
) {
124
    return this->add_edge(src, dst, control_flow::Assignments{}, condition, debug_info_elements);
8✔
125
};
×
126

127
control_flow::InterstateEdge& SDFGBuilder::add_edge(
2✔
128
    const control_flow::State& src,
129
    const control_flow::State& dst,
130
    const control_flow::Assignments& assignments,
131
    const std::vector<DebugInfoElement>& debug_info_elements
132
) {
133
    return this->add_edge(src, dst, assignments, SymEngine::boolTrue, debug_info_elements);
2✔
134
};
×
135

136
control_flow::InterstateEdge& SDFGBuilder::add_edge(
51✔
137
    const control_flow::State& src,
138
    const control_flow::State& dst,
139
    const control_flow::Assignments& assignments,
140
    const symbolic::Condition condition,
141
    const std::vector<DebugInfoElement>& debug_info_elements
142
) {
143
    for (auto& entry : assignments) {
55✔
144
        auto& lhs = entry.first;
4✔
145
        auto& type = this->function().type(lhs->get_name());
4✔
146
        if (type.type_id() != types::TypeID::Scalar) {
4✔
147
            throw InvalidSDFGException("Assignment - LHS: must be integer type");
×
148
        }
149

150
        auto& rhs = entry.second;
4✔
151
        for (auto& atom : symbolic::atoms(rhs)) {
5✔
152
            if (symbolic::is_nullptr(atom)) {
1✔
153
                throw InvalidSDFGException("Assignment - RHS: must be integer type, but is nullptr");
×
154
            }
155
            auto& atom_type = this->function().type(atom->get_name());
1✔
156
            if (atom_type.type_id() != types::TypeID::Scalar) {
1✔
157
                throw InvalidSDFGException("Assignment - RHS: must be integer type");
×
158
            }
159
        }
160
    }
161

162
    for (auto& atom : symbolic::atoms(condition)) {
59✔
163
        if (symbolic::is_nullptr(atom)) {
8✔
164
            continue;
×
165
        }
166
        auto& atom_type = this->function().type(atom->get_name());
8✔
167
        if (atom_type.type_id() != types::TypeID::Scalar && atom_type.type_id() != types::TypeID::Pointer) {
8✔
168
            throw InvalidSDFGException("Condition: must be integer type or pointer type");
×
169
        }
170
    }
171

172
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, this->sdfg_->graph_);
51✔
173
    assert(edge.second);
51✔
174

175
    auto res = this->sdfg_->edges_.insert(
102✔
176
        {edge.first,
102✔
177
         std::unique_ptr<control_flow::InterstateEdge>(new control_flow::InterstateEdge(
102✔
178
             this->new_element_id(), fill_debug_info(debug_info_elements), edge.first, src, dst, condition, assignments
51✔
179
         ))}
180
    );
181

182
    assert(res.second);
51✔
183

184
    return *(*res.first).second;
51✔
185
};
×
186

187
void SDFGBuilder::remove_edge(const control_flow::InterstateEdge& edge) {
×
188
    auto desc = edge.edge();
×
189
    this->sdfg_->edges_.erase(desc);
×
190

191
    boost::remove_edge(desc, this->sdfg_->graph_);
×
192
};
×
193

194
std::tuple<control_flow::State&, control_flow::State&, control_flow::State&> SDFGBuilder::add_loop(
1✔
195
    const control_flow::State& state,
196
    sdfg::symbolic::Symbol iterator,
197
    sdfg::symbolic::Expression init,
198
    sdfg::symbolic::Condition cond,
199
    sdfg::symbolic::Expression update,
200
    const std::vector<DebugInfoElement>& debug_info_elements
201
) {
202
    // Init: iterator = init
203
    auto& init_state = this->add_state_after(state, true, debug_info_elements);
1✔
204
    const graph::Edge init_edge_desc = (*this->sdfg_->in_edges(init_state).begin()).edge_;
1✔
205
    auto& init_edge = this->sdfg_->edges_[init_edge_desc];
1✔
206
    init_edge->assignments_.insert({iterator, init});
1✔
207

208
    // Final state
209
    auto& final_state = this->add_state_after(init_state, false, debug_info_elements);
1✔
210

211
    // Init -> early_exit -> final
212
    auto& early_exit_state = this->add_state(false, debug_info_elements);
1✔
213
    this->add_edge(init_state, early_exit_state, symbolic::Not(cond));
1✔
214
    this->add_edge(early_exit_state, final_state);
1✔
215

216
    // Init -> header -> body
217
    auto& header_state = this->add_state(false, debug_info_elements);
1✔
218
    this->add_edge(init_state, header_state, cond);
1✔
219

220
    auto& body_state = this->add_state(false, debug_info_elements);
1✔
221
    this->add_edge(header_state, body_state);
1✔
222

223
    auto& update_state = this->add_state(false, debug_info_elements);
1✔
224
    this->add_edge(body_state, update_state, {{iterator, update}});
1✔
225

226
    // Back edge and exit edge
227
    this->add_edge(update_state, header_state, cond);
1✔
228
    this->add_edge(update_state, final_state, symbolic::Not(cond));
1✔
229

230
    return {init_state, body_state, final_state};
1✔
231
};
×
232

233
/***** Section: Dataflow Graph *****/
234

235
data_flow::AccessNode& SDFGBuilder::add_access(
6✔
236
    control_flow::State& state, const std::string& data, const std::vector<DebugInfoElement>& debug_info_elements
237
) {
238
    auto& dataflow = state.dataflow();
6✔
239
    auto vertex = boost::add_vertex(dataflow.graph_);
6✔
240
    auto res = dataflow.nodes_.insert(
12✔
241
        {vertex,
6✔
242
         std::unique_ptr<data_flow::AccessNode>(new data_flow::AccessNode(
12✔
243
             this->new_element_id(), fill_debug_info(debug_info_elements), vertex, dataflow, data
6✔
244
         ))}
245
    );
246

247
    return dynamic_cast<data_flow::AccessNode&>(*(res.first->second));
6✔
248
};
×
249

250
data_flow::Tasklet& SDFGBuilder::add_tasklet(
3✔
251
    control_flow::State& state,
252
    const data_flow::TaskletCode code,
253
    const std::string& output,
254
    const std::vector<std::string>& inputs,
255
    const std::vector<DebugInfoElement>& debug_info_elements
256
) {
257
    auto& dataflow = state.dataflow();
3✔
258
    auto vertex = boost::add_vertex(dataflow.graph_);
3✔
259
    auto res = dataflow.nodes_.insert(
6✔
260
        {vertex,
3✔
261
         std::unique_ptr<data_flow::Tasklet>(new data_flow::Tasklet(
6✔
262
             this->new_element_id(),
3✔
263
             fill_debug_info(debug_info_elements),
3✔
264
             vertex,
3✔
265
             dataflow,
3✔
266
             code,
3✔
267
             output,
3✔
268
             inputs,
3✔
269
             symbolic::__true__()
3✔
270
         ))}
271
    );
272

273
    return dynamic_cast<data_flow::Tasklet&>(*(res.first->second));
3✔
274
};
×
275

276
data_flow::Memlet& SDFGBuilder::add_memlet(
6✔
277
    control_flow::State& state,
278
    data_flow::DataFlowNode& src,
279
    const std::string& src_conn,
280
    data_flow::DataFlowNode& dst,
281
    const std::string& dst_conn,
282
    const data_flow::Subset& subset,
283
    const types::IType& base_type,
284
    const std::vector<DebugInfoElement>& debug_info_elements
285
) {
286
    auto& dataflow = state.dataflow();
6✔
287
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, dataflow.graph_);
6✔
288
    auto res = dataflow.edges_.insert(
12✔
289
        {edge.first,
12✔
290
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
12✔
291
             this->new_element_id(),
6✔
292
             fill_debug_info(debug_info_elements),
6✔
293
             edge.first,
6✔
294
             dataflow,
6✔
295
             src,
6✔
296
             src_conn,
6✔
297
             dst,
6✔
298
             dst_conn,
6✔
299
             subset,
6✔
300
             base_type
6✔
301
         ))}
302
    );
303

304
    auto& memlet = dynamic_cast<data_flow::Memlet&>(*(res.first->second));
6✔
305
#ifndef NDEBUG
306
    memlet.validate(*this->sdfg_);
6✔
307
#endif
308

309
    return memlet;
6✔
310
};
×
311

312
data_flow::Memlet& SDFGBuilder::add_memlet(
×
313
    control_flow::State& state,
314
    data_flow::DataFlowNode& src,
315
    const std::string& src_conn,
316
    data_flow::DataFlowNode& dst,
317
    const std::string& dst_conn,
318
    const data_flow::Subset& begin_subset,
319
    const data_flow::Subset& end_subset,
320
    const types::IType& base_type,
321
    const std::vector<DebugInfoElement>& debug_info_elements
322
) {
323
    auto& dataflow = state.dataflow();
×
324
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, dataflow.graph_);
×
325
    auto res = dataflow.edges_.insert(
×
326
        {edge.first,
×
327
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
×
328
             this->new_element_id(),
×
NEW
329
             fill_debug_info(debug_info_elements),
×
330
             edge.first,
×
331
             dataflow,
×
332
             src,
×
333
             src_conn,
×
334
             dst,
×
335
             dst_conn,
×
336
             begin_subset,
×
337
             end_subset,
×
338
             base_type
×
339
         ))}
340
    );
341
    auto& memlet = dynamic_cast<data_flow::Memlet&>(*(res.first->second));
×
342
#ifndef NDEBUG
343
    memlet.validate(*this->sdfg_);
×
344
#endif
345

346
    return memlet;
×
347
};
×
348

349
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
350
    control_flow::State& state,
351
    data_flow::AccessNode& src,
352
    data_flow::Tasklet& dst,
353
    const std::string& dst_conn,
354
    const data_flow::Subset& subset,
355
    const types::IType& base_type,
356
    const std::vector<DebugInfoElement>& debug_info_elements
357
) {
NEW
358
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, base_type, debug_info_elements);
×
359
};
×
360

361
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
362
    control_flow::State& state,
363
    data_flow::Tasklet& src,
364
    const std::string& src_conn,
365
    data_flow::AccessNode& dst,
366
    const data_flow::Subset& subset,
367
    const types::IType& base_type,
368
    const std::vector<DebugInfoElement>& debug_info_elements
369
) {
NEW
370
    return this->add_memlet(state, src, src_conn, dst, "void", subset, base_type, debug_info_elements);
×
371
};
×
372

373
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
3✔
374
    control_flow::State& state,
375
    data_flow::AccessNode& src,
376
    data_flow::Tasklet& dst,
377
    const std::string& dst_conn,
378
    const data_flow::Subset& subset,
379
    const std::vector<DebugInfoElement>& debug_info_elements
380
) {
381
    auto& src_type = this->function().type(src.data());
3✔
382
    auto& base_type = types::infer_type(this->function(), src_type, subset);
3✔
383
    if (base_type.type_id() != types::TypeID::Scalar) {
3✔
384
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
385
    }
386
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, src_type, debug_info_elements);
3✔
387
};
×
388

389
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
3✔
390
    control_flow::State& state,
391
    data_flow::Tasklet& src,
392
    const std::string& src_conn,
393
    data_flow::AccessNode& dst,
394
    const data_flow::Subset& subset,
395
    const std::vector<DebugInfoElement>& debug_info_elements
396
) {
397
    auto& dst_type = this->function().type(dst.data());
3✔
398
    auto& base_type = types::infer_type(this->function(), dst_type, subset);
3✔
399
    if (base_type.type_id() != types::TypeID::Scalar) {
3✔
400
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
401
    }
402
    return this->add_memlet(state, src, src_conn, dst, "void", subset, dst_type, debug_info_elements);
3✔
403
};
×
404

405
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
406
    control_flow::State& state,
407
    data_flow::AccessNode& src,
408
    data_flow::LibraryNode& dst,
409
    const std::string& dst_conn,
410
    const data_flow::Subset& begin_subset,
411
    const data_flow::Subset& end_subset,
412
    const types::IType& base_type,
413
    const std::vector<DebugInfoElement>& debug_info_elements
414
) {
NEW
415
    return this->add_memlet(state, src, "void", dst, dst_conn, begin_subset, end_subset, base_type, debug_info_elements);
×
416
};
×
417

418
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
419
    control_flow::State& state,
420
    data_flow::LibraryNode& src,
421
    const std::string& src_conn,
422
    data_flow::AccessNode& dst,
423
    const data_flow::Subset& begin_subset,
424
    const data_flow::Subset& end_subset,
425
    const types::IType& base_type,
426
    const std::vector<DebugInfoElement>& debug_info_elements
427
) {
NEW
428
    return this->add_memlet(state, src, src_conn, dst, "void", begin_subset, end_subset, base_type, debug_info_elements);
×
429
};
×
430

431
data_flow::Memlet& SDFGBuilder::add_reference_memlet(
×
432
    control_flow::State& state,
433
    data_flow::AccessNode& src,
434
    data_flow::AccessNode& dst,
435
    const data_flow::Subset& subset,
436
    const types::IType& base_type,
437
    const std::vector<DebugInfoElement>& debug_info_elements
438
) {
NEW
439
    return this->add_memlet(state, src, "void", dst, "ref", subset, base_type, debug_info_elements);
×
440
};
×
441

442
data_flow::Memlet& SDFGBuilder::add_dereference_memlet(
×
443
    control_flow::State& state,
444
    data_flow::AccessNode& src,
445
    data_flow::AccessNode& dst,
446
    bool derefs_src,
447
    const types::IType& base_type,
448
    const std::vector<DebugInfoElement>& debug_info_elements
449
) {
450
    if (derefs_src) {
×
NEW
451
        return this->add_memlet(state, src, "void", dst, "deref", {symbolic::zero()}, base_type, debug_info_elements);
×
452
    } else {
NEW
453
        return this->add_memlet(state, src, "deref", dst, "void", {symbolic::zero()}, base_type, debug_info_elements);
×
454
    }
455
};
×
456

NEW
457
size_t SDFGBuilder::add_debug_info_element(const DebugInfoElement& element) {
×
NEW
458
    return sdfg_->debug_info().add_element(element);
×
NEW
459
}
×
460

NEW
461
const DebugInfo& SDFGBuilder::debug_info() const { return sdfg_->debug_info(); }
×
462

463
} // namespace builder
464
} // 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