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

daisytuner / sdfglib / 17559474002

08 Sep 2025 05:49PM UTC coverage: 61.347% (+2.2%) from 59.145%
17559474002

Pull #219

github

web-flow
Merge 2ae413ec1 into b8fdeb232
Pull Request #219: stdlib Library Nodes and ConstantNodes

424 of 1301 new or added lines in 74 files covered. (32.59%)

89 existing lines in 31 files now uncovered.

9318 of 15189 relevant lines covered (61.35%)

109.36 hits per line

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

72.22
/src/builder/sdfg_builder.cpp
1
#include "sdfg/builder/sdfg_builder.h"
2

3
#include "sdfg/types/utils.h"
4

5
namespace sdfg {
6
namespace builder {
7

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

10
SDFGBuilder::SDFGBuilder(std::unique_ptr<SDFG>& sdfg)
×
11
    : FunctionBuilder(), sdfg_(std::move(sdfg)) {
×
12

13
      };
×
14

15
SDFGBuilder::SDFGBuilder(const std::string& name, FunctionType type)
52✔
16
    : FunctionBuilder(), sdfg_(new SDFG(name, type)) {
52✔
17

18
      };
52✔
19

NEW
20
SDFGBuilder::SDFGBuilder(const std::string& name, FunctionType type, const types::IType& return_type)
×
NEW
21
    : FunctionBuilder(), sdfg_(new SDFG(name, type, return_type)) {
×
22

NEW
23
      };
×
24

25
SDFG& SDFGBuilder::subject() const { return *this->sdfg_; };
33✔
26

27
std::unique_ptr<SDFG> SDFGBuilder::move() {
14✔
28
#ifndef NDEBUG
29
    this->sdfg_->validate();
14✔
30
#endif
31

32
    return std::move(this->sdfg_);
14✔
33
};
34

35
/***** Section: Control-Flow Graph *****/
36

37
control_flow::State& SDFGBuilder::add_state(bool is_start_state, const DebugInfo& debug_info) {
60✔
38
    auto vertex = boost::add_vertex(this->sdfg_->graph_);
60✔
39
    auto res = this->sdfg_->states_.insert(
120✔
40
        {vertex,
60✔
41
         std::unique_ptr<control_flow::State>(new control_flow::State(this->new_element_id(), debug_info, vertex))}
60✔
42
    );
43

44
    assert(res.second);
60✔
45
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
60✔
46

47
    if (is_start_state) {
60✔
48
        this->sdfg_->start_state_ = (*res.first).second.get();
12✔
49
    }
12✔
50

51
    return *(*res.first).second;
60✔
52
};
×
53

54
control_flow::State& SDFGBuilder::
55
    add_state_before(const control_flow::State& state, bool is_start_state, const DebugInfo& debug_info) {
1✔
56
    auto& new_state = this->add_state(false, debug_info);
1✔
57

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

61
    // Redirect control-flow
62
    for (auto edge : to_redirect) {
2✔
63
        this->add_edge(edge->src(), new_state, edge->condition());
1✔
64

65
        auto desc = edge->edge();
1✔
66
        this->sdfg_->edges_.erase(desc);
1✔
67
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
68
    }
69
    this->add_edge(new_state, state);
1✔
70

71
    if (is_start_state) {
1✔
72
        this->sdfg_->start_state_ = &new_state;
×
73
    }
×
74

75
    return new_state;
1✔
76
};
1✔
77

78
control_flow::State& SDFGBuilder::
79
    add_state_after(const control_flow::State& state, bool connect_states, const DebugInfo& debug_info) {
4✔
80
    auto& new_state = this->add_state(false, debug_info);
4✔
81

82
    std::vector<const control_flow::InterstateEdge*> to_redirect;
4✔
83
    for (auto& e : this->sdfg_->out_edges(state)) to_redirect.push_back(&e);
5✔
84

85
    // Redirect control-flow
86
    for (auto& edge : to_redirect) {
5✔
87
        this->add_edge(new_state, edge->dst(), edge->condition());
1✔
88

89
        auto desc = edge->edge();
1✔
90
        this->sdfg_->edges_.erase(desc);
1✔
91
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
92
    }
93
    if (connect_states) {
4✔
94
        this->add_edge(state, new_state);
3✔
95
    }
3✔
96

97
    return new_state;
4✔
98
};
4✔
99

100
control_flow::ReturnState& SDFGBuilder::
101
    add_return_state(const std::string& data, bool unreachable, const DebugInfo& debug_info) {
4✔
102
    auto vertex = boost::add_vertex(this->sdfg_->graph_);
4✔
103
    auto res = this->sdfg_->states_.insert(
8✔
104
        {vertex,
4✔
105
         std::unique_ptr<control_flow::State>(
4✔
106
             new control_flow::ReturnState(this->new_element_id(), debug_info, vertex, data, unreachable)
4✔
107
         )}
108
    );
109

110
    assert(res.second);
4✔
111
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
4✔
112

113
    return static_cast<control_flow::ReturnState&>(*(*res.first).second);
4✔
NEW
114
};
×
115

116
control_flow::ReturnState& SDFGBuilder::add_return_state_after(
3✔
117
    const control_flow::State& state, const std::string& data, bool unreachable, const DebugInfo& debug_info
118
) {
119
    auto& new_state = this->add_return_state(data, unreachable, debug_info);
3✔
120

121
    std::vector<const control_flow::InterstateEdge*> to_redirect;
3✔
122
    for (auto& e : this->sdfg_->out_edges(state)) to_redirect.push_back(&e);
3✔
123

124
    // Redirect control-flow
125
    for (auto& edge : to_redirect) {
3✔
NEW
126
        this->add_edge(new_state, edge->dst(), edge->condition());
×
127

NEW
128
        auto desc = edge->edge();
×
NEW
129
        this->sdfg_->edges_.erase(desc);
×
NEW
130
        boost::remove_edge(desc, this->sdfg_->graph_);
×
131
    }
132
    this->add_edge(state, new_state);
3✔
133

134
    return new_state;
3✔
135
};
3✔
136

137
control_flow::InterstateEdge& SDFGBuilder::
138
    add_edge(const control_flow::State& src, const control_flow::State& dst, const DebugInfo& debug_info) {
41✔
139
    return this->add_edge(src, dst, control_flow::Assignments{}, SymEngine::boolTrue, debug_info);
41✔
140
};
×
141

142
control_flow::InterstateEdge& SDFGBuilder::add_edge(
8✔
143
    const control_flow::State& src,
144
    const control_flow::State& dst,
145
    const symbolic::Condition condition,
146
    const DebugInfo& debug_info
147
) {
148
    return this->add_edge(src, dst, control_flow::Assignments{}, condition, debug_info);
8✔
149
};
×
150

151
control_flow::InterstateEdge& SDFGBuilder::add_edge(
2✔
152
    const control_flow::State& src,
153
    const control_flow::State& dst,
154
    const control_flow::Assignments& assignments,
155
    const DebugInfo& debug_info
156
) {
157
    return this->add_edge(src, dst, assignments, SymEngine::boolTrue, debug_info);
2✔
158
};
×
159

160
control_flow::InterstateEdge& SDFGBuilder::add_edge(
53✔
161
    const control_flow::State& src,
162
    const control_flow::State& dst,
163
    const control_flow::Assignments& assignments,
164
    const symbolic::Condition condition,
165
    const DebugInfo& debug_info
166
) {
167
    if (dynamic_cast<const control_flow::ReturnState*>(&src) != nullptr) {
53✔
NEW
168
        throw InvalidSDFGException("Cannot add edge from ReturnState");
×
169
    }
170

171
    for (auto& entry : assignments) {
57✔
172
        auto& lhs = entry.first;
4✔
173
        auto& type = this->function().type(lhs->get_name());
4✔
174
        if (type.type_id() != types::TypeID::Scalar) {
4✔
175
            throw InvalidSDFGException("Assignment - LHS: must be integer type");
×
176
        }
177

178
        auto& rhs = entry.second;
4✔
179
        for (auto& atom : symbolic::atoms(rhs)) {
5✔
180
            if (symbolic::is_nullptr(atom)) {
1✔
181
                throw InvalidSDFGException("Assignment - RHS: must be integer type, but is nullptr");
×
182
            }
183
            auto& atom_type = this->function().type(atom->get_name());
1✔
184
            if (atom_type.type_id() != types::TypeID::Scalar) {
1✔
185
                throw InvalidSDFGException("Assignment - RHS: must be integer type");
×
186
            }
187
        }
188
    }
189

190
    for (auto& atom : symbolic::atoms(condition)) {
61✔
191
        if (symbolic::is_nullptr(atom)) {
8✔
192
            continue;
×
193
        }
194
        auto& atom_type = this->function().type(atom->get_name());
8✔
195
        if (atom_type.type_id() != types::TypeID::Scalar && atom_type.type_id() != types::TypeID::Pointer) {
8✔
196
            throw InvalidSDFGException("Condition: must be integer type or pointer type");
×
197
        }
198
    }
199

200
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, this->sdfg_->graph_);
53✔
201
    assert(edge.second);
53✔
202

203
    auto res = this->sdfg_->edges_.insert(
106✔
204
        {edge.first,
106✔
205
         std::unique_ptr<control_flow::InterstateEdge>(new control_flow::InterstateEdge(
53✔
206
             this->new_element_id(), debug_info, edge.first, src, dst, condition, assignments
53✔
207
         ))}
208
    );
209

210
    assert(res.second);
53✔
211

212
    return *(*res.first).second;
53✔
213
};
×
214

215
void SDFGBuilder::remove_edge(const control_flow::InterstateEdge& edge) {
×
216
    auto desc = edge.edge();
×
217
    this->sdfg_->edges_.erase(desc);
×
218

219
    boost::remove_edge(desc, this->sdfg_->graph_);
×
220
};
×
221

222
std::tuple<control_flow::State&, control_flow::State&, control_flow::State&> SDFGBuilder::add_loop(
1✔
223
    const control_flow::State& state,
224
    sdfg::symbolic::Symbol iterator,
225
    sdfg::symbolic::Expression init,
226
    sdfg::symbolic::Condition cond,
227
    sdfg::symbolic::Expression update,
228
    const DebugInfo& debug_info
229
) {
230
    // Init: iterator = init
231
    auto& init_state = this->add_state_after(state, true, debug_info);
1✔
232
    const graph::Edge init_edge_desc = (*this->sdfg_->in_edges(init_state).begin()).edge_;
1✔
233
    auto& init_edge = this->sdfg_->edges_[init_edge_desc];
1✔
234
    init_edge->assignments_.insert({iterator, init});
1✔
235

236
    // Final state
237
    auto& final_state = this->add_state_after(init_state, false, debug_info);
1✔
238

239
    // Init -> early_exit -> final
240
    auto& early_exit_state = this->add_state(false, debug_info);
1✔
241
    this->add_edge(init_state, early_exit_state, symbolic::Not(cond));
1✔
242
    this->add_edge(early_exit_state, final_state);
1✔
243

244
    // Init -> header -> body
245
    auto& header_state = this->add_state(false, debug_info);
1✔
246
    this->add_edge(init_state, header_state, cond);
1✔
247

248
    auto& body_state = this->add_state(false, debug_info);
1✔
249
    this->add_edge(header_state, body_state);
1✔
250

251
    auto& update_state = this->add_state(false, debug_info);
1✔
252
    this->add_edge(body_state, update_state, {{iterator, update}});
1✔
253

254
    // Back edge and exit edge
255
    this->add_edge(update_state, header_state, cond);
1✔
256
    this->add_edge(update_state, final_state, symbolic::Not(cond));
1✔
257

258
    return {init_state, body_state, final_state};
1✔
259
};
×
260

261
/***** Section: Dataflow Graph *****/
262

263
data_flow::AccessNode& SDFGBuilder::
264
    add_access(control_flow::State& state, const std::string& data, const DebugInfo& debug_info) {
6✔
265
    auto& dataflow = state.dataflow();
6✔
266
    auto vertex = boost::add_vertex(dataflow.graph_);
6✔
267
    auto res = dataflow.nodes_.insert(
12✔
268
        {vertex,
6✔
269
         std::unique_ptr<
6✔
270
             data_flow::AccessNode>(new data_flow::AccessNode(this->new_element_id(), debug_info, vertex, dataflow, data)
6✔
271
         )}
272
    );
273

274
    return static_cast<data_flow::AccessNode&>(*(res.first->second));
6✔
NEW
275
};
×
276

277
data_flow::ConstantNode& SDFGBuilder::add_constant(
1✔
278
    control_flow::State& state, const std::string& data, const types::IType& type, const DebugInfo& debug_info
279
) {
280
    auto& dataflow = state.dataflow();
1✔
281
    auto vertex = boost::add_vertex(dataflow.graph_);
1✔
282
    auto res = dataflow.nodes_.insert(
2✔
283
        {vertex,
1✔
284
         std::unique_ptr<data_flow::ConstantNode>(
1✔
285
             new data_flow::ConstantNode(this->new_element_id(), debug_info, vertex, dataflow, data, type)
1✔
286
         )}
287
    );
288

289
    return static_cast<data_flow::ConstantNode&>(*(res.first->second));
1✔
UNCOV
290
};
×
291

292
data_flow::Tasklet& SDFGBuilder::add_tasklet(
3✔
293
    control_flow::State& state,
294
    const data_flow::TaskletCode code,
295
    const std::string& output,
296
    const std::vector<std::string>& inputs,
297
    const DebugInfo& debug_info
298
) {
299
    auto& dataflow = state.dataflow();
3✔
300
    auto vertex = boost::add_vertex(dataflow.graph_);
3✔
301
    auto res = dataflow.nodes_.insert(
6✔
302
        {vertex,
3✔
303
         std::unique_ptr<data_flow::Tasklet>(
3✔
304
             new data_flow::Tasklet(this->new_element_id(), debug_info, vertex, dataflow, code, output, inputs)
3✔
305
         )}
306
    );
307

308
    return static_cast<data_flow::Tasklet&>(*(res.first->second));
3✔
309
};
×
310

311
data_flow::Memlet& SDFGBuilder::add_memlet(
6✔
312
    control_flow::State& state,
313
    data_flow::DataFlowNode& src,
314
    const std::string& src_conn,
315
    data_flow::DataFlowNode& dst,
316
    const std::string& dst_conn,
317
    const data_flow::Subset& subset,
318
    const types::IType& base_type,
319
    const DebugInfo& debug_info
320
) {
321
    auto& dataflow = state.dataflow();
6✔
322
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, dataflow.graph_);
6✔
323
    auto res = dataflow.edges_.insert(
12✔
324
        {edge.first,
12✔
325
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
6✔
326
             this->new_element_id(), debug_info, edge.first, dataflow, src, src_conn, dst, dst_conn, subset, base_type
6✔
327
         ))}
