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

daisytuner / sdfglib / 17651658650

11 Sep 2025 04:58PM UTC coverage: 61.012% (+1.3%) from 59.755%
17651658650

Pull #219

github

web-flow
Merge 742a12367 into f744ac9f5
Pull Request #219: stdlib Library Nodes and ConstantNodes

499 of 1681 new or added lines in 81 files covered. (29.68%)

95 existing lines in 36 files now uncovered.

9718 of 15928 relevant lines covered (61.01%)

108.0 hits per line

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

67.14
/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,517✔
20
    std::unordered_set<size_t> indices;
3,517✔
21
    for (const auto& element : debug_info_elements) {
3,520✔
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,517✔
26
}
3,517✔
27

28
std::unordered_set<const control_flow::State*> StructuredSDFGBuilder::
29
    determine_loop_nodes(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
    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
    if (pdom == nullptr) {
3✔
NEW
83
        return nullptr;
×
84
    }
85

86
    for (auto& edge : out_edges) {
9✔
87
        if (!post_dominates(pdom, &edge->dst(), pdom_tree)) {
6✔
88
            return nullptr;
×
89
        }
90
    }
91

92
    return pdom;
3✔
93
}
3✔
94

95
void StructuredSDFGBuilder::traverse(SDFG& sdfg) {
4✔
96
    // Start of SDFGS
97
    Sequence& root = *structured_sdfg_->root_;
4✔
98
    const State* start_state = &sdfg.start_state();
4✔
99

100
    auto pdom_tree = sdfg.post_dominator_tree();
4✔
101

102
    std::unordered_set<const InterstateEdge*> breaks;
4✔
103
    std::unordered_set<const InterstateEdge*> continues;
4✔
104
    for (auto& edge : sdfg.back_edges()) {
5✔
105
        continues.insert(edge);
1✔
106
    }
107

108
    std::unordered_set<const control_flow::State*> visited;
4✔
109
    this->traverse_with_loop_detection(sdfg, root, start_state, nullptr, continues, breaks, pdom_tree, visited);
4✔
110
};
4✔
111

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

126
    auto in_edges = sdfg.in_edges(*current);
8✔
127

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

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

159
        for (auto& edge : breaks) {
1✔
160
            exit_edges.insert(edge);
×
161
        }
162

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

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

181
        std::unordered_set<const control_flow::State*> loop_visited(visited);
1✔
182
        this->traverse_without_loop_detection(
1✔
183
            sdfg, loop.root(), current, exit_state, continues, exit_edges, pdom_tree, loop_visited
1✔
184
        );
185

186
        this->traverse_with_loop_detection(sdfg, scope, exit_state, end, continues, breaks, pdom_tree, visited);
1✔
187
    } else {
1✔
188
        this->traverse_without_loop_detection(sdfg, scope, current, end, continues, breaks, pdom_tree, visited);
7✔
189
    }
190
};
9✔
191

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

210
        if (visited.find(curr) != visited.end()) {
17✔
211
            throw UnstructuredControlFlowException();
×
212
        }
213
        visited.insert(curr);
17✔
214

215
        auto out_edges = sdfg.out_edges(*curr);
17✔
216
        auto out_degree = sdfg.out_degree(*curr);
17✔
217

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

224
            auto return_state = dynamic_cast<const control_flow::ReturnState*>(curr);
4✔
225
            assert(return_state != nullptr);
4✔
226
            this->add_return(
4✔
227
                scope,
4✔
228
                return_state->data(),
4✔
229
                return_state->unreachable(),
4✔
230
                {},
4✔
231
                structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
4✔
232
            );
233
            continue;
4✔
234
        }
235

236
        // Case 2: Transition
237
        if (out_degree == 1) {
13✔
238
            auto& oedge = *out_edges.begin();
10✔
239
            if (!oedge.is_unconditional()) {
10✔
240
                throw UnstructuredControlFlowException();
×
241
            }
242
            this->add_block(
10✔
243
                scope,
10✔
244
                curr->dataflow(),
10✔
245
                oedge.assignments(),
10✔
246
                structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
10✔
247
            );
248

249
            if (continues.find(&oedge) != continues.end()) {
10✔
250
                this->add_continue(scope, {}, structured_sdfg_->debug_info_.get_region(oedge.debug_info().indices()));
×
251
            } else if (breaks.find(&oedge) != breaks.end()) {
10✔
252
                this->add_break(scope, {}, structured_sdfg_->debug_info_.get_region(oedge.debug_info().indices()));
×
253
            } else {
×
254
                bool starts_loop = false;
10✔
255
                for (auto& iedge : sdfg.in_edges(oedge.dst())) {
23✔
256
                    if (continues.find(&iedge) != continues.end()) {
13✔
257
                        starts_loop = true;
×
258
                        break;
×
259
                    }
260
                }
261
                if (!starts_loop) {
10✔
262
                    queue.push_back(&oedge.dst());
10✔
263
                } else {
10✔
264
                    this->traverse_with_loop_detection(
×
265
                        sdfg, scope, &oedge.dst(), end, continues, breaks, pdom_tree, visited
×
266
                    );
267
                }
268
            }
269
            continue;
10✔
270
        }
271

272
        // Case 3: Branches
273
        if (out_degree > 1) {
3✔
274
            this->add_block(
3✔
275
                scope, curr->dataflow(), {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices())
3✔
276
            );
277

278
            std::vector<const InterstateEdge*> out_edges_vec;
3✔
279
            for (auto& edge : out_edges) {
9✔
280
                out_edges_vec.push_back(&edge);
6✔
281
            }
282

283
            // Best-effort approach: Find end of if-else
284
            // If not found, the branches may repeat paths yielding a large SDFG
285
            const control_flow::State* local_end = this->find_end_of_if_else(sdfg, curr, out_edges_vec, pdom_tree);
3✔
286
            if (local_end == nullptr) {
3✔
287
                local_end = end;
×
288
            }
×
289

290
            auto& if_else =
3✔
291
                this->add_if_else(scope, {}, structured_sdfg_->debug_info_.get_region(curr->debug_info().indices()));
3✔
292
            for (size_t i = 0; i < out_degree; i++) {
9✔
293
                auto& out_edge = out_edges_vec[i];
6✔
294

295
                auto& branch = this->add_case(
6✔
296
                    if_else,
6✔
297
                    out_edge->condition(),
6✔
298
                    structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
6✔
299
                );
300
                if (!out_edge->assignments().empty()) {
6✔
301
                    this->add_block(
2✔
302
                        branch,
2✔
303
                        out_edge->assignments(),
2✔
304
                        structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
2✔
305
                    );
306
                }
2✔
307
                if (continues.find(out_edge) != continues.end()) {
6✔
308
                    this->add_continue(
1✔
309
                        branch, {}, structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices())
1✔
310
                    );
311
                } else if (breaks.find(out_edge) != breaks.end()) {
6✔
312
                    this->add_break(branch, {}, structured_sdfg_->debug_info_.get_region(out_edge->debug_info().indices()));
1✔
313
                } else {
1✔
314
                    std::unordered_set<const control_flow::State*> branch_visited(visited);
4✔
315
                    this->traverse_with_loop_detection(
4✔
316
                        sdfg, branch, &out_edge->dst(), local_end, continues, breaks, pdom_tree, branch_visited
4✔
317
                    );
318
                }
4✔
319
            }
