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

daisytuner / sdfglib / 17637380013

11 Sep 2025 07:29AM UTC coverage: 59.755% (+0.6%) from 59.145%
17637380013

push

github

web-flow
New debug info (#210)

* initial draft

* update data structure and construction logic

* finalize DebugInfo draft

* fix tests

* Update serializer and fix tests

* fix append bug

* update data structure

* sdfg builder update

* const ref vectors

* update implementation and partial tests

* compiling state

* update serializer interface

* update dot test

* reset interface to debug_info in json to maintain compatibility with tools

* first review batch

* second batch of changes

* merge fixes

777 of 1111 new or added lines in 46 files covered. (69.94%)

11 existing lines in 11 files now uncovered.

9755 of 16325 relevant lines covered (59.75%)

115.06 hits per line

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

70.31
/src/builder/structured_sdfg_builder.cpp
1
#include "sdfg/builder/structured_sdfg_builder.h"
2

3
#include <cstddef>
4

5
#include "sdfg/analysis/scope_analysis.h"
6
#include "sdfg/data_flow/library_node.h"
7
#include "sdfg/debug_info.h"
8
#include "sdfg/structured_control_flow/map.h"
9
#include "sdfg/structured_control_flow/sequence.h"
10
#include "sdfg/structured_control_flow/structured_loop.h"
11
#include "sdfg/types/utils.h"
12

13
using namespace sdfg::control_flow;
14
using namespace sdfg::structured_control_flow;
15

16
namespace sdfg {
17
namespace builder {
18

19
DebugInfoRegion StructuredSDFGBuilder::fill_debug_info(const DebugInfos& debug_info_elements) {
3,408✔
20
    std::unordered_set<size_t> indices;
3,408✔
21
    for (const auto& element : debug_info_elements) {
3,411✔
22
        auto index = structured_sdfg_->debug_info_.add_element(element);
3✔
23
        indices.insert(index);
3✔
24
    }
25
    return DebugInfoRegion{std::move(indices), structured_sdfg_->debug_info_.elements()};
3,408✔
26
}
3,408✔
27

28
std::unordered_set<const control_flow::State*> StructuredSDFGBuilder::
29
    determine_loop_nodes(const SDFG& sdfg, const control_flow::State& start, const control_flow::State& end) const {
1✔
30
    std::unordered_set<const control_flow::State*> nodes;
1✔
31
    std::unordered_set<const control_flow::State*> visited;
1✔
32
    std::list<const control_flow::State*> queue = {&start};
1✔
33
    while (!queue.empty()) {
4✔
34
        auto curr = queue.front();
3✔
35
        queue.pop_front();
3✔
36
        if (visited.find(curr) != visited.end()) {
3✔
37
            continue;
×
38
        }
39
        visited.insert(curr);
3✔
40

41
        nodes.insert(curr);
3✔
42
        if (curr == &end) {
3✔
43
            continue;
1✔
44
        }
45

46
        for (auto& iedge : sdfg.in_edges(*curr)) {
4✔
47
            queue.push_back(&iedge.src());
2✔
48
        }
49
    }
50

51
    return nodes;
1✔
52
};
1✔
53

54
bool post_dominates(
6✔
55
    const State* pdom,
56
    const State* node,
57
    const std::unordered_map<const control_flow::State*, const control_flow::State*>& pdom_tree
58
) {
59
    if (pdom == node) {
6✔
60
        return true;
1✔
61
    }
62

63
    auto current = pdom_tree.at(node);
5✔
64
    while (current != nullptr) {
9✔
65
        if (current == pdom) {
9✔
66
            return true;
5✔
67
        }
68
        current = pdom_tree.at(current);
4✔
69
    }
70

71
    return false;
×
72
}
6✔
73

74
const control_flow::State* StructuredSDFGBuilder::find_end_of_if_else(
3✔
75
    const SDFG& sdfg,
76
    const State* current,
77
    std::vector<const InterstateEdge*>& out_edges,
78
    const std::unordered_map<const control_flow::State*, const control_flow::State*>& pdom_tree
79
) {
80
    // Best-effort approach: Check if post-dominator of current dominates all out edges
81
    auto pdom = pdom_tree.at(current);
3✔
82
    for (auto& edge : out_edges) {
9✔
83
        if (!post_dominates(pdom, &edge->dst(), pdom_tree)) {
6✔
84
            return nullptr;
×
85
        }
86
    }
87

88
    return pdom;
3✔
89
}
3✔
90

91
void StructuredSDFGBuilder::traverse(const SDFG& sdfg) {
4✔
92
    // Start of SDFGS
93
    Sequence& root = *structured_sdfg_->root_;
4✔
94
    const State* start_state = &sdfg.start_state();
4✔
95

96
    auto pdom_tree = sdfg.post_dominator_tree();
4✔
97

98
    std::unordered_set<const InterstateEdge*> breaks;
4✔
99
    std::unordered_set<const InterstateEdge*> continues;
4✔
100
    for (auto& edge : sdfg.back_edges()) {
5✔
101
        continues.insert(edge);
1✔
102
    }
103

104
    std::unordered_set<const control_flow::State*> visited;
4✔
105
    this->traverse_with_loop_detection(sdfg, root, start_state, nullptr, continues, breaks, pdom_tree, visited);
4✔
106
};
4✔
107

108
void StructuredSDFGBuilder::traverse_with_loop_detection(
9✔
109
    const SDFG& sdfg,
110
    Sequence& scope,
111
    const State* current,
112
    const State* end,
113
    const std::unordered_set<const InterstateEdge*>& continues,
114
    const std::unordered_set<const InterstateEdge*>& breaks,
115
    const std::unordered_map<const control_flow::State*, const control_flow::State*>& pdom_tree,
116
    std::unordered_set<const control_flow::State*>& visited
117
) {
118
    if (current == end) {
9✔
119
        return;
1✔
120
    }
121

122
    auto in_edges = sdfg.in_edges(*current);
8✔
123

124
    // Loop detection
125
    std::unordered_set<const InterstateEdge*> loop_edges;
8✔
126
    for (auto& iedge : in_edges) {
13✔
127
        if (continues.find(&iedge) != continues.end()) {
5✔
128
            loop_edges.insert(&iedge);
1✔
129
        }
1✔
130
    }
131
    if (!loop_edges.empty()) {
8✔
132
        // 1. Determine nodes of loop body
133
        std::unordered_set<const control_flow::State*> body;
1✔
134
        for (auto back_edge : loop_edges) {
2✔
135
            auto loop_nodes = this->determine_loop_nodes(sdfg, back_edge->src(), back_edge->dst());
1✔
136
            body.insert(loop_nodes.begin(), loop_nodes.end());
1✔
137
        }
1✔
138

139
        // 2. Determine exit states and exit edges
140
        std::unordered_set<const control_flow::State*> exit_states;
1✔
141
        std::unordered_set<const control_flow::InterstateEdge*> exit_edges;
1✔
142
        for (auto node : body) {
4✔
143
            for (auto& edge : sdfg.out_edges(*node)) {
7✔
144
                if (body.find(&edge.dst()) == body.end()) {
4✔
145
                    exit_edges.insert(&edge);
1✔
146
                    exit_states.insert(&edge.dst());
1✔
147
                }
1✔
148
            }
149
        }
150
        if (exit_states.size() != 1) {
1✔
151
            throw UnstructuredControlFlowException();
×
152
        }
153
        const control_flow::State* exit_state = *exit_states.begin();
1✔
154

155
        for (auto& edge : breaks) {
1✔
156
            exit_edges.insert(edge);
×
157
        }
158

159
        // Collect debug information (could be removed when this is computed dynamically)
160
        DebugInfoRegion dbg_info = current->debug_info();
1✔
161
        for (auto& edge : in_edges) {
3✔
162
            dbg_info =
2✔
163
                DebugInfoRegion::merge(dbg_info, edge.debug_info(), this->structured_sdfg_->debug_info().elements());
2✔
164
        }
165
        for (auto node : body) {
4✔
166
            dbg_info =
3✔
167
                DebugInfoRegion::merge(dbg_info, node->debug_info(), this->structured_sdfg_->debug_info().elements());
3✔
168
        }
169
        for (auto edge : exit_edges) {
2✔
170
            dbg_info =
1✔
171
                DebugInfoRegion::merge(dbg_info, edge->debug_info(), this->structured_sdfg_->debug_info().elements());
1✔
172
        }
173

174
        // 3. Add while loop
175
        While& loop = this->add_while(scope, {}, structured_sdfg_->debug_info_.get_region(dbg_info.indices()));
1✔
176

177
        std::unordered_set<const control_flow::State*> loop_visited(visited);
1✔
178
        this->traverse_without_loop_detection(
1✔
179
            sdfg, loop.root(), current, exit_state, continues, exit_edges, pdom_tree, loop_visited
1✔
180
        );
181

182
        this->traverse_with_loop_detection(sdfg, scope, exit_state, end, continues, breaks, pdom_tree, visited);
1✔
183
    } else {
1✔
184
        this->traverse_without_loop_detection(sdfg, scope, current, end, continues, breaks, pdom_tree, visited);
7✔
185
    }
186
};
9✔
187

188
void StructuredSDFGBuilder::traverse_without_loop_detection(
8✔
189
    const SDFG& sdfg,
190
    Sequence& scope,
191
    const State* current,
192
    const State* end,
193
    const std::unordered_set<const InterstateEdge*>& continues,
194
    const std::unordered_set<const InterstateEdge*>& breaks,
195
    const std::unordered_map<const control_flow::State*, const control_flow::State*>& pdom_tree,
196
    std::unordered_set<const control_flow::State*>& visited
197
) {
198
    std::list<const State*> queue = {current};
8✔
199
    while (!queue.empty()) {
26✔
200
        auto curr = queue.front();
18✔
201
        queue.pop_front();
18✔
202
        if (curr == end) {
18✔
203
            continue;
3✔
204
        }
205

206
        if (visited.find(curr) != visited.end()) {
15✔
207
            throw UnstructuredControlFlowException();
×
208
        }
209
        visited.insert(curr);
15✔
210

211
        auto out_edges = sdfg.out_edges(*curr);
15✔
212
        auto out_degree = sdfg.out_degree(*curr);
15✔
213

214
        // Case 1: Sink node
215
        if (out_degree == 0) {
15✔
216
            this->add_block(
4✔
217
                scope, curr->dataflow(), {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
4✔
218
            );
219
            this->add_return(scope, {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices()));
4✔
220
            continue;
4✔
221
        }
222

223
        // Case 2: Transition
224
        if (out_degree == 1) {
11✔
225
            auto& oedge = *out_edges.begin();
8✔
226
            if (!oedge.is_unconditional()) {
8✔
227
                throw UnstructuredControlFlowException();
×
228
            }
229
            this->add_block(
8✔
230
                scope,
8✔
231
                curr->dataflow(),
8✔
232
                oedge.assignments(),
8✔
233
                structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
8✔
234
            );
235

236
            if (continues.find(&oedge) != continues.end()) {
8✔
NEW
237
                this->add_continue(scope, {}, structured_sdfg_->debug_info_.get_region(oedge.debug_info().indices()));
×
238
            } else if (breaks.find(&oedge) != breaks.end()) {
8✔
NEW
239
                this->add_break(scope, {}, structured_sdfg_->debug_info_.get_region(oedge.debug_info().indices()));
×
240
            } else {
×
241
                bool starts_loop = false;
8✔
242
                for (auto& iedge : sdfg.in_edges(oedge.dst())) {
19✔
243
                    if (continues.find(&iedge) != continues.end()) {
11✔
244
                        starts_loop = true;
×
245
                        break;
×
246
                    }
247
                }
248
                if (!starts_loop) {
8✔
249
                    queue.push_back(&oedge.dst());
8✔
250
                } else {
8✔
251
                    this->traverse_with_loop_detection(
×
252
                        sdfg, scope, &oedge.dst(), end, continues, breaks, pdom_tree, visited
×
253
                    );
254
                }
255
            }
256
            continue;
8✔
257
        }
258

259
        // Case 3: Branches
260
        if (out_degree > 1) {
3✔
261
            this->add_block(
3✔
262
                scope, curr->dataflow(), {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
3✔
263
            );
264

265
            std::vector<const InterstateEdge*> out_edges_vec;
3✔
266
            for (auto& edge : out_edges) {
9✔
267
                out_edges_vec.push_back(&edge);
6✔
268
            }
269

270
            // Best-effort approach: Find end of if-else
271
            // If not found, the branches may repeat paths yielding a large SDFG
272
            const control_flow::State* local_end = this->find_end_of_if_else(sdfg, curr, out_edges_vec, pdom_tree);
3✔
273
            if (local_end == nullptr) {
3✔
274
                local_end = end;
×
275
            }
×
276

277
            auto& if_else =
3✔
278
                this->add_if_else(scope, {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices()));
3✔
279
            for (size_t i = 0; i < out_degree; i++) {
9✔
280
                auto& out_edge = out_edges_vec[i];
6✔
281

282
                auto& branch = this->add_case(
6✔
283
                    if_else,
6✔
284
                    out_edge->condition(),
6✔
285
                    structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
6✔
286
                );
287
                if (!out_edge->assignments().empty()) {
6✔
288
                    this->add_block(
2✔
289
                        branch,
2✔
290
                        out_edge->assignments(),
2✔
291
                        structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
2✔
292
                    );
293
                }
2✔
294
                if (continues.find(out_edge) != continues.end()) {
6✔
295
                    this->add_continue(
1✔
296
                        branch, {}, structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
1✔
297
                    );
298
                } else if (breaks.find(out_edge) != breaks.end()) {
6✔
299
                    this->add_break(branch, {}, structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices()));
1✔
300
                } else {
1✔
301
                    std::unordered_set<const control_flow::State*> branch_visited(visited);
4✔
302
                    this->traverse_with_loop_detection(
4✔
303
                        sdfg, branch, &out_edge->dst(), local_end, continues, breaks, pdom_tree, branch_visited
4✔
304
                    );
305
                }
4✔
306
            }
6✔
307

308
            if (local_end != end) {
3✔
309
                bool starts_loop = false;
2✔
310
                for (auto& iedge : sdfg.in_edges(*local_end)) {
6✔
311
                    if (continues.find(&iedge) != continues.end()) {
4✔
312
                        starts_loop = true;
×
313
                        break;
×
314
                    }
315
                }
316
                if (!starts_loop) {
2✔
317
                    queue.push_back(local_end);
2✔
318
                } else {
2✔
319
                    this->traverse_with_loop_detection(sdfg, scope, local_end, end, continues, breaks, pdom_tree, visited);
×
320
                }
321
            }
2✔
322
            continue;
323
        }
3✔
324
    }
325
}
8✔
326

327
Function& StructuredSDFGBuilder::function() const { return static_cast<Function&>(*this->structured_sdfg_); };
5,573✔
328

329
StructuredSDFGBuilder::StructuredSDFGBuilder(std::unique_ptr<StructuredSDFG>& sdfg)
79✔
330
    : FunctionBuilder(), structured_sdfg_(std::move(sdfg)) {};
79✔
331

332
StructuredSDFGBuilder::StructuredSDFGBuilder(const std::string& name, FunctionType type)
518✔
333
    : FunctionBuilder(), structured_sdfg_(new StructuredSDFG(name, type)) {};
518✔
334

335
StructuredSDFGBuilder::StructuredSDFGBuilder(const SDFG& sdfg)
4✔
336
    : FunctionBuilder(), structured_sdfg_(new StructuredSDFG(sdfg.name(), sdfg.type())) {
4✔
337
    this->structured_sdfg_->debug_info(sdfg.debug_info());
4✔
338
    for (auto& entry : sdfg.structures_) {
4✔
339
        this->structured_sdfg_->structures_.insert({entry.first, entry.second->clone()});
×
340
    }
341

342
    for (auto& entry : sdfg.containers_) {
11✔
343
        this->structured_sdfg_->containers_.insert({entry.first, entry.second->clone()});
7✔
344
    }
345

346
    for (auto& arg : sdfg.arguments_) {
6✔
347
        this->structured_sdfg_->arguments_.push_back(arg);
2✔
348
    }
349

350
    for (auto& ext : sdfg.externals_) {
5✔
351
        this->structured_sdfg_->externals_.push_back(ext);
1✔
352
        this->structured_sdfg_->externals_linkage_types_[ext] = sdfg.linkage_type(ext);
1✔
353
    }
354

355
    for (auto& entry : sdfg.assumptions_) {
9✔
356
        this->structured_sdfg_->assumptions_.insert({entry.first, entry.second});
5✔
357
    }
358

359
    for (auto& entry : sdfg.metadata_) {
6✔
360
        this->structured_sdfg_->metadata_[entry.first] = entry.second;
2✔
361
    }
362

363
    this->traverse(sdfg);
4✔
364
};
4✔
365

366
StructuredSDFG& StructuredSDFGBuilder::subject() const { return *this->structured_sdfg_; };
1,086✔
367

368
std::unique_ptr<StructuredSDFG> StructuredSDFGBuilder::move() {
423✔
369
#ifndef NDEBUG
370
    this->structured_sdfg_->validate();
423✔
371
#endif
372

373
    return std::move(this->structured_sdfg_);
423✔
374
};
375

376
Element* StructuredSDFGBuilder::find_element_by_id(const size_t& element_id) const {
13✔
377
    auto& sdfg = this->subject();
13✔
378
    std::list<Element*> queue = {&sdfg.root()};
13✔
379
    while (!queue.empty()) {
55✔
380
        auto current = queue.front();
55✔
381
        queue.pop_front();
55✔
382

383
        if (current->element_id() == element_id) {
55✔
384
            return current;
13✔
385
        }
386

387
        if (auto block_stmt = dynamic_cast<structured_control_flow::Block*>(current)) {
42✔
388
            auto& dataflow = block_stmt->dataflow();
×
389
            for (auto& node : dataflow.nodes()) {
×
390
                queue.push_back(&node);
×
391
            }
392
            for (auto& edge : dataflow.edges()) {
×
393
                queue.push_back(&edge);
×
394
            }
395
        } else if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
42✔
396
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
44✔
397
                queue.push_back(&sequence_stmt->at(i).first);
22✔
398
                queue.push_back(&sequence_stmt->at(i).second);
22✔
399
            }
22✔
400
        } else if (dynamic_cast<structured_control_flow::Return*>(current)) {
42✔
401
            // Do nothing
402
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
20✔
403
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
404
                queue.push_back(&if_else_stmt->at(i).first);
×
405
            }
×
406
        } else if (auto for_stmt = dynamic_cast<structured_control_flow::For*>(current)) {
20✔
407
            queue.push_back(&for_stmt->root());
×
408
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
20✔
409
            queue.push_back(&while_stmt->root());
×
410
        } else if (dynamic_cast<structured_control_flow::Continue*>(current)) {
20✔
411
            // Do nothing
412
        } else if (dynamic_cast<structured_control_flow::Break*>(current)) {
20✔
413
            // Do nothing
414
        } else if (auto map_stmt = dynamic_cast<structured_control_flow::Map*>(current)) {
20✔
415
            queue.push_back(&map_stmt->root());
10✔
416
        }
10✔
417
    }
418

419
    return nullptr;
×
420
};
13✔
421

422
Sequence& StructuredSDFGBuilder::add_sequence(
27✔
423
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
424
) {
425
    parent.children_
54✔
426
        .push_back(std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
27✔
427
        );
428

429
    parent.transitions_.push_back(std::unique_ptr<Transition>(
54✔
430
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
27✔
431
    ));
432

433
    return static_cast<Sequence&>(*parent.children_.back().get());
27✔
434
};
×
435

436
Sequence& StructuredSDFGBuilder::add_sequence_before(
10✔
437
    Sequence& parent,
438
    ControlFlowNode& child,
439
    const sdfg::control_flow::Assignments& assignments,
440
    const DebugInfos& debug_info_elements
441
) {
442
    int index = parent.index(child);
10✔
443
    if (index == -1) {
10✔
444
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
445
    }
446

447
    parent.children_.insert(
20✔
448
        parent.children_.begin() + index,
10✔
449
        std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
10✔
450
    );
451

452
    parent.transitions_.insert(
20✔
453
        parent.transitions_.begin() + index,
10✔
454
        std::unique_ptr<
10✔
455
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
10✔
456
        )
457
    );
458

459
    return static_cast<Sequence&>(*parent.children_.at(index).get());
10✔
460
};
×
461