328
    );
329

330
    auto& memlet = static_cast<data_flow::Memlet&>(*(res.first->second));
6✔
331
#ifndef NDEBUG
332
    memlet.validate(*this->sdfg_);
6✔
333
#endif
334

335
    return memlet;
6✔
336
};
×
337

338
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
339
    control_flow::State& state,
340
    data_flow::AccessNode& src,
341
    data_flow::Tasklet& dst,
342
    const std::string& dst_conn,
343
    const data_flow::Subset& subset,
344
    const types::IType& base_type,
345
    const DebugInfo& debug_info
346
) {
347
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, base_type, debug_info);
×
348
};
×
349

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

362
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
3✔
363
    control_flow::State& state,
364
    data_flow::AccessNode& src,
365
    data_flow::Tasklet& dst,
366
    const std::string& dst_conn,
367
    const data_flow::Subset& subset,
368
    const DebugInfo& debug_info
369
) {
370
    const types::IType* src_type = nullptr;
3✔
371
    if (auto cnode = dynamic_cast<data_flow::ConstantNode*>(&src)) {
3✔
NEW
372
        src_type = &cnode->type();
×
NEW
373
    } else {
×
374
        src_type = &this->sdfg_->type(src.data());
3✔
375
    }
376
    auto& base_type = types::infer_type(*this->sdfg_, *src_type, subset);
3✔
377
    if (base_type.type_id() != types::TypeID::Scalar) {
3✔
378
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
379
    }
380
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, *src_type, debug_info);
3✔
381
};
×
382