6✔
320

321
            if (local_end != end) {
3✔
322
                bool starts_loop = false;
2✔
323
                for (auto& iedge : sdfg.in_edges(*local_end)) {
6✔
324
                    if (continues.find(&iedge) != continues.end()) {
4✔
325
                        starts_loop = true;
×
326
                        break;
×
327
                    }
328
                }
329
                if (!starts_loop) {
2✔
330
                    queue.push_back(local_end);
2✔
331
                } else {
2✔
332
                    this->traverse_with_loop_detection(sdfg, scope, local_end, end, continues, breaks, pdom_tree, visited);
×
333
                }
334
            }
2✔
335
            continue;
336
        }
3✔
337
    }
338
}
8✔
339

340
Function& StructuredSDFGBuilder::function() const { return static_cast<Function&>(*this->structured_sdfg_); };
5,674✔
341

342
StructuredSDFGBuilder::StructuredSDFGBuilder(std::unique_ptr<StructuredSDFG>& sdfg)
80✔
343
    : FunctionBuilder(), structured_sdfg_(std::move(sdfg)) {};
80✔
344

345
StructuredSDFGBuilder::StructuredSDFGBuilder(const std::string& name, FunctionType type)
511✔
346
    : FunctionBuilder(), structured_sdfg_(new StructuredSDFG(name, type)) {};
511✔
347

348
StructuredSDFGBuilder::StructuredSDFGBuilder(const std::string& name, FunctionType type, const types::IType& return_type)
5✔
349
    : FunctionBuilder(), structured_sdfg_(new StructuredSDFG(name, type, return_type)) {};
5✔
350

351
StructuredSDFGBuilder::StructuredSDFGBuilder(SDFG& sdfg)
4✔
352
    : FunctionBuilder(), structured_sdfg_(new StructuredSDFG(sdfg.name(), sdfg.type(), sdfg.return_type())) {
4✔
353
    this->structured_sdfg_->debug_info(sdfg.debug_info());
4✔
354

355
    for (auto& entry : sdfg.structures_) {
4✔
356
        this->structured_sdfg_->structures_.insert({entry.first, entry.second->clone()});
×
357
    }
358

359
    for (auto& entry : sdfg.containers_) {
11✔
360
        this->structured_sdfg_->containers_.insert({entry.first, entry.second->clone()});
7✔
361
    }
362

363
    for (auto& arg : sdfg.arguments_) {
6✔
364
        this->structured_sdfg_->arguments_.push_back(arg);
2✔
365
    }
366

367
    for (auto& ext : sdfg.externals_) {
5✔
368
        this->structured_sdfg_->externals_.push_back(ext);
1✔
369
        this->structured_sdfg_->externals_linkage_types_[ext] = sdfg.linkage_type(ext);
1✔
370
    }
371

372
    for (auto& entry : sdfg.assumptions_) {
9✔
373
        this->structured_sdfg_->assumptions_.insert({entry.first, entry.second});
5✔
374
    }
375

376
    for (auto& entry : sdfg.metadata_) {
6✔
377
        this->structured_sdfg_->metadata_[entry.first] = entry.second;
2✔
378
    }
379

380
    this->traverse(sdfg);
4✔
381
};
4✔
382

383
StructuredSDFG& StructuredSDFGBuilder::subject() const { return *this->structured_sdfg_; };
1,560✔
384

385
std::unique_ptr<StructuredSDFG> StructuredSDFGBuilder::move() {
257✔
386
#ifndef NDEBUG
387
    this->structured_sdfg_->validate();
257✔
388
#endif
389

390
    return std::move(this->structured_sdfg_);
257✔
391
};
392

NEW
393
void StructuredSDFGBuilder::rename_container(const std::string& old_name, const std::string& new_name) const {
×
NEW
394
    FunctionBuilder::rename_container(old_name, new_name);
×
395

NEW
396
    this->structured_sdfg_->root_->replace(symbolic::symbol(old_name), symbolic::symbol(new_name));
×
NEW
397
};
×
398

399
Element* StructuredSDFGBuilder::find_element_by_id(const size_t& element_id) const {
13✔
400
    auto& sdfg = this->subject();
13✔
401
    std::list<Element*> queue = {&sdfg.root()};
13✔
402
    while (!queue.empty()) {
55✔
403
        auto current = queue.front();
55✔
404
        queue.pop_front();
55✔
405

406
        if (current->element_id() == element_id) {
55✔
407
            return current;
13✔
408
        }
409

410
        if (auto block_stmt = dynamic_cast<structured_control_flow::Block*>(current)) {
42✔
411
            auto& dataflow = block_stmt->dataflow();
×
412
            for (auto& node : dataflow.nodes()) {
×
413
                queue.push_back(&node);
×
414
            }
415
            for (auto& edge : dataflow.edges()) {
×
416
                queue.push_back(&edge);
×
417
            }
418
        } else if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
42✔
419
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
44✔
420
                queue.push_back(&sequence_stmt->at(i).first);
22✔
421
                queue.push_back(&sequence_stmt->at(i).second);
22✔
422
            }
22✔
423
        } else if (dynamic_cast<structured_control_flow::Return*>(current)) {
42✔
424
            // Do nothing
425
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
20✔
426
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
427
                queue.push_back(&if_else_stmt->at(i).first);
×
428
            }
×
429
        } else if (auto for_stmt = dynamic_cast<structured_control_flow::For*>(current)) {
20✔
430
            queue.push_back(&for_stmt->root());
×
431
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
20✔
432
            queue.push_back(&while_stmt->root());
×
433
        } else if (dynamic_cast<structured_control_flow::Continue*>(current)) {
20✔
434
            // Do nothing
435
        } else if (dynamic_cast<structured_control_flow::Break*>(current)) {
20✔
436
            // Do nothing
437
        } else if (auto map_stmt = dynamic_cast<structured_control_flow::Map*>(current)) {
20✔
438
            queue.push_back(&map_stmt->root());
10✔
439
        }
10✔
440
    }
441

442
    return nullptr;
×
443
};
13✔
444

445
Sequence& StructuredSDFGBuilder::add_sequence(
27✔
446
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
447
) {
448
    parent.children_
54✔
449
        .push_back(std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
27✔
450
        );
451

452
    parent.transitions_.push_back(std::unique_ptr<Transition>(
54✔
453
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
27✔
454
    ));
455

456
    return static_cast<Sequence&>(*parent.children_.back().get());
27✔
457
};
×
458

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