462
Sequence& StructuredSDFGBuilder::add_sequence_after(
×
463
    Sequence& parent,
464
    ControlFlowNode& child,
465
    const sdfg::control_flow::Assignments& assignments,
466
    const DebugInfos& debug_info_elements
467
) {
468
    int index = parent.index(child);
×
469
    if (index == -1) {
×
470
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
471
    }
472

473
    parent.children_.insert(
×
474
        parent.children_.begin() + index + 1,
×
NEW
475
        std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
476
    );
477

478
    parent.transitions_.insert(
×
479
        parent.transitions_.begin() + index + 1,
×
NEW
480
        std::unique_ptr<
×
NEW
481
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
482
        )
483
    );
484

485
    return static_cast<Sequence&>(*parent.children_.at(index + 1).get());
×
486
};
×
487

488
std::pair<Sequence&, Transition&> StructuredSDFGBuilder::
NEW
489
    add_sequence_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
490
    int index = parent.index(child);
×
491
    if (index == -1) {
×
492
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
493
    }
494

495
    parent.children_.insert(
×
NEW
496
        parent.children_.begin() + index,
×
NEW
497
        std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
498
    );
499

500
    parent.transitions_.insert(
×
501
        parent.transitions_.begin() + index,
×
NEW
502
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
503
        )