383
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
3✔
384
    control_flow::State& state,
385
    data_flow::Tasklet& src,
386
    const std::string& src_conn,
387
    data_flow::AccessNode& dst,
388
    const data_flow::Subset& subset,
389
    const DebugInfo& debug_info
390
) {
391
    auto& dst_type = this->function().type(dst.data());
3✔
392
    auto& base_type = types::infer_type(this->function(), dst_type, subset);
3✔
393
    if (base_type.type_id() != types::TypeID::Scalar) {
3✔
394
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
395
    }
396
    return this->add_memlet(state, src, src_conn, dst, "void", subset, dst_type, debug_info);
3✔
397
};
×
398

399
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
400
    control_flow::State& state,
401
    data_flow::AccessNode& src,
402
    data_flow::LibraryNode& dst,
403
    const std::string& dst_conn,
404
    const data_flow::Subset& subset,
405
    const types::IType& base_type,
406
    const DebugInfo& debug_info
407
) {
NEW
408
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, base_type, debug_info);
×
409
};
×
410

411
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
412
    control_flow::State& state,
413
    data_flow::LibraryNode& src,
414
    const std::string& src_conn,
415
    data_flow::AccessNode& dst,
416
    const data_flow::Subset& subset,
417
    const types::IType& base_type,
418
    const DebugInfo& debug_info