470
    parent.children_.insert(
20✔
471
        parent.children_.begin() + index,
10✔
472
        std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
10✔
473
    );
474

475
    parent.transitions_.insert(
20✔
476
        parent.transitions_.begin() + index,
10✔
477
        std::unique_ptr<
10✔
478
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
10✔
479
        )
480
    );
481

482
    return static_cast<Sequence&>(*parent.children_.at(index).get());
10✔
483
};
×
484

485
Sequence& StructuredSDFGBuilder::add_sequence_after(
×
486
    Sequence& parent,
487
    ControlFlowNode& child,
488
    const sdfg::control_flow::Assignments& assignments,
489
    const DebugInfos& debug_info_elements
490
) {
491
    int index = parent.index(child);
×
492
    if (index == -1) {
×
493
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
494
    }
495

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

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

508
    return static_cast<Sequence&>(*parent.children_.at(index + 1).get());
×
509
};
×
510

511
std::pair<Sequence&, Transition&> StructuredSDFGBuilder::
512
    add_sequence_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
513
    int index = parent.index(child);
×
514
    if (index == -1) {
×
515
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
516
    }
517

518
    parent.children_.insert(
×
519
        parent.children_.begin() + index,
×
520
        std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
521
    );
522

523
    parent.transitions_.insert(
×
524
        parent.transitions_.begin() + index,
×
525
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
526
        )
527
    );
528

529
    auto new_entry = parent.at(index);
×
530
    auto& new_block = dynamic_cast<structured_control_flow::Sequence&>(new_entry.first);
×
531

532
    return {new_block, new_entry.second};
×
533
};
×
534

535
void StructuredSDFGBuilder::remove_child(Sequence& parent, size_t index) {
25✔
536
    parent.children_.erase(parent.children_.begin() + index);
25✔
537
    parent.transitions_.erase(parent.transitions_.begin() + index);
25✔
538
};
25✔
539

540
void StructuredSDFGBuilder::remove_children(Sequence& parent) {
×
541
    parent.children_.clear();
×
542
    parent.transitions_.clear();
×
543
};
×
544

545
void StructuredSDFGBuilder::move_child(Sequence& source, size_t source_index, Sequence& target) {
10✔
546
    this->move_child(source, source_index, target, target.size());
10✔
547
};
10✔
548

549
void StructuredSDFGBuilder::move_child(Sequence& source, size_t source_index, Sequence& target, size_t target_index) {
10✔
550
    auto node_ptr = std::move(source.children_.at(source_index));
10✔
551
    auto trans_ptr = std::move(source.transitions_.at(source_index));
10✔
552
    source.children_.erase(source.children_.begin() + source_index);
10✔
553
    source.transitions_.erase(source.transitions_.begin() + source_index);
10✔
554

555
    trans_ptr->parent_ = &target;
10✔
556
    target.children_.insert(target.children_.begin() + target_index, std::move(node_ptr));
10✔
557
    target.transitions_.insert(target.transitions_.begin() + target_index, std::move(trans_ptr));
10✔
558
};
10✔
559

560
void StructuredSDFGBuilder::move_children(Sequence& source, Sequence& target) {
23✔
561
    this->move_children(source, target, target.size());
23✔
562
};
23✔
563

564
void StructuredSDFGBuilder::move_children(Sequence& source, Sequence& target, size_t target_index) {
23✔
565
    target.children_.insert(
46✔
566
        target.children_.begin() + target_index,
23✔
567
        std::make_move_iterator(source.children_.begin()),
23✔
568
        std::make_move_iterator(source.children_.end())
23✔
569
    );
570
    target.transitions_.insert(
46✔
571
        target.transitions_.begin() + target_index,
23✔
572
        std::make_move_iterator(source.transitions_.begin()),
23✔
573
        std::make_move_iterator(source.transitions_.end())
23✔
574
    );
575
    for (auto& trans : target.transitions_) {
52✔
576
        trans->parent_ = &target;
29✔
577
    }
578
    source.children_.clear();
23✔
579
    source.transitions_.clear();
23✔
580
};
23✔
581

582
Block& StructuredSDFGBuilder::add_block(
504✔
583
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
584
) {
585
    parent.children_
1,008✔
586
        .push_back(std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements))));
504✔
587

588
    parent.transitions_.push_back(std::unique_ptr<Transition>(
1,008✔
589
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
504✔
590
    ));
591

592
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.back());
504✔
593
    (*new_block.dataflow_).parent_ = &new_block;
504✔
594

595
    return new_block;
504✔
596
};
×
597

598
Block& StructuredSDFGBuilder::add_block(
20✔
599
    Sequence& parent,
600
    const data_flow::DataFlowGraph& data_flow_graph,
601
    const sdfg::control_flow::Assignments& assignments,
602
    const DebugInfos& debug_info_elements
603
) {
604
    parent.children_
40✔
605
        .push_back(std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements))));
20✔
606

607
    parent.transitions_.push_back(std::unique_ptr<Transition>(
40✔
608
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
20✔
609
    ));
610

611
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.back());
20✔
612
    (*new_block.dataflow_).parent_ = &new_block;
20✔
613

614
    this->add_dataflow(data_flow_graph, new_block);
20✔
615

616
    return new_block;
20✔
617
};
×
618

619
Block& StructuredSDFGBuilder::add_block_before(
11✔
620
    Sequence& parent,
621
    ControlFlowNode& child,
622
    const sdfg::control_flow::Assignments& assignments,
623
    const DebugInfos& debug_info_elements
624
) {
625
    int index = parent.index(child);
11✔
626
    if (index == -1) {
11✔
627
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
628
    }
629

630
    parent.children_.insert(
22✔
631
        parent.children_.begin() + index,
11✔
632
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
11✔
633
    );
634

635
    parent.transitions_.insert(
22✔
636
        parent.transitions_.begin() + index,
11✔
637
        std::unique_ptr<
11✔
638
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
11✔
639
        )
640
    );
641

642
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index));
11✔
643
    (*new_block.dataflow_).parent_ = &new_block;
11✔
644

645
    return new_block;
11✔
646
};
×
647

648
Block& StructuredSDFGBuilder::add_block_before(
×
649
    Sequence& parent,
650
    ControlFlowNode& child,
651
    data_flow::DataFlowGraph& data_flow_graph,
652
    const sdfg::control_flow::Assignments& assignments,
653
    const DebugInfos& debug_info_elements
654
) {
655
    int index = parent.index(child);
×
656
    if (index == -1) {
×
657
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
658
    }
659

660
    parent.children_.insert(
×
661
        parent.children_.begin() + index,
×
662
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
663
    );
664

665
    parent.transitions_.insert(
×
666
        parent.transitions_.begin() + index,
×
667
        std::unique_ptr<
×
668
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
669
        )
670
    );
671

672
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index));
×
673
    (*new_block.dataflow_).parent_ = &new_block;
×
674
    this->add_dataflow(data_flow_graph, new_block);
×
675