504
    );
505

506
    auto new_entry = parent.at(index);
×
507
    auto& new_block = dynamic_cast<structured_control_flow::Sequence&>(new_entry.first);
×
508

509
    return {new_block, new_entry.second};
×
510
};
×
511

512
void StructuredSDFGBuilder::remove_child(Sequence& parent, size_t index) {
25✔
513
    parent.children_.erase(parent.children_.begin() + index);
25✔
514
    parent.transitions_.erase(parent.transitions_.begin() + index);
25✔
515
};
25✔
516

517
void StructuredSDFGBuilder::remove_children(Sequence& parent) {
×
518
    parent.children_.clear();
×
519
    parent.transitions_.clear();
×
520
};
×
521

522
void StructuredSDFGBuilder::move_child(Sequence& source, size_t source_index, Sequence& target) {
10✔
523
    this->move_child(source, source_index, target, target.size());
10✔
524
};
10✔
525

526
void StructuredSDFGBuilder::move_child(Sequence& source, size_t source_index, Sequence& target, size_t target_index) {
10✔
527
    auto node_ptr = std::move(source.children_.at(source_index));
10✔
528
    auto trans_ptr = std::move(source.transitions_.at(source_index));
10✔
529
    source.children_.erase(source.children_.begin() + source_index);
10✔
530
    source.transitions_.erase(source.transitions_.begin() + source_index);
10✔
531

532
    trans_ptr->parent_ = &target;
10✔
533
    target.children_.insert(target.children_.begin() + target_index, std::move(node_ptr));
10✔
534
    target.transitions_.insert(target.transitions_.begin() + target_index, std::move(trans_ptr));
10✔
535
};
10✔
536

537
void StructuredSDFGBuilder::move_children(Sequence& source, Sequence& target) {
23✔
538
    this->move_children(source, target, target.size());
23✔
539
};
23✔
540

541
void StructuredSDFGBuilder::move_children(Sequence& source, Sequence& target, size_t target_index) {
23✔
542
    target.children_.insert(
46✔
543
        target.children_.begin() + target_index,
23✔
544
        std::make_move_iterator(source.children_.begin()),
23✔
545
        std::make_move_iterator(source.children_.end())
23✔
546
    );
547
    target.transitions_.insert(
46✔
548
        target.transitions_.begin() + target_index,
23✔
549
        std::make_move_iterator(source.transitions_.begin()),
23✔
550
        std::make_move_iterator(source.transitions_.end())
23✔
551
    );
552
    for (auto& trans : target.transitions_) {
52✔
553
        trans->parent_ = &target;
29✔
554
    }
555
    source.children_.clear();
23✔
556
    source.transitions_.clear();
23✔
557
};
23✔
558

559
Block& StructuredSDFGBuilder::add_block(
504✔
560
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
561
) {
562
    parent.children_
1,008✔
563
        .push_back(std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements))));
504✔
564