419
) {
NEW
420
    return this->add_memlet(state, src, src_conn, dst, "void", subset, base_type, debug_info);
×
421
};
×
422

423
data_flow::Memlet& SDFGBuilder::add_reference_memlet(
×
424
    control_flow::State& state,
425
    data_flow::AccessNode& src,
426
    data_flow::AccessNode& dst,
427
    const data_flow::Subset& subset,
428
    const types::IType& base_type,
429
    const DebugInfo& debug_info
430
) {
431
    return this->add_memlet(state, src, "void", dst, "ref", subset, base_type, debug_info);
×
432
};
×
433

434
data_flow::Memlet& SDFGBuilder::add_dereference_memlet(
×
435
    control_flow::State& state,
436
    data_flow::AccessNode& src,
437
    data_flow::AccessNode& dst,
438
    bool derefs_src,
439
    const types::IType& base_type,
440
    const DebugInfo& debug_info
441
) {
442
    if (derefs_src) {
×
443
        return this->add_memlet(state, src, "void", dst, "deref", {symbolic::zero()}, base_type, debug_info);
×
444
    } else {
445
        return this->add_memlet(state, src, "deref", dst, "void", {symbolic::zero()}, base_type, debug_info);
×
446
    }
447
};
×
448

449
} // namespace builder
450
} // 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