676
    return new_block;
×
677
};
×
678

679
Block& StructuredSDFGBuilder::add_block_after(
3✔
680
    Sequence& parent,
681
    ControlFlowNode& child,
682
    const sdfg::control_flow::Assignments& assignments,
683
    const DebugInfos& debug_info_elements
684
) {
685
    int index = parent.index(child);
3✔
686
    if (index == -1) {
3✔
687
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
688
    }
689

690
    parent.children_.insert(
6✔
691
        parent.children_.begin() + index + 1,
3✔
692
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
3✔
693
    );
694

695
    parent.transitions_.insert(
6✔
696
        parent.transitions_.begin() + index + 1,
3✔
697
        std::unique_ptr<
3✔
698
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
3✔
699
        )
700
    );
701

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

705
    return new_block;
3✔
706
};
×
707

708
Block& StructuredSDFGBuilder::add_block_after(
×
709
    Sequence& parent,
710
    ControlFlowNode& child,
711
    data_flow::DataFlowGraph& data_flow_graph,
712
    const sdfg::control_flow::Assignments& assignments,
713
    const DebugInfos& debug_info_elements
714
) {
715
    int index = parent.index(child);
×
716
    if (index == -1) {
×
717
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
718
    }
719

720
    parent.children_.insert(
×
721
        parent.children_.begin() + index + 1,
×
722
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
723
    );
724

725
    parent.transitions_.insert(
×
726
        parent.transitions_.begin() + index + 1,
×
727
        std::unique_ptr<
×
728
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
×
729
        )
730
    );
731

732
    auto& new_block = static_cast<structured_control_flow::Block&>(*parent.children_.at(index + 1));
×
733
    (*new_block.dataflow_).parent_ = &new_block;
×
734
    this->add_dataflow(data_flow_graph, new_block);
×
735

736
    return new_block;
×
737
};
×
738

739
std::pair<Block&, Transition&> StructuredSDFGBuilder::
740
    add_block_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
741
    int index = parent.index(child);
×
742
    if (index == -1) {
×
743
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
744
    }
745

746
    parent.children_.insert(
×
747
        parent.children_.begin() + index,
×
748
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
749
    );
750

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

757
    auto new_entry = parent.at(index);
×
758
    auto& new_block = static_cast<structured_control_flow::Block&>(new_entry.first);
×
759
    (*new_block.dataflow_).parent_ = &new_block;
×
760

761
    return {new_block, new_entry.second};
×
762
};
×
763

764
std::pair<Block&, Transition&> StructuredSDFGBuilder::add_block_before(
×
765
    Sequence& parent,
766
    ControlFlowNode& child,
767
    data_flow::DataFlowGraph& data_flow_graph,
768
    const DebugInfos& debug_info_elements
769
) {
770
    int index = parent.index(child);
×
771
    if (index == -1) {
×
772
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
773
    }
774

775
    parent.children_.insert(
×
776
        parent.children_.begin() + index,
×
777
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
778
    );
779

780
    parent.transitions_.insert(
×
781
        parent.transitions_.begin() + index,
×
782
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
783
        )
784
    );
785

786
    auto new_entry = parent.at(index);
×
787
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
788
    (*new_block.dataflow_).parent_ = &new_block;
×
789

790
    this->add_dataflow(data_flow_graph, new_block);
×
791

792
    return {new_block, new_entry.second};
×
793
};
×
794

795
std::pair<Block&, Transition&> StructuredSDFGBuilder::
796
    add_block_after(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
797
    int index = parent.index(child);
×
798
    if (index == -1) {
×
799
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
800
    }
801

802
    parent.children_.insert(
×
803
        parent.children_.begin() + index + 1,
×
804
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
805
    );
806

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

813
    auto new_entry = parent.at(index + 1);
×
814
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
815
    (*new_block.dataflow_).parent_ = &new_block;
×
816

817
    return {new_block, new_entry.second};
×
818
};
×
819

820
std::pair<Block&, Transition&> StructuredSDFGBuilder::add_block_after(
×
821
    Sequence& parent,
822
    ControlFlowNode& child,
823
    data_flow::DataFlowGraph& data_flow_graph,
824
    const DebugInfos& debug_info_elements
825
) {
826
    int index = parent.index(child);
×
827
    if (index == -1) {
×
828
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
829
    }
830

831
    parent.children_.insert(
×
832
        parent.children_.begin() + index + 1,
×
833
        std::unique_ptr<Block>(new Block(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
834
    );
835

836
    parent.transitions_.insert(
×
837
        parent.transitions_.begin() + index + 1,
×
838
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
839
        )
840
    );
841

842
    auto new_entry = parent.at(index + 1);
×
843
    auto& new_block = dynamic_cast<structured_control_flow::Block&>(new_entry.first);
×
844
    (*new_block.dataflow_).parent_ = &new_block;
×
845

846
    this->add_dataflow(data_flow_graph, new_block);
×
847

848
    return {new_block, new_entry.second};
×
849
};
×
850

851
IfElse& StructuredSDFGBuilder::add_if_else(
41✔
852
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
853
) {
854
    parent.children_
82✔
855
        .push_back(std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements))));
41✔
856

857
    parent.transitions_.push_back(std::unique_ptr<Transition>(
82✔
858
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
41✔
859
    ));
860

861
    return static_cast<IfElse&>(*parent.children_.back().get());
41✔
862
};
×
863

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

875
    parent.children_.insert(
2✔
876
        parent.children_.begin() + index,
1✔
877
        std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements)))
1✔
878
    );
879

880
    parent.transitions_.insert(
2✔
881
        parent.transitions_.begin() + index,
1✔
882
        std::unique_ptr<
1✔
883
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
1✔
884
        )
885
    );
886

887
    return static_cast<IfElse&>(*parent.children_.at(index));
1✔
888
};
×
889

890
IfElse& StructuredSDFGBuilder::add_if_else_after(
×
891
    Sequence& parent,
892
    ControlFlowNode& child,
893
    const sdfg::control_flow::Assignments& assignments,
894
    const DebugInfos& debug_info_elements
895
) {
896
    int index = parent.index(child);
×
897
    if (index == -1) {
×
898
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
899
    }
900

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

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

913
    return static_cast<IfElse&>(*parent.children_.at(index + 1));
×
914
};
×
915

916
std::pair<IfElse&, Transition&> StructuredSDFGBuilder::
917
    add_if_else_before(Sequence& parent, ControlFlowNode& child, const DebugInfos& debug_info_elements) {
×
918
    int index = parent.index(child);
×
919
    if (index == -1) {
×
920
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
921
    }
922

923
    parent.children_.insert(
×
924
        parent.children_.begin() + index,
×
925
        std::unique_ptr<IfElse>(new IfElse(this->new_element_id(), fill_debug_info(debug_info_elements)))
×
926
    );
927

928
    parent.transitions_.insert(
×
929
        parent.transitions_.begin() + index,
×
930
        std::unique_ptr<Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent)
×
931
        )