565
    parent.transitions_.push_back(std::unique_ptr<Transition>(
1,008✔
566
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
504✔
567
    ));
568

569
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.back());
504✔
570
    (*new_block.dataflow_).parent_ = &new_block;
504✔
571

572
    return new_block;
504✔
573
};
×
574

575
Block& StructuredSDFGBuilder::add_block(
18✔
576
    Sequence& parent,
577
    const data_flow::DataFlowGraph& data_flow_graph,
578
    const sdfg::control_flow::Assignments& assignments,
579
    const DebugInfos& debug_info_elements
580
) {
581
    parent.children_
36✔
582
        .push_back(std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements))));
18✔
583

584
    parent.transitions_.push_back(std::unique_ptr<Transition>(
36✔
585
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
18✔
586
    ));
587

588
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.back());
18✔
589
    (*new_block.dataflow_).parent_ = &new_block;
18✔
590

591
    this->add_dataflow(data_flow_graph, new_block);
18✔
592

593
    return new_block;
18✔
594
};
×
595

596
Block& StructuredSDFGBuilder::add_block_before(
11✔
597
    Sequence& parent,
598
    ControlFlowNode& child,
599
    const sdfg::control_flow::Assignments& assignments,
600
    const DebugInfos& debug_info_elements
601
) {
602
    int index = parent.index(child);
11✔
603
    if (index == -1) {
11✔
604
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
605
    }
606

607
    parent.children_.insert(
22✔
608
        parent.children_.begin() + index,
11✔
609
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
11✔
610
    );
611

612
    parent.transitions_.insert(
22✔
613
        parent.transitions_.begin() + index,
11✔
614
        std::unique_ptr<
11✔
615
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
11✔
616
        )
617
    );
618

619
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index));
11✔
620
    (*new_block.dataflow_).parent_ = &new_block;
11✔
621

622
    return new_block;
11✔
623
};
×
624

625
Block& StructuredSDFGBuilder::add_block_before(
×
626
    Sequence& parent,
627
    ControlFlowNode& child,
628
    data_flow::DataFlowGraph& data_flow_graph,
629
    const sdfg::control_flow::Assignments& assignments,
630
    const DebugInfos& debug_info_elements
631
) {
632
    int index = parent.index(child);
×
633
    if (index == -1) {
×
634
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
635
    }
636

NEW
637
    parent.children_.insert(
×
NEW
638
        parent.children_.begin() + index,
×
NEW
639
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
640
    );
641

642
    parent.transitions_.insert(
×
643
        parent.transitions_.begin() + index,
×
NEW
644
        std::unique_ptr<
×
NEW
645
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
646
        )
647
    );
648

649
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index));
×
650
    (*new_block.dataflow_).parent_ = &new_block;
×
651
    this->add_dataflow(data_flow_graph, new_block);
×
652

653
    return new_block;
×
654
};
×
655

656
Block& StructuredSDFGBuilder::add_block_after(
3✔
657
    Sequence& parent,
658
    ControlFlowNode& child,
659
    const sdfg::control_flow::Assignments& assignments,
660
    const DebugInfos& debug_info_elements
661
) {
662
    int index = parent.index(child);
3✔
663
    if (index == -1) {
3✔
664
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
665
    }
666

667
    parent.children_.insert(
6✔
668
        parent.children_.begin() + index + 1,
3✔
669
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
3✔
670
    );
671

672
    parent.transitions_.insert(
6✔
673
        parent.transitions_.begin() + index + 1,
3✔
674
        std::unique_ptr<
3✔
675
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
3✔
676
        )
677
    );
678

679
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index + 1));
3✔
680
    (*new_block.dataflow_).parent_ = &new_block;
3✔
681

682
    return new_block;
3✔
683
};
×
684

685
Block& StructuredSDFGBuilder::add_block_after(
×
686
    Sequence& parent,
687
    ControlFlowNode& child,
688
    data_flow::DataFlowGraph& data_flow_graph,
689
    const sdfg::control_flow::Assignments& assignments,
690
    const DebugInfos& debug_info_elements
691
) {
692
    int index = parent.index(child);
×
693
    if (index == -1) {
×
694
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
695
    }
696

697
    parent.children_.insert(
×
NEW
698
        parent.children_.begin() + index + 1,
×
NEW
699
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
700
    );
701

702
    parent.transitions_.insert(
×
703
        parent.transitions_.begin() + index + 1,
×
NEW
704
        std::unique_ptr<
×
NEW
705
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
706
        )
707
    );
708

709
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index + 1));
×
710
    (*new_block.dataflow_).parent_ = &new_block;
×
711
    this->add_dataflow(data_flow_graph, new_block);
×
712

713
    return new_block;
×
714
};
×
715

716
std::pair<Block&, Transition&> StructuredSDFGBuilder::
NEW
717
    add_block_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
718
    int index = parent.index(child);
×
719
    if (index == -1) {
×
720
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
721
    }
722

NEW
723
    parent.children_.insert(
×
NEW
724
        parent.children_.begin() + index,
×
NEW
725
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
726
    );
727

728
    parent.transitions_.insert(
×
729
        parent.transitions_.begin() + index,
×
NEW
730
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
731
        )
732
    );
733

734
    auto new_entry = parent.at(index);
×
735
    auto& new_block = static_cast<structured_control_flow::Block&>(new_entry.first);
×
736
    (*new_block.dataflow_).parent_ = &new_block;
×
737

738
    return {new_block, new_entry.second};
×
739
};
×
740

741
std::pair<Block&, Transition&> StructuredSDFGBuilder::add_block_before(
×
742
    Sequence& parent,
743
    ControlFlowNode& child,
744
    data_flow::DataFlowGraph& data_flow_graph,
745
    const DebugInfos& debug_info_elements
746
) {
747
    int index = parent.index(child);
×
748
    if (index == -1) {
×
749
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
750
    }
751

NEW
752
    parent.children_.insert(
×
NEW
753
        parent.children_.begin() + index,
×
NEW
754
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
755
    );
756

757
    parent.transitions_.insert(
×
758
        parent.transitions_.begin() + index,
×
NEW
759
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
760
        )
761
    );
762

763
    auto new_entry = parent.at(index);
×
764
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
765
    (*new_block.dataflow_).parent_ = &new_block;
×
766

767
    this->add_dataflow(data_flow_graph, new_block);
×
768

769
    return {new_block, new_entry.second};
×
770
};
×
771

772
std::pair<Block&, Transition&> StructuredSDFGBuilder::
NEW
773
    add_block_after(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
774
    int index = parent.index(child);
×
775
    if (index == -1) {
×
776
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
777
    }
778

779
    parent.children_.insert(
×
NEW
780
        parent.children_.begin() + index + 1,
×
NEW
781
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
782
    );
783

784
    parent.transitions_.insert(
×
785
        parent.transitions_.begin() + index + 1,
×
NEW
786
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
787
        )
788
    );
789

790
    auto new_entry = parent.at(index + 1);
×
791
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
792
    (*new_block.dataflow_).parent_ = &new_block;
×
793

794
    return {new_block, new_entry.second};
×
795
};
×
796

797
std::pair<Block&, Transition&> StructuredSDFGBuilder::add_block_after(
×
798
    Sequence& parent,
799
    ControlFlowNode& child,
800
    data_flow::DataFlowGraph& data_flow_graph,
801
    const DebugInfos& debug_info_elements
802
) {
803
    int index = parent.index(child);
×
804
    if (index == -1) {
×
805
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
806
    }
807

808
    parent.children_.insert(
×
NEW
809
        parent.children_.begin() + index + 1,
×
NEW
810
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
811
    );
812

813
    parent.transitions_.insert(
×
814
        parent.transitions_.begin() + index + 1,
×
NEW
815
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
816
        )
817
    );
818

819
    auto new_entry = parent.at(index + 1);
×
820
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
821
    (*new_block.dataflow_).parent_ = &new_block;
×
822

823
    this->add_dataflow(data_flow_graph, new_block);
×
824

825
    return {new_block, new_entry.second};
×
826
};
×
827

828
IfElse& StructuredSDFGBuilder::add_if_else(
40✔
829
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
830
) {
831
    parent.children_
80✔
832
        .push_back(std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements))));
40✔
833

834
    parent.transitions_.push_back(std::unique_ptr<Transition>(
80✔
835
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
40✔
836
    ));