932
    );
933

934
    auto new_entry = parent.at(index);
×
935
    auto& new_block = dynamic_cast<structured_control_flow::IfElse&>(new_entry.first);
×
936

937
    return {new_block, new_entry.second};
×
938
};
×
939

940
Sequence& StructuredSDFGBuilder::
941
    add_case(IfElse& scope, const sdfg::symbolic::Condition cond, const DebugInfos& debug_info_elements) {
66✔
942
    scope.cases_
132✔
943
        .push_back(std::unique_ptr<Sequence>(new Sequence(this->new_element_id(), fill_debug_info(debug_info_elements)))
66✔
944
        );
945

946
    scope.conditions_.push_back(cond);
66✔
947
    return *scope.cases_.back();
66✔
948
};
×
949

950
void StructuredSDFGBuilder::remove_case(IfElse& scope, size_t index, const DebugInfos& debug_info_elements) {
×
951
    scope.cases_.erase(scope.cases_.begin() + index);
×
952
    scope.conditions_.erase(scope.conditions_.begin() + index);
×
953
};
×
954

955
While& StructuredSDFGBuilder::add_while(
33✔
956
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
957
) {
958
    parent.children_
66✔
959
        .push_back(std::unique_ptr<While>(new While(this->new_element_id(), fill_debug_info(debug_info_elements))));
33✔
960

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

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

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

971
For& StructuredSDFGBuilder::add_for(
119✔
972
    Sequence& parent,
973
    const symbolic::Symbol& indvar,
974
    const symbolic::Condition& condition,
975
    const symbolic::Expression& init,
976
    const symbolic::Expression& update,
977
    const sdfg::control_flow::Assignments& assignments,
978
    const DebugInfos& debug_info_elements
979
) {
980
    parent.children_.push_back(std::unique_ptr<For>(
238✔
981
        new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition)
119✔
982
    ));
983

984
    // Increment element id for body node
985
    this->new_element_id();
119✔
986

987
    parent.transitions_.push_back(std::unique_ptr<Transition>(
238✔
988
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
119✔
989
    ));
990

991
    return static_cast<For&>(*parent.children_.back().get());
119✔
992
};
×
993

994
For& StructuredSDFGBuilder::add_for_before(
6✔
995
    Sequence& parent,
996
    ControlFlowNode& child,
997
    const symbolic::Symbol& indvar,
998
    const symbolic::Condition& condition,
999
    const symbolic::Expression& init,
1000
    const symbolic::Expression& update,
1001
    const sdfg::control_flow::Assignments& assignments,
1002
    const DebugInfos& debug_info_elements
1003
) {
1004
    int index = parent.index(child);
6✔
1005
    if (index == -1) {
6✔
1006
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1007
    }
1008

1009
    parent.children_.insert(
12✔
1010
        parent.children_.begin() + index,
6✔
1011
        std::unique_ptr<
6✔
1012
            For>(new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition))
6✔
1013
    );
1014

1015
    // Increment element id for body node
1016
    this->new_element_id();
6✔
1017

1018
    parent.transitions_.insert(
12✔
1019
        parent.transitions_.begin() + index,
6✔
1020
        std::unique_ptr<
6✔
1021
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
6✔
1022
        )
1023
    );
1024

1025
    return static_cast<For&>(*parent.children_.at(index).get());
6✔
1026
};
×
1027

1028
For& StructuredSDFGBuilder::add_for_after(
2✔
1029
    Sequence& parent,
1030
    ControlFlowNode& child,
1031
    const symbolic::Symbol& indvar,
1032
    const symbolic::Condition& condition,
1033
    const symbolic::Expression& init,
1034
    const symbolic::Expression& update,
1035
    const sdfg::control_flow::Assignments& assignments,
1036
    const DebugInfos& debug_info_elements
1037
) {
1038
    int index = parent.index(child);
2✔
1039
    if (index == -1) {
2✔
1040
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1041
    }
1042

1043
    parent.children_.insert(
4✔
1044
        parent.children_.begin() + index + 1,
2✔
1045
        std::unique_ptr<
2✔
1046
            For>(new For(this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition))
2✔
1047
    );
1048

1049
    // Increment element id for body node
1050
    this->new_element_id();
2✔
1051

1052
    parent.transitions_.insert(
4✔
1053
        parent.transitions_.begin() + index + 1,
2✔
1054
        std::unique_ptr<
2✔
1055
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
2✔
1056
        )
1057
    );
1058

1059
    return static_cast<For&>(*parent.children_.at(index + 1).get());
2✔
1060
};
×
1061

1062
Map& StructuredSDFGBuilder::add_map(
51✔
1063
    Sequence& parent,
1064
    const symbolic::Symbol& indvar,
1065
    const symbolic::Condition& condition,
1066
    const symbolic::Expression& init,
1067
    const symbolic::Expression& update,
1068
    const ScheduleType& schedule_type,
1069
    const sdfg::control_flow::Assignments& assignments,
1070
    const DebugInfos& debug_info_elements
1071
) {
1072
    parent.children_.push_back(std::unique_ptr<Map>(new Map(
102✔
1073
        this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
51✔
1074
    )));
1075

1076
    // Increment element id for body node
1077
    this->new_element_id();
51✔
1078

1079
    parent.transitions_.push_back(std::unique_ptr<Transition>(
102✔
1080
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
51✔
1081
    ));
1082

1083
    return static_cast<Map&>(*parent.children_.back().get());
51✔
1084
};
×
1085

1086
Map& StructuredSDFGBuilder::add_map_before(
6✔
1087
    Sequence& parent,
1088
    ControlFlowNode& child,
1089
    const symbolic::Symbol& indvar,
1090
    const symbolic::Condition& condition,
1091
    const symbolic::Expression& init,
1092
    const symbolic::Expression& update,
1093
    const ScheduleType& schedule_type,
1094
    const sdfg::control_flow::Assignments& assignments,
1095
    const DebugInfos& debug_info_elements
1096
) {
1097
    int index = parent.index(child);
6✔
1098
    if (index == -1) {
6✔
1099
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1100
    }
1101

1102
    parent.children_.insert(
12✔
1103
        parent.children_.begin() + index,
6✔
1104
        std::unique_ptr<Map>(new Map(
12✔
1105
            this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
6✔
1106
        ))
1107
    );
1108

1109
    // Increment element id for body node
1110
    this->new_element_id();
6✔
1111

1112
    parent.transitions_.insert(
12✔
1113
        parent.transitions_.begin() + index,
6✔
1114
        std::unique_ptr<
6✔
1115
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
6✔
1116
        )
1117
    );
1118

1119
    return static_cast<Map&>(*parent.children_.at(index).get());
6✔
1120
};
×
1121