837

838
    return static_cast<IfElse&>(*parent.children_.back().get());
40✔
839
};
×
840

841
IfElse& StructuredSDFGBuilder::add_if_else_before(
1✔
842
    Sequence& parent,
843
    ControlFlowNode& child,
844
    const sdfg::control_flow::Assignments& assignments,
845
    const DebugInfos& debug_info_elements
846
) {
847
    int index = parent.index(child);
1✔
848
    if (index == -1) {
1✔
849
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
850
    }
851

852
    parent.children_.insert(
2✔
853
        parent.children_.begin() + index,
1✔
854
        std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements)))
1✔
855
    );
856

857
    parent.transitions_.insert(
2✔
858
        parent.transitions_.begin() + index,
1✔
859
        std::unique_ptr<
1✔
860
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
1✔
861
        )
862
    );
863

864
    return static_cast<IfElse&>(*parent.children_.at(index));
1✔
865
};
×
866

867
IfElse& StructuredSDFGBuilder::add_if_else_after(
×
868
    Sequence& parent,
869
    ControlFlowNode& child,
870
    const sdfg::control_flow::Assignments& assignments,
871
    const DebugInfos& debug_info_elements
872
) {
873
    int index = parent.index(child);
×
874
    if (index == -1) {
×
875
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
876
    }
877

878
    parent.children_.insert(
×
NEW
879
        parent.children_.begin() + index + 1,
×
NEW
880
        std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
881
    );
882

883
    parent.transitions_.insert(
×
884
        parent.transitions_.begin() + index + 1,
×
NEW
885
        std::unique_ptr<
×
NEW
886
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
887
        )
888
    );
889

890
    return static_cast<IfElse&>(*parent.children_.at(index + 1));
×
891
};
×
892

893
std::pair<IfElse&, Transition&> StructuredSDFGBuilder::
NEW
894
    add_if_else_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
895
    int index = parent.index(child);
×
896
    if (index == -1) {
×
897
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
898
    }
899

NEW
900
    parent.children_.insert(
×
NEW
901
        parent.children_.begin() + index,
×
NEW
902
        std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
903
    );
904

905
    parent.transitions_.insert(
×
906
        parent.transitions_.begin() + index,
×
NEW
907
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
908
        )
909
    );
910

911
    auto new_entry = parent.at(index);
×
912
    auto& new_block = dynamic_cast<structured_control_flow::IfElse&>(new_entry.first);
×
913

914
    return {new_block, new_entry.second};
×
915
};
×
916

917
Sequence& StructuredSDFGBuilder::
918
    add_case(IfElse& scope, const sdfg::symbolic::Condition cond, const DebugInfos& debug_info_elements) {
64✔
919
    scope.cases_
128✔
920
        .push_back(std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
64✔
921
        );
922

923
    scope.conditions_.push_back(cond);
64✔
924
    return *scope.cases_.back();
64✔
925
};
×
926

NEW
927
void StructuredSDFGBuilder::remove_case(IfElse& scope, size_t index, const DebugInfos& debug_info_elements) {
×
928
    scope.cases_.erase(scope.cases_.begin() + index);
×
929
    scope.conditions_.erase(scope.conditions_.begin() + index);
×
930
};
×
931

932
While& StructuredSDFGBuilder::add_while(
33✔
933
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
934
) {
935
    parent.children_
66✔
936
        .push_back(std::unique_ptr<While>(new While(this->new_element_id(), fill_debug_info(debug_info_elements))));
33✔
937

938
    // Increment element id for body node
939
    this->new_element_id();
33✔
940

941
    parent.transitions_.push_back(std::unique_ptr<Transition>(
66✔
942
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
33✔
943
    ));
944

945
    return static_cast<While&>(*parent.children_.back().get());
33✔
946
};
×
947

948
For& StructuredSDFGBuilder::add_for(
121✔
949
    Sequence& parent,
950
    const symbolic::Symbol& indvar,
951
    const symbolic::Condition& condition,
952
    const symbolic::Expression& init,
953
    const symbolic::Expression& update,
954
    const sdfg::control_flow::Assignments& assignments,
955
    const DebugInfos& debug_info_elements
956
) {
957
    parent.children_.push_back(std::unique_ptr<For>(
242✔
958
        new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition)
121✔
959
    ));
960

961
    // Increment element id for body node
962
    this->new_element_id();
121✔
963

964
    parent.transitions_.push_back(std::unique_ptr<Transition>(
242✔
965
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
121✔
966
    ));
967

968
    return static_cast<For&>(*parent.children_.back().get());
121✔
969
};
×
970

971
For& StructuredSDFGBuilder::add_for_before(
6✔
972
    Sequence& parent,
973
    ControlFlowNode& child,
974
    const symbolic::Symbol& indvar,
975
    const symbolic::Condition& condition,
976
    const symbolic::Expression& init,
977
    const symbolic::Expression& update,
978
    const sdfg::control_flow::Assignments& assignments,
979
    const DebugInfos& debug_info_elements
980
) {
981
    int index = parent.index(child);
6✔
982
    if (index == -1) {
6✔
983
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
984
    }
985

986
    parent.children_.insert(
12✔
987
        parent.children_.begin() + index,
6✔
988
        std::unique_ptr<
6✔
989
            For>(new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition))
6✔
990
    );
991

992
    // Increment element id for body node
993
    this->new_element_id();
6✔
994

995
    parent.transitions_.insert(
12✔
996
        parent.transitions_.begin() + index,
6✔
997
        std::unique_ptr<
6✔
998
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
6✔
999
        )
1000
    );
1001

1002
    return static_cast<For&>(*parent.children_.at(index).get());
6✔
1003
};
×
1004

1005
For& StructuredSDFGBuilder::add_for_after(
2✔
1006
    Sequence& parent,
1007
    ControlFlowNode& child,
1008
    const symbolic::Symbol& indvar,
1009
    const symbolic::Condition& condition,
1010
    const symbolic::Expression& init,
1011
    const symbolic::Expression& update,
1012
    const sdfg::control_flow::Assignments& assignments,
1013
    const DebugInfos& debug_info_elements
1014
) {
1015
    int index = parent.index(child);
2✔
1016
    if (index == -1) {
2✔
1017
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1018
    }
1019

1020
    parent.children_.insert(
4✔
1021
        parent.children_.begin() + index + 1,
2✔
1022
        std::unique_ptr<
2✔
1023
            For>(new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition))
2✔
1024
    );
1025

1026
    // Increment element id for body node
1027
    this->new_element_id();
2✔
1028

1029
    parent.transitions_.insert(
4✔
1030
        parent.transitions_.begin() + index + 1,
2✔
1031
        std::unique_ptr<
2✔
1032
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
2✔
1033
        )
1034
    );
1035

1036
    return static_cast<For&>(*parent.children_.at(index + 1).get());
2✔
1037
};
×
1038

1039
Map& StructuredSDFGBuilder::add_map(
51✔
1040
    Sequence& parent,
1041
    const symbolic::Symbol& indvar,
1042
    const symbolic::Condition& condition,
1043
    const symbolic::Expression& init,
1044
    const symbolic::Expression& update,
1045
    const ScheduleType& schedule_type,
1046
    const sdfg::control_flow::Assignments& assignments,
1047
    const DebugInfos& debug_info_elements
1048
) {
1049
    parent.children_.push_back(std::unique_ptr<Map>(new Map(
102✔
1050
        this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
51✔
1051
    )));
1052

1053
    // Increment element id for body node
1054
    this->new_element_id();
51✔
1055

1056
    parent.transitions_.push_back(std::unique_ptr<Transition>(
102✔
1057
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
51✔
1058
    ));
1059

1060
    return static_cast<Map&>(*parent.children_.back().get());
51✔
1061
};
×
1062