1122
Map& StructuredSDFGBuilder::add_map_after(
12✔
1123
    Sequence& parent,
1124
    ControlFlowNode& child,
1125
    const symbolic::Symbol& indvar,
1126
    const symbolic::Condition& condition,
1127
    const symbolic::Expression& init,
1128
    const symbolic::Expression& update,
1129
    const ScheduleType& schedule_type,
1130
    const sdfg::control_flow::Assignments& assignments,
1131
    const DebugInfos& debug_info_elements
1132
) {
1133
    int index = parent.index(child);
12✔
1134
    if (index == -1) {
12✔
1135
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1136
    }
1137

1138
    parent.children_.insert(
24✔
1139
        parent.children_.begin() + index + 1,
12✔
1140
        std::unique_ptr<Map>(new Map(
24✔
1141
            this->new_element_id(), fill_debug_info(debug_info_elements), indvar, init, update, condition, schedule_type
12✔
1142
        ))
1143
    );
1144

1145
    // Increment element id for body node
1146
    this->new_element_id();
12✔
1147

1148
    parent.transitions_.insert(
24✔
1149
        parent.transitions_.begin() + index + 1,
12✔
1150
        std::unique_ptr<
12✔
1151
            Transition>(new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
12✔
1152
        )
1153
    );
1154

1155
    return static_cast<Map&>(*parent.children_.at(index + 1).get());
12✔
1156
};
×
1157

1158
Continue& StructuredSDFGBuilder::add_continue(
14✔
1159
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
1160
) {
1161
    // Check if continue is in a loop
1162
    analysis::AnalysisManager analysis_manager(this->subject());
14✔
1163
    auto& scope_tree_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
14✔
1164
    auto current_scope = scope_tree_analysis.parent_scope(&parent);
14✔
1165
    bool in_loop = false;
14✔
1166
    while (current_scope != nullptr) {
24✔
1167
        if (dynamic_cast<structured_control_flow::While*>(current_scope)) {
24✔
1168
            in_loop = true;
14✔
1169
            break;
14✔
1170
        } else if (dynamic_cast<structured_control_flow::For*>(current_scope)) {
10✔
1171
            throw UnstructuredControlFlowException();
×
1172
        }
1173
        current_scope = scope_tree_analysis.parent_scope(current_scope);
10✔
1174
    }
1175
    if (!in_loop) {
14✔
1176
        throw UnstructuredControlFlowException();
×
1177
    }
1178

1179
    parent.children_
28✔
1180
        .push_back(std::unique_ptr<Continue>(new Continue(this->new_element_id(), fill_debug_info(debug_info_elements)))
14✔
1181
        );
1182

1183
    parent.transitions_.push_back(std::unique_ptr<Transition>(
28✔
1184
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
14✔
1185
    ));
1186

1187
    return static_cast<Continue&>(*parent.children_.back().get());
14✔
1188
};
14✔
1189

1190
Break& StructuredSDFGBuilder::add_break(
15✔
1191
    Sequence& parent, const sdfg::control_flow::Assignments& assignments, const DebugInfos& debug_info_elements
1192
) {
1193
    // Check if break is in a loop
1194
    analysis::AnalysisManager analysis_manager(this->subject());
15✔
1195
    auto& scope_tree_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
15✔
1196
    auto current_scope = scope_tree_analysis.parent_scope(&parent);
15✔
1197
    bool in_loop = false;
15✔
1198
    while (current_scope != nullptr) {
25✔
1199
        if (dynamic_cast<structured_control_flow::While*>(current_scope)) {
25✔
1200
            in_loop = true;
15✔
1201
            break;
15✔
1202
        } else if (dynamic_cast<structured_control_flow::For*>(current_scope)) {
10✔
1203
            throw UnstructuredControlFlowException();
×
1204
        }
1205
        current_scope = scope_tree_analysis.parent_scope(current_scope);
10✔
1206
    }
1207
    if (!in_loop) {
15✔
1208
        throw UnstructuredControlFlowException();
×
1209
    }
1210

1211
    parent.children_
30✔
1212
        .push_back(std::unique_ptr<Break>(new Break(this->new_element_id(), fill_debug_info(debug_info_elements))));
15✔
1213

1214
    parent.transitions_.push_back(std::unique_ptr<Transition>(
30✔
1215
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
15✔
1216
    ));
1217

1218
    return static_cast<Break&>(*parent.children_.back().get());
15✔
1219
};
15✔
1220

1221
Return& StructuredSDFGBuilder::add_return(
16✔
1222
    Sequence& parent,
1223
    const std::string& data,
1224
    bool unreachable,
1225
    const sdfg::control_flow::Assignments& assignments,
1226
    const DebugInfos& debug_info_elements
1227
) {
1228
    parent.children_
32✔
1229
        .push_back(std::unique_ptr<
16✔
1230
                   Return>(new Return(this->new_element_id(), fill_debug_info(debug_info_elements), data, unreachable))
16✔
1231
        );
1232

1233
    parent.transitions_.push_back(std::unique_ptr<Transition>(
32✔
1234
        new Transition(this->new_element_id(), fill_debug_info(debug_info_elements), parent, assignments)
16✔
1235
    ));
1236

1237
    return static_cast<Return&>(*parent.children_.back().get());
16✔
1238
};
×
1239

1240
For& StructuredSDFGBuilder::convert_while(
×
1241
    Sequence& parent,
1242
    While& loop,
1243
    const symbolic::Symbol& indvar,
1244
    const symbolic::Condition& condition,
1245
    const symbolic::Expression& init,
1246
    const symbolic::Expression& update
1247
) {
1248
    int index = parent.index(loop);
×
1249
    if (index == -1) {
×
1250
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1251
    }
1252

1253
    auto iter = parent.children_.begin() + index;
×
1254
    auto& new_iter = *parent.children_.insert(
×
1255
        iter + 1,
×
1256
        std::unique_ptr<For>(new For(this->new_element_id(), loop.debug_info(), indvar, init, update, condition))
×
1257
    );
1258

1259
    // Increment element id for body node
1260
    this->new_element_id();
×
1261

1262
    auto& for_loop = dynamic_cast<For&>(*new_iter);
×
1263
    this->move_children(loop.root(), for_loop.root());
×
1264

1265
    // Remove while loop
1266
    parent.children_.erase(parent.children_.begin() + index);
×
1267

1268
    return for_loop;
×
1269
};
×
1270

1271
Map& StructuredSDFGBuilder::convert_for(Sequence& parent, For& loop) {
8✔
1272
    int index = parent.index(loop);
8✔
1273
    if (index == -1) {
8✔
1274
        throw InvalidSDFGException("StructuredSDFGBuilder: Child not found");
×
1275
    }
1276

1277
    auto iter = parent.children_.begin() + index;
8✔
1278
    auto& new_iter = *parent.children_.insert(
16✔
1279
        iter + 1,
8✔
1280
        std::unique_ptr<Map>(new Map(
16✔
1281
            this->new_element_id(),
8✔
1282
            loop.debug_info(),
8✔
1283
            loop.indvar(),
8✔
1284
            loop.init(),
8✔
1285
            loop.update(),
8✔
1286
            loop.condition(),
8✔
1287
            ScheduleType_Sequential::create()
8✔
1288
        ))
1289
    );
1290

1291
    // Increment element id for body node
1292
    this->new_element_id();
8✔
1293

1294
    auto& map = dynamic_cast<Map&>(*new_iter);
8✔
1295
    this->move_children(loop.root(), map.root());
8✔
1296

1297
    // Remove for loop
1298
    parent.children_.erase(parent.children_.begin() + index);
8✔
1299

1300
    return map;
8✔
1301
};
×
1302

1303
Sequence& StructuredSDFGBuilder::parent(const ControlFlowNode& node) {
2✔
1304
    std::list<structured_control_flow::ControlFlowNode*> queue = {&this->structured_sdfg_->root()};
2✔
1305
    while (!queue.empty()) {
2✔
1306
        auto current = queue.front();
2✔
1307
        queue.pop_front();
2✔
1308

1309
        if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
2✔
1310
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
2✔
1311
                if (&sequence_stmt->at(i).first == &node) {
2✔
1312
                    return *sequence_stmt;
2✔
1313
                }
1314
                queue.push_back(&sequence_stmt->at(i).first);
×
1315
            }
×
1316
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
×
1317
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
1318
                queue.push_back(&if_else_stmt->at(i).first);
×
1319
            }
×
1320
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
×
1321
            queue.push_back(&while_stmt->root());
×
1322
        } else if (auto loop_stmt = dynamic_cast<structured_control_flow::StructuredLoop*>(current)) {
×
1323
            queue.push_back(&loop_stmt->root());
×
1324
        }
×
1325
    }
1326

1327
    return this->structured_sdfg_->root();
×
1328
};
2✔
1329

1330
/***** Section: Dataflow Graph *****/
1331

1332
data_flow::AccessNode& StructuredSDFGBuilder::
1333
    add_access(structured_control_flow::Block& block, const std::string& data, const DebugInfos& debug_info_elements) {
605✔
1334
    auto vertex = boost::add_vertex(block.dataflow_->graph_);
605✔
1335
    auto res = block.dataflow_->nodes_.insert(
1,210✔
1336
        {vertex,
605✔
1337
         std::unique_ptr<data_flow::AccessNode>(new data_flow::AccessNode(
1,210✔
1338
             this->new_element_id(), fill_debug_info(debug_info_elements), vertex, block.dataflow(), data
605✔
1339
         ))}
1340
    );
1341

1342
    return dynamic_cast<data_flow::AccessNode&>(*(res.first->second));
605✔
1343
};
×
1344

1345
data_flow::ConstantNode& StructuredSDFGBuilder::add_constant(
52✔
1346
    structured_control_flow::Block& block,
1347
    const std::string& data,
1348
    const types::IType& type,
1349
    const DebugInfos& debug_info_elements
1350
) {
1351
    auto vertex = boost::add_vertex(block.dataflow_->graph_);
52✔
1352
    auto res = block.dataflow_->nodes_.insert(
104✔
1353
        {vertex,
52✔
1354
         std::unique_ptr<data_flow::ConstantNode>(new data_flow::ConstantNode(
104✔
1355
             this->new_element_id(), fill_debug_info(debug_info_elements), vertex, block.dataflow(), data, type
52✔
1356
         ))}
1357
    );
1358

1359
    return dynamic_cast<data_flow::ConstantNode&>(*(res.first->second));
52✔
1360
};
×
1361

1362

1363
data_flow::Tasklet& StructuredSDFGBuilder::add_tasklet(
360✔
1364
    structured_control_flow::Block& block,
1365
    const data_flow::TaskletCode code,
1366
    const std::string& output,
1367
    const std::vector<std::string>& inputs,
1368
    const DebugInfos& debug_info_elements
1369
) {
1370
    auto vertex = boost::add_vertex(block.dataflow_->graph_);
360✔
1371
    auto res = block.dataflow_->nodes_.insert(
720✔
1372
        {vertex,
360✔
1373
         std::unique_ptr<data_flow::Tasklet>(new data_flow::Tasklet(
720✔
1374
             this->new_element_id(), fill_debug_info(debug_info_elements), vertex, block.dataflow(), code, output, inputs
360✔
1375
         ))}
1376
    );
1377

1378
    return dynamic_cast<data_flow::Tasklet&>(*(res.first->second));
360✔
UNCOV
1379
};
×
1380

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

1408
    auto& memlet = dynamic_cast<data_flow::Memlet&>(*(res.first->second));
652✔
1409
#ifndef NDEBUG
1410
    memlet.validate(*this->structured_sdfg_);
652✔
1411
#endif
1412

1413
    return memlet;
652✔
1414
};
×
1415

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

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

1440
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
131✔
1441
    structured_control_flow::Block& block,
1442
    data_flow::AccessNode& src,
1443
    data_flow::Tasklet& dst,
1444
    const std::string& dst_conn,
1445
    const data_flow::Subset& subset,
1446
    const DebugInfos& debug_info_elements
1447
) {
1448
    const types::IType* src_type = nullptr;
131✔
1449
    if (auto cnode = dynamic_cast<data_flow::ConstantNode*>(&src)) {
131✔
1450
        src_type = &cnode->type();
40✔
1451
    } else {
40✔
1452
        src_type = &this->structured_sdfg_->type(src.data());
91✔
1453
    }
1454
    auto& base_type = types::infer_type(*this->structured_sdfg_, *src_type, subset);
131✔
1455
    if (base_type.type_id() != types::TypeID::Scalar) {
131✔
1456
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
1457
    }
1458
    return this->add_memlet(block, src, "void", dst, dst_conn, subset, *src_type, debug_info_elements);
131✔
1459
};
×
1460

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

1477
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
16✔
1478
    structured_control_flow::Block& block,
1479
    data_flow::AccessNode& src,
1480
    data_flow::LibraryNode& dst,
1481
    const std::string& dst_conn,
1482
    const data_flow::Subset& subset,
1483
    const types::IType& base_type,
1484
    const DebugInfos& debug_info_elements
1485
) {
1486
    return this->add_memlet(block, src, "void", dst, dst_conn, subset, base_type, debug_info_elements);
16✔
1487
};
×
1488

1489
data_flow::Memlet& StructuredSDFGBuilder::add_computational_memlet(
9✔
1490
    structured_control_flow::Block& block,
1491
    data_flow::LibraryNode& src,
1492
    const std::string& src_conn,
1493
    data_flow::AccessNode& dst,
1494
    const data_flow::Subset& subset,
1495
    const types::IType& base_type,
1496
    const DebugInfos& debug_info_elements
1497
) {
1498
    return this->add_memlet(block, src, src_conn, dst, "void", subset, base_type, debug_info_elements);
9✔
1499
};
×
1500