1063
Map& StructuredSDFGBuilder::add_map_before(
6✔
1064
    Sequence& parent,
1065
    ControlFlowNode& child,
1066
    const symbolic::Symbol& indvar,
1067
    const symbolic::Condition& condition,
1068
    const symbolic::Expression& init,
1069
    const symbolic::Expression& update,
1070
    const ScheduleType& schedule_type,
1071
    const sdfg::control_flow::Assignments& assignments,
1072
    const DebugInfos& debug_info_elements
1073
) {
1074
    int index = parent.index(child);
6✔
1075
    if (index == -1) {
6✔
1076
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1077
    }
1078

1079
    parent.children_.insert(
12✔
1080
        parent.children_.begin() + index,
6✔
1081
        std::unique_ptr<Map>(new Map(
12✔
1082
            this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
6✔
1083
        ))
1084
    );
1085

1086
    // Increment element id for body node
1087
    this->new_element_id();
6✔
1088

1089
    parent.transitions_.insert(
12✔
1090
        parent.transitions_.begin() + index,
6✔
1091
        std::unique_ptr<
6✔
1092
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
6✔
1093
        )
1094
    );
1095

1096
    return static_cast<Map&>(*parent.children_.at(index).get());
6✔
1097
};
×
1098

1099
Map& StructuredSDFGBuilder::add_map_after(
12✔
1100
    Sequence& parent,
1101
    ControlFlowNode& child,
1102
    const symbolic::Symbol& indvar,
1103
    const symbolic::Condition& condition,
1104
    const symbolic::Expression& init,
1105
    const symbolic::Expression& update,
1106
    const ScheduleType& schedule_type,
1107
    const sdfg::control_flow::Assignments& assignments,
1108
    const DebugInfos& debug_info_elements
1109
) {
1110
    int index = parent.index(child);
12✔
1111
    if (index == -1) {
12✔
1112
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1113
    }
1114

1115
    parent.children_.insert(
24✔
1116
        parent.children_.begin() + index + 1,
12✔
1117
        std::unique_ptr<Map>(new Map(
24✔
1118
            this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
12✔
1119
        ))
1120
    );
1121

1122
    // Increment element id for body node
1123
    this->new_element_id();
12✔
1124

1125
    parent.transitions_.insert(
24✔
1126
        parent.transitions_.begin() + index + 1,
12✔
1127
        std::unique_ptr<
12✔
1128
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
12✔
1129
        )
1130
    );
1131

1132
    return static_cast<Map&>(*parent.children_.at(index + 1).get());
12✔
1133
};
×
1134

1135
Continue& StructuredSDFGBuilder::add_continue(
14✔
1136
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
1137
) {
1138
    // Check if continue is in a loop
1139
    analysis::AnalysisManager analysis_manager(this->subject());
14✔
1140
    auto& scope_tree_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
14✔
1141
    auto current_scope = scope_tree_analysis.parent_scope(&parent);
14✔
1142
    bool in_loop = false;
14✔
1143
    while (current_scope != nullptr) {
24✔
1144
        if (dynamic_cast<structured_control_flow::While*>(current_scope)) {
24✔
1145
            in_loop = true;
14✔
1146
            break;
14✔
1147
        } else if (dynamic_cast<structured_control_flow::For*>(current_scope)) {
10✔
1148
            throw UnstructuredControlFlowException();
×
1149
        }
1150
        current_scope = scope_tree_analysis.parent_scope(current_scope);
10✔
1151
    }
1152
    if (!in_loop) {
14✔
1153
        throw UnstructuredControlFlowException();
×
1154
    }
1155

1156
    parent.children_
28✔
1157
        .push_back(std::unique_ptr<Continue>(new Continue(this->new_element_id(), fill_debug_info(debug_info_elements)))
14✔
1158
        );
1159

1160
    parent.transitions_.push_back(std::unique_ptr<Transition>(
28✔
1161
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
14✔
1162
    ));
1163

1164
    return static_cast<Continue&>(*parent.children_.back().get());
14✔
1165
};
14✔
1166

1167
Break& StructuredSDFGBuilder::add_break(
15✔
1168
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
1169
) {
1170
    // Check if break is in a loop
1171
    analysis::AnalysisManager analysis_manager(this->subject());
15✔
1172
    auto& scope_tree_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
15✔
1173
    auto current_scope = scope_tree_analysis.parent_scope(&parent);
15✔
1174
    bool in_loop = false;
15✔
1175
    while (current_scope != nullptr) {
25✔
1176
        if (dynamic_cast<structured_control_flow::While*>(current_scope)) {
25✔
1177
            in_loop = true;
15✔
1178
            break;
15✔
1179
        } else if (dynamic_cast<structured_control_flow::For*>(current_scope)) {
10✔
1180
            throw UnstructuredControlFlowException();
×
1181
        }
1182
        current_scope = scope_tree_analysis.parent_scope(current_scope);
10✔
1183
    }
1184
    if (!in_loop) {
15✔
1185
        throw UnstructuredControlFlowException();
×
1186
    }
1187

1188
    parent.children_
30✔
1189
        .push_back(std::unique_ptr<Break>(new Break(this->new_element_id(), fill_debug_info(debug_info_elements))));
15✔
1190

1191
    parent.transitions_.push_back(std::unique_ptr<Transition>(
30✔
1192
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
15✔
1193
    ));
1194

1195
    return static_cast<Break&>(*parent.children_.back().get());
15✔
1196
};
15✔
1197

1198
Return& StructuredSDFGBuilder::add_return(
14✔
1199
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
1200
) {
1201
    parent.children_
28✔
1202
        .push_back(std::unique_ptr<Return>(new Return(this->new_element_id(), fill_debug_info(debug_info_elements))));
14✔
1203

1204
    parent.transitions_.push_back(std::unique_ptr<Transition>(
28✔
1205
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
14✔
1206
    ));
1207

1208
    return static_cast<Return&>(*parent.children_.back().get());
14✔
1209
};
×
1210

1211
For& StructuredSDFGBuilder::convert_while(
×
1212
    Sequence& parent,
1213
    While& loop,
1214
    const symbolic::Symbol& indvar,
1215
    const symbolic::Condition& condition,
1216
    const symbolic::Expression& init,
1217
    const symbolic::Expression& update
1218
) {
1219
    int index = parent.index(loop);
×
1220
    if (index == -1) {
×
1221
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1222
    }
1223

1224
    auto iter = parent.children_.begin() + index;
×
1225
    auto& new_iter = *parent.children_.insert(
×
1226
        iter + 1,
×
1227
        std::unique_ptr<For>(new For(this->new_element_id(), loop.debug_info(), indvar, init, update, condition))
×
1228
    );
1229

1230
    // Increment element id for body node
1231
    this->new_element_id();
×
1232

1233
    auto& for_loop = dynamic_cast<For&>(*new_iter);
×
1234
    this->move_children(loop.root(), for_loop.root());
×
1235

1236
    // Remove while loop
1237
    parent.children_.erase(parent.children_.begin() + index);
×
1238

1239
    return for_loop;
×
1240
};
×
1241

1242
Map& StructuredSDFGBuilder::convert_for(Sequence& parent, For& loop) {
8✔
1243
    int index = parent.index(loop);
8✔
1244
    if (index == -1) {
8✔
1245
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1246
    }
1247

1248
    auto iter = parent.children_.begin() + index;
8✔
1249
    auto& new_iter = *parent.children_.insert(
16✔
1250
        iter + 1,
8✔
1251
        std::unique_ptr<Map>(new Map(
16✔
1252
            this->new_element_id(),
8✔
1253
            loop.debug_info(),
8✔
1254
            loop.indvar(),
8✔
1255
            loop.init(),
8✔
1256
            loop.update(),
8✔
1257
            loop.condition(),
8✔
1258
            ScheduleType_Sequential::create()
8✔
1259
        ))
1260
    );
1261

1262
    // Increment element id for body node
1263
    this->new_element_id();
8✔
1264

1265
    auto& map = dynamic_cast<Map&>(*new_iter);
8✔
1266
    this->move_children(loop.root(), map.root());
8✔
1267

1268
    // Remove for loop
1269
    parent.children_.erase(parent.children_.begin() + index);
8✔
1270

1271
    return map;
8✔
1272
};
×
1273

1274
Sequence& StructuredSDFGBuilder::parent(const ControlFlowNode& node) {
2✔
1275
    std::list<structured_control_flow::ControlFlowNode*> queue = {&this->structured_sdfg_->root()};
2✔
1276
    while (!queue.empty()) {
2✔
1277
        auto current = queue.front();
2✔
1278
        queue.pop_front();
2✔
1279

1280
        if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
2✔
1281
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
2✔
1282
                if (&sequence_stmt->at(i).first == &node) {
2✔
1283
                    return *sequence_stmt;
2✔
1284
                }
1285
                queue.push_back(&sequence_stmt->at(i).first);
×
1286
            }
×
1287
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
×
1288
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
1289
                queue.push_back(&if_else_stmt->at(i).first);
×
1290
            }