1501
data_flow::Memlet& StructuredSDFGBuilder::add_reference_memlet(
8✔
1502
    structured_control_flow::Block& block,
1503
    data_flow::AccessNode& src,
1504
    data_flow::AccessNode& dst,
1505
    const data_flow::Subset& subset,
1506
    const types::IType& base_type,
1507
    const DebugInfos& debug_info_elements
1508
) {
1509
    return this->add_memlet(block, src, "void", dst, "ref", subset, base_type, debug_info_elements);
8✔
1510
};
×
1511

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

1527
void StructuredSDFGBuilder::remove_memlet(structured_control_flow::Block& block, const data_flow::Memlet& edge) {
21✔
1528
    auto& graph = block.dataflow();
21✔
1529
    auto e = edge.edge();
21✔
1530
    boost::remove_edge(e, graph.graph_);
21✔
1531
    graph.edges_.erase(e);
21✔
1532
};
21✔
1533

1534
void StructuredSDFGBuilder::remove_node(structured_control_flow::Block& block, const data_flow::DataFlowNode& node) {
20✔
1535
    auto& graph = block.dataflow();
20✔
1536
    auto v = node.vertex();
20✔
1537
    boost::remove_vertex(v, graph.graph_);
20✔
1538
    graph.nodes_.erase(v);
20✔
1539
};
20✔
1540

1541
void StructuredSDFGBuilder::clear_node(structured_control_flow::Block& block, const data_flow::CodeNode& node) {
9✔
1542
    auto& graph = block.dataflow();
9✔
1543

1544
    std::unordered_set<const data_flow::DataFlowNode*> to_delete = {&node};
9✔
1545

1546
    // Delete incoming
1547
    std::list<const data_flow::Memlet*> iedges;
9✔
1548
    for (auto& iedge : graph.in_edges(node)) {
24✔
1549
        iedges.push_back(&iedge);
15✔
1550
    }
1551
    for (auto iedge : iedges) {
24✔
1552
        auto& src = iedge->src();
15✔
1553
        to_delete.insert(&src);
15✔
1554

1555
        auto edge = iedge->edge();
15✔
1556
        graph.edges_.erase(edge);
15✔
1557
        boost::remove_edge(edge, graph.graph_);
15✔
1558
    }
1559

1560
    // Delete outgoing
1561
    std::list<const data_flow::Memlet*> oedges;
9✔
1562
    for (auto& oedge : graph.out_edges(node)) {
18✔
1563
        oedges.push_back(&oedge);
9✔
1564
    }
1565
    for (auto oedge : oedges) {
18✔
1566
        auto& dst = oedge->dst();
9✔
1567
        to_delete.insert(&dst);
9✔
1568

1569
        auto edge = oedge->edge();
9✔
1570
        graph.edges_.erase(edge);
9✔
1571
        boost::remove_edge(edge, graph.graph_);
9✔
1572
    }
1573

1574
    // Delete nodes
1575
    for (auto obsolete_node : to_delete) {
42✔
1576
        if (graph.in_degree(*obsolete_node) == 0 && graph.out_degree(*obsolete_node) == 0) {
33✔
1577
            auto vertex = obsolete_node->vertex();
33✔
1578
            graph.nodes_.erase(vertex);
33✔
1579
            boost::remove_vertex(vertex, graph.graph_);
33✔
1580
        }
33✔
1581
    }
1582
};
9✔
1583

UNCOV
1584
void StructuredSDFGBuilder::clear_node(structured_control_flow::Block& block, const data_flow::AccessNode& node) {
×
UNCOV
1585
    auto& graph = block.dataflow();
×
UNCOV
1586
    if (graph.out_degree(node) != 0) {
×
1587
        throw InvalidSDFGException("StructuredSDFGBuilder: Access node has outgoing edges");
×
1588
    }
1589

UNCOV
1590
    std::list<const data_flow::Memlet*> tmp;
×
UNCOV
1591
    std::list<const data_flow::DataFlowNode*> queue = {&node};
×
UNCOV
1592
    while (!queue.empty()) {
×
UNCOV
1593
        auto current = queue.front();
×
UNCOV
1594
        queue.pop_front();
×
UNCOV
1595
        if (current != &node) {
×
UNCOV
1596
            if (dynamic_cast<const data_flow::AccessNode*>(current)) {
×
1597
                if (graph.in_degree(*current) > 0 || graph.out_degree(*current) > 0) {
×
1598
                    continue;
×
1599
                }
1600
            }
×
UNCOV
1601
        }
×
1602

UNCOV
1603
        tmp.clear();
×
UNCOV
1604
        for (auto& iedge : graph.in_edges(*current)) {
×
UNCOV
1605
            tmp.push_back(&iedge);
×
1606
        }
UNCOV
1607
        for (auto iedge : tmp) {
×
UNCOV
1608
            auto& src = iedge->src();
×
UNCOV
1609
            queue.push_back(&src);
×
1610

UNCOV
1611
            auto edge = iedge->edge();
×
UNCOV
1612
            graph.edges_.erase(edge);
×
UNCOV
1613
            boost::remove_edge(edge, graph.graph_);
×
1614
        }
1615

UNCOV
1616
        auto vertex = current->vertex();
×
UNCOV
1617
        graph.nodes_.erase(vertex);
×
UNCOV
1618
        boost::remove_vertex(vertex, graph.graph_);
×
1619
    }
UNCOV
1620
};
×
1621

1622
void StructuredSDFGBuilder::add_dataflow(const data_flow::DataFlowGraph& from, Block& to) {
20✔
1623
    auto& to_dataflow = to.dataflow();
20✔
1624

1625
    std::unordered_map<graph::Vertex, graph::Vertex> node_mapping;
20✔
1626
    for (auto& entry : from.nodes_) {
21✔
1627
        auto vertex = boost::add_vertex(to_dataflow.graph_);
1✔
1628
        to_dataflow.nodes_.insert({vertex, entry.second->clone(this->new_element_id(), vertex, to_dataflow)});
1✔
1629
        node_mapping.insert({entry.first, vertex});
1✔
1630
    }
1631

1632
    for (auto& entry : from.edges_) {
20✔
1633
        auto src = node_mapping[entry.second->src().vertex()];
×
1634
        auto dst = node_mapping[entry.second->dst().vertex()];
×
1635

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

1638
        to_dataflow.edges_.insert(
×
1639
            {edge.first,
×
1640
             entry.second->clone(
×
1641
                 this->new_element_id(), edge.first, to_dataflow, *to_dataflow.nodes_[src], *to_dataflow.nodes_[dst]
×
1642
             )}
1643
        );
1644
    }
1645
};
20✔
1646

1647
size_t StructuredSDFGBuilder::add_debug_info_element(const DebugInfo& element) {
3✔
1648
    return structured_sdfg_->debug_info().add_element(element);
3✔
1649
}
×
1650

1651
const DebugTable& StructuredSDFGBuilder::debug_info() const { return structured_sdfg_->debug_info(); }
105✔
1652

1653
} // namespace builder
1654
} // 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