×
1291
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
×
1292
            queue.push_back(&while_stmt->root());
×
1293
        } else if (auto loop_stmt = dynamic_cast<structured_control_flow::StructuredLoop*>(current)) {
×
1294
            queue.push_back(&loop_stmt->root());
×
1295
        }
×
1296
    }
1297

1298
    return this->structured_sdfg_->root();
×
1299
};
2✔
1300

1301
/***** Section: Dataflow Graph *****/
1302

1303
data_flow::AccessNode& StructuredSDFGBuilder::
1304
    add_access(structured_control_flow::Block& block, const std::string& data, const DebugInfos& debug_info_elements) {
608✔
1305
    auto vertex = boost::add_vertex(block.dataflow_->graph_);
608✔
1306
    auto res = block.dataflow_->nodes_.insert(
1,216✔
1307
        {vertex,
608✔
1308
         std::unique_ptr<data_flow::AccessNode>(new data_flow::AccessNode(
1,216✔
1309
             this->new_element_id(), fill_debug_info(debug_info_elements), vertex, block.dataflow(), data
608✔
1310
         ))}
1311
    );
1312

1313
    return dynamic_cast<data_flow::AccessNode&>(*(res.first->second));
608✔
1314
};
×
1315

1316
data_flow::Tasklet& StructuredSDFGBuilder::add_tasklet(
359✔
1317
    structured_control_flow::Block& block,
1318
    const data_flow::TaskletCode code,
1319
    const std::string& output,
1320
    const std::vector<std::string>& inputs,
1321
    const DebugInfos& debug_info_elements
1322
) {
1323
    auto vertex = boost::add_vertex(block.dataflow_->graph_);
359✔
1324
    auto res = block.dataflow_->nodes_.insert(
718✔
1325
        {vertex,
359✔
1326
         std::unique_ptr<data_flow::Tasklet>(new data_flow::Tasklet(
718✔
1327
             this->new_element_id(),
359✔
1328
             fill_debug_info(debug_info_elements),
359✔
1329
             vertex,
359✔
1330
             block.dataflow(),
359✔
1331
             code,
359✔
1332
             output,
359✔
1333
             inputs,
359✔
1334
             symbolic::__true__()
359✔
1335
         ))}
1336
    );
1337

1338
    return dynamic_cast<data_flow::Tasklet&>(*(res.first->second));
359✔
1339
};
×
1340

1341
data_flow::Memlet& StructuredSDFGBuilder::add_memlet(
560✔
1342
    structured_control_flow::Block& block,
1343
    data_flow::DataFlowNode& src,
1344
    const std::string& src_conn,
1345
    data_flow::DataFlowNode& dst,
1346
    const std::string& dst_conn,
1347
    const data_flow::Subset& subset,
1348
    const types::IType& base_type,
1349
    const DebugInfos& debug_info_elements
1350
) {
1351
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, block.dataflow_->graph_);
560✔
1352
    auto res = block.dataflow_->edges_.insert(
1,120✔
1353
        {edge.first,
1,120✔
1354
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
1,120✔
1355
             this->new_element_id(),
560✔
1356
             fill_debug_info(debug_info_elements),
560✔
1357
             edge.first,
560✔
1358
             block.dataflow(),
560✔
1359
             src,
560✔
1360
             src_conn,
560✔
1361
             dst,
560✔
1362
             dst_conn,
560✔
1363
             subset,
560✔
1364
             base_type
560✔
1365
         ))}
1366
    );
1367

1368
    auto& memlet = dynamic_cast<data_flow::Memlet&>(*(res.first->second));
560✔
1369
#ifndef NDEBUG
1370
    memlet.validate(*this->structured_sdfg_);
560✔
1371
#endif
1372

1373
    return memlet;
560✔
1374
};
×
1375

1376
data_flow::Memlet& StructuredSDFGBuilder::add_memlet(
41✔
1377
    structured_control_flow::Block& block,
1378
    data_flow::DataFlowNode& src,
1379
    const std::string& src_conn,
1380
    data_flow::DataFlowNode& dst,
1381
    const std::string& dst_conn,
1382
    const data_flow::Subset& begin_subset,
1383
    const data_flow::Subset& end_subset,
1384
    const types::IType& base_type,
1385
    const DebugInfos& debug_info_elements
1386
) {
1387
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, block.dataflow_->graph_);
41✔
1388
    auto res = block.dataflow_->edges_.insert(
82✔
1389
        {edge.first,
82✔
1390
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
82✔
1391
             this->new_element_id(),
41✔
1392
             fill_debug_info(debug_info_elements),
41✔
1393
             edge.first,
41✔
1394
             block.dataflow(),
41✔
1395
             src,
41✔
1396
             src_conn,
41✔
1397
             dst,
41✔
1398
             dst_conn,
41✔
1399
             begin_subset,
41✔
1400
             end_subset,
41✔
1401
             base_type
41✔
1402
         ))}
1403
    );
1404

1405
    auto& memlet = dynamic_cast<data_flow::Memlet&>(*(res.first->second));
41✔
1406
#ifndef NDEBUG
1407
    memlet.validate(*this->structured_sdfg_);
41✔
1408
#endif
1409

1410
    return memlet;
41✔
1411
};
×
1412

1413
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
96✔
1414
    structured_control_flow::Block& block,
1415
    data_flow::AccessNode& src,
1416
    data_flow::Tasklet& dst,
1417
    const std::string& dst_conn,
1418
    const data_flow::Subset& subset,
1419
    const types::IType& base_type,
1420
    const DebugInfos& debug_info_elements
1421
) {
1422
    return this->add_memlet(block, src, "void", dst, dst_conn, subset, base_type, debug_info_elements);
96✔
1423
};
×
1424

1425
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
87✔
1426
    structured_control_flow::Block& block,
1427
    data_flow::Tasklet& src,
1428
    const std::string& src_conn,
1429
    data_flow::AccessNode& dst,
1430
    const data_flow::Subset& subset,
1431
    const types::IType& base_type,
1432
    const DebugInfos& debug_info_elements
1433
) {
1434
    return this->add_memlet(block, src, src_conn, dst, "void", subset, base_type, debug_info_elements);
87✔
1435
};
×
1436

1437
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
91✔
1438
    structured_control_flow::Block& block,
1439
    data_flow::AccessNode& src,
1440
    data_flow::Tasklet& dst,
1441
    const std::string& dst_conn,
1442
    const data_flow::Subset& subset,
1443
    const DebugInfos& debug_info_elements
1444
) {
1445
    auto& src_type = this->structured_sdfg_->type(src.data());
91✔
1446
    auto& base_type = types::infer_type(*this->structured_sdfg_, src_type, subset);
91✔
1447
    if (base_type.type_id() != types::TypeID::Scalar) {
91✔
1448
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
1449
    }
1450
    return this->add_memlet(block, src, "void", dst, dst_conn, subset, src_type, debug_info_elements);
91✔
1451
};
×
1452

1453
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
267✔
1454
    structured_control_flow::Block& block,
1455
    data_flow::Tasklet& src,
1456
    const std::string& src_conn,
1457
    data_flow::AccessNode& dst,
1458
    const data_flow::Subset& subset,
1459
    const DebugInfos& debug_info_elements
1460
) {
1461
    auto& dst_type = this->structured_sdfg_->type(dst.data());
267✔
1462
    auto& base_type = types::infer_type(*this->structured_sdfg_, dst_type, subset);
267✔
1463
    if (base_type.type_id() != types::TypeID::Scalar) {
267✔
1464
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
1465
    }
1466
    return this->add_memlet(block, src, src_conn, dst, "void", subset, dst_type, debug_info_elements);
267✔
1467
};
×
1468

1469
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
14✔
1470
    structured_control_flow::Block& block,
1471
    data_flow::AccessNode& src,
1472
    data_flow::LibraryNode& dst,
1473
    const std::string& dst_conn,
1474
    const data_flow::Subset& begin_subset,
1475
    const data_flow::Subset& end_subset,
1476
    const types::IType& base_type,
1477
    const DebugInfos& debug_info_elements
1478
) {
1479
    return this->add_memlet(block, src, "void", dst, dst_conn, begin_subset, end_subset, base_type, debug_info_elements);
14✔
1480
};
×
1481

1482
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
9✔
1483
    structured_control_flow::Block& block,
1484
    data_flow::LibraryNode& src,
1485
    const std::string& src_conn,
1486
    data_flow::AccessNode& dst,
1487
    const data_flow::Subset& begin_subset,
1488
    const data_flow::Subset& end_subset,
1489
    const types::IType& base_type,
1490
    const DebugInfos& debug_info_elements
1491
) {
1492
    return this->add_memlet(block, src, src_conn, dst, "void", begin_subset, end_subset, base_type, debug_info_elements);
9✔
1493
};
×
1494

1495
data_flow::Memlet& StructuredSDFGBuilder::add_reference_memlet(
8✔
1496
    structured_control_flow::Block& block,
1497
    data_flow::AccessNode& src,
1498
    data_flow::AccessNode& dst,
1499
    const data_flow::Subset& subset,
1500
    const types::IType& base_type,
1501
    const DebugInfos& debug_info_elements
1502
) {
1503
    return this->add_memlet(block, src, "void", dst, "ref", subset, base_type, debug_info_elements);
8✔
1504
};
×
1505

1506
data_flow::Memlet& StructuredSDFGBuilder::add_dereference_memlet(
11✔
1507
    structured_control_flow::Block& block,
1508
    data_flow::AccessNode& src,
1509
    data_flow::AccessNode& dst,
1510
    bool derefs_src,
1511
    const types::IType& base_type,
1512
    const DebugInfos& debug_info_elements
1513
) {
1514
    if (derefs_src) {
11✔
1515
        return this->add_memlet(block, src, "void", dst, "deref", {symbolic::zero()}, base_type, debug_info_elements);
6✔
1516
    } else {
1517
        return this->add_memlet(block, src, "deref", dst, "void", {symbolic::zero()}, base_type, debug_info_elements);
5✔
1518
    }
1519
};
11✔
1520

1521
void StructuredSDFGBuilder::remove_memlet(structured_control_flow::Block& block, const data_flow::Memlet& edge) {
19✔
1522
    auto& graph = block.dataflow();
19✔
1523
    auto e = edge.edge();
19✔
1524
    boost::remove_edge(e, graph.graph_);
19✔
1525
    graph.edges_.erase(e);
19✔
1526
};
19✔
1527

1528
void StructuredSDFGBuilder::remove_node(structured_control_flow::Block& block, const data_flow::DataFlowNode& node) {
18✔
1529
    auto& graph = block.dataflow();
18✔
1530
    auto v = node.vertex();
18✔
1531
    boost::remove_vertex(v, graph.graph_);
18✔
1532
    graph.nodes_.erase(v);
18✔
1533
};
18✔
1534

1535
void StructuredSDFGBuilder::clear_node(structured_control_flow::Block& block, const data_flow::CodeNode& node) {
8✔
1536
    auto& graph = block.dataflow();
8✔
1537

1538
    std::unordered_set<const data_flow::DataFlowNode*> to_delete = {&node};
8✔
1539

1540
    // Delete incoming
1541
    std::list<const data_flow::Memlet*> iedges;
8✔
1542
    for (auto& iedge : graph.in_edges(node)) {
15✔
1543
        iedges.push_back(&iedge);
7✔
1544
    }
1545
    for (auto iedge : iedges) {
15✔
1546
        auto& src = iedge->src();
7✔
1547
        to_delete.insert(&src);
7✔
1548

1549
        auto edge = iedge->edge();
7✔
1550
        graph.edges_.erase(edge);
7✔
1551
        boost::remove_edge(edge, graph.graph_);
7✔
1552
    }
1553

1554
    // Delete outgoing
1555
    std::list<const data_flow::Memlet*> oedges;
8✔
1556
    for (auto& oedge : graph.out_edges(node)) {
16✔
1557
        oedges.push_back(&oedge);
8✔
1558
    }
1559
    for (auto oedge : oedges) {
16✔
1560
        auto& dst = oedge->dst();
8✔
1561
        to_delete.insert(&dst);
8✔
1562

1563
        auto edge = oedge->edge();
8✔
1564
        graph.edges_.erase(edge);
8✔
1565
        boost::remove_edge(edge, graph.graph_);
8✔
1566
    }
1567

1568
    // Delete nodes
1569
    for (auto obsolete_node : to_delete) {
31✔
1570
        if (graph.in_degree(*obsolete_node) == 0 && graph.out_degree(*obsolete_node) == 0) {
23✔
1571
            auto vertex = obsolete_node->vertex();
23✔
1572
            graph.nodes_.erase(vertex);
23✔
1573
            boost::remove_vertex(vertex, graph.graph_);
23✔
1574
        }
23✔
1575
    }
1576
};
8✔
1577

1578
void StructuredSDFGBuilder::clear_node(structured_control_flow::Block& block, const data_flow::AccessNode& node) {
1✔
1579
    auto& graph = block.dataflow();
1✔
1580
    if (graph.out_degree(node) != 0) {
1✔
1581
        throw InvalidSDFGException("StructuredSDFGBuilder: Access node has outgoing edges");
×
1582
    }
1583

1584
    std::list<const data_flow::Memlet*> tmp;
1✔
1585
    std::list<const data_flow::DataFlowNode*> queue = {&node};
1✔
1586
    while (!queue.empty()) {
3✔
1587
        auto current = queue.front();
2✔
1588
        queue.pop_front();
2✔
1589
        if (current != &node) {
2✔
1590
            if (dynamic_cast<const data_flow::AccessNode*>(current)) {
1✔
1591
                if (graph.in_degree(*current) > 0 || graph.out_degree(*current) > 0) {
×
1592
                    continue;
×
1593
                }
1594
            }
×
1595
        }
1✔
1596

1597
        tmp.clear();
2✔
1598
        for (auto& iedge : graph.in_edges(*current)) {
3✔
1599
            tmp.push_back(&iedge);
1✔
1600
        }
1601
        for (auto iedge : tmp) {
3✔
1602
            auto& src = iedge->src();
1✔
1603
            queue.push_back(&src);
1✔
1604

1605
            auto edge = iedge->edge();
1✔
1606
            graph.edges_.erase(edge);
1✔
1607
            boost::remove_edge(edge, graph.graph_);
1✔
1608
        }
1609

1610
        auto vertex = current->vertex();
2✔
1611
        graph.nodes_.erase(vertex);
2✔
1612
        boost::remove_vertex(vertex, graph.graph_);
2✔
1613
    }
1614
};
1✔
1615

1616
void StructuredSDFGBuilder::add_dataflow(const data_flow::DataFlowGraph& from, Block& to) {
18✔
1617
    auto& to_dataflow = to.dataflow();
18✔
1618

1619
    std::unordered_map<graph::Vertex, graph::Vertex> node_mapping;
18✔
1620
    for (auto& entry : from.nodes_) {
19✔
1621
        auto vertex = boost::add_vertex(to_dataflow.graph_);
1✔
1622
        to_dataflow.nodes_.insert({vertex, entry.second->clone(this->new_element_id(), vertex, to_dataflow)});
1✔
1623
        node_mapping.insert({entry.first, vertex});
1✔
1624
    }
1625

1626
    for (auto& entry : from.edges_) {
18✔
1627
        auto src = node_mapping[entry.second->src().vertex()];
×
1628
        auto dst = node_mapping[entry.second->dst().vertex()];
×
1629

1630
        auto edge = boost::add_edge(src, dst, to_dataflow.graph_);
×
1631

1632
        to_dataflow.edges_.insert(
×
1633
            {edge.first,
×
1634
             entry.second->clone(
×
1635
                 this->new_element_id(), edge.first, to_dataflow, *to_dataflow.nodes_[src], *to_dataflow.nodes_[dst]
×
1636
             )}
1637
        );
1638
    }
1639
};
18✔
1640

1641
size_t StructuredSDFGBuilder::add_debug_info_element(const DebugInfo& element) {
3✔
1642
    return structured_sdfg_->debug_info().add_element(element);
3✔
NEW
1643
}
×
1644

1645
const DebugTable& StructuredSDFGBuilder::debug_info() const { return structured_sdfg_->debug_info(); }
143✔
1646

1647
} // namespace builder
1648
} // 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