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

daisytuner / sdfglib / 19224974600

10 Nov 2025 08:11AM UTC coverage: 61.223% (+0.02%) from 61.206%
19224974600

Pull #331

github

web-flow
Merge 66fefbaff into d01b8b39b
Pull Request #331: allow interpretation of pointers as ints in symbolic expressions

54 of 95 new or added lines in 19 files covered. (56.84%)

3 existing lines in 3 files now uncovered.

10321 of 16858 relevant lines covered (61.22%)

107.0 hits per line

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

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

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

5
namespace sdfg {
6
namespace builder {
7

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

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

13
      };
×
14

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

18
      };
1,173✔
19

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

23
      };
×
24

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

27
std::unique_ptr<SDFG> SDFGBuilder::move() { return std::move(this->sdfg_); };
13✔
28

29
void SDFGBuilder::rename_container(const std::string& old_name, const std::string& new_name) const {
×
30
    FunctionBuilder::rename_container(old_name, new_name);
×
31

32
    for (auto& entry : this->sdfg_->states_) {
×
33
        entry.second->replace(symbolic::symbol(old_name), symbolic::symbol(new_name));
×
34
    }
35
    for (auto& entry : this->sdfg_->edges_) {
×
36
        entry.second->replace(symbolic::symbol(old_name), symbolic::symbol(new_name));
×
37
    }
38
}
×
39

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

42
control_flow::State& SDFGBuilder::add_state(bool is_start_state, const DebugInfo& debug_info) {
70✔
43
    auto vertex = boost::add_vertex(this->sdfg_->graph_);
70✔
44
    auto res = this->sdfg_->states_.insert(
140✔
45
        {vertex,
70✔
46
         std::unique_ptr<control_flow::State>(new control_flow::State(this->new_element_id(), debug_info, vertex))}
70✔
47
    );
48

49
    assert(res.second);
70✔
50
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
70✔
51

52
    if (is_start_state) {
70✔
53
        this->sdfg_->start_state_ = (*res.first).second.get();
12✔
54
    }
12✔
55

56
    return *(*res.first).second;
70✔
57
};
×
58

59
control_flow::State& SDFGBuilder::
60
    add_state_before(const control_flow::State& state, bool is_start_state, const DebugInfo& debug_info) {
1✔
61
    auto& new_state = this->add_state(false, debug_info);
1✔
62

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

66
    // Redirect control-flow
67
    for (auto edge : to_redirect) {
2✔
68
        this->add_edge(edge->src(), new_state, edge->condition());
1✔
69

70
        auto desc = edge->edge();
1✔
71
        this->sdfg_->edges_.erase(desc);
1✔
72
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
73
    }
74
    this->add_edge(new_state, state);
1✔
75

76
    if (is_start_state) {
1✔
77
        this->sdfg_->start_state_ = &new_state;
×
78
    }
×
79

80
    return new_state;
1✔
81
};
1✔
82

83
control_flow::State& SDFGBuilder::
84
    add_state_after(const control_flow::State& state, bool connect_states, const DebugInfo& debug_info) {
4✔
85
    auto& new_state = this->add_state(false, debug_info);
4✔
86

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

90
    // Redirect control-flow
91
    for (auto& edge : to_redirect) {
5✔
92
        this->add_edge(new_state, edge->dst(), edge->condition());
1✔
93

94
        auto desc = edge->edge();
1✔
95
        this->sdfg_->edges_.erase(desc);
1✔
96
        boost::remove_edge(desc, this->sdfg_->graph_);
1✔
97
    }
98
    if (connect_states) {
4✔
99
        this->add_edge(state, new_state);
3✔
100
    }
3✔
101

102
    return new_state;
4✔
103
};
4✔
104

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

113
    assert(res.second);
4✔
114
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
4✔
115

116
    return static_cast<control_flow::ReturnState&>(*(*res.first).second);
4✔
117
};
×
118

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

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

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

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

136
    return new_state;
3✔
137
};
3✔
138

139
control_flow::ReturnState& SDFGBuilder::
140
    add_constant_return_state(const std::string& data, const types::IType& type, const DebugInfo& debug_info) {
×
141
    auto vertex = boost::add_vertex(this->sdfg_->graph_);
×
142
    auto res = this->sdfg_->states_.insert(
×
143
        {vertex,
×
144
         std::unique_ptr<
×
145
             control_flow::State>(new control_flow::ReturnState(this->new_element_id(), debug_info, vertex, data, type))
×
146
        }
147
    );
148

149
    assert(res.second);
×
150
    (*res.first).second->dataflow_->parent_ = (*res.first).second.get();
×
151

152
    return static_cast<control_flow::ReturnState&>(*(*res.first).second);
×
153
};
×
154

155
control_flow::ReturnState& SDFGBuilder::add_constant_return_state_after(
×
156
    const control_flow::State& state, const std::string& data, const types::IType& type, const DebugInfo& debug_info
157
) {
158
    auto& new_state = this->add_constant_return_state(data, type, debug_info);
×
159

160
    std::vector<const control_flow::InterstateEdge*> to_redirect;
×
161
    for (auto& e : this->sdfg_->out_edges(state)) to_redirect.push_back(&e);
×
162

163
    // Redirect control-flow
164
    for (auto& edge : to_redirect) {
×
165
        this->add_edge(new_state, edge->dst(), edge->condition());
×
166

167
        auto desc = edge->edge();
×
168
        this->sdfg_->edges_.erase(desc);
×
169
        boost::remove_edge(desc, this->sdfg_->graph_);
×
170
    }
171
    this->add_edge(state, new_state);
×
172

173
    return new_state;
×
174
};
×
175

176
control_flow::InterstateEdge& SDFGBuilder::
177
    add_edge(const control_flow::State& src, const control_flow::State& dst, const DebugInfo& debug_info) {
41✔
178
    return this->add_edge(src, dst, control_flow::Assignments{}, SymEngine::boolTrue, debug_info);
41✔
179
};
×
180

181
control_flow::InterstateEdge& SDFGBuilder::add_edge(
8✔
182
    const control_flow::State& src,
183
    const control_flow::State& dst,
184
    const symbolic::Condition condition,
185
    const DebugInfo& debug_info
186
) {
187
    return this->add_edge(src, dst, control_flow::Assignments{}, condition, debug_info);
8✔
188
};
×
189

190
control_flow::InterstateEdge& SDFGBuilder::add_edge(
2✔
191
    const control_flow::State& src,
192
    const control_flow::State& dst,
193
    const control_flow::Assignments& assignments,
194
    const DebugInfo& debug_info
195
) {
196
    return this->add_edge(src, dst, assignments, SymEngine::boolTrue, debug_info);
2✔
197
};
×
198

199
control_flow::InterstateEdge& SDFGBuilder::add_edge(
53✔
200
    const control_flow::State& src,
201
    const control_flow::State& dst,
202
    const control_flow::Assignments& assignments,
203
    const symbolic::Condition condition,
204
    const DebugInfo& debug_info
205
) {
206
    if (dynamic_cast<const control_flow::ReturnState*>(&src) != nullptr) {
53✔
207
        throw InvalidSDFGException("Cannot add edge from ReturnState");
×
208
    }
209

210
    for (auto& entry : assignments) {
57✔
211
        auto& lhs = entry.first;
4✔
212
        auto& type = this->function().type(lhs->get_name());
4✔
213
        if (type.type_id() != types::TypeID::Scalar) {
4✔
NEW
214
            throw InvalidSDFGException("Assignment - LHS: must be scalar type");
×
215
        }
216
        if (!types::is_integer(type.primitive_type())) {
4✔
217
            throw InvalidSDFGException("Assignment - LHS: must be integer type");
×
218
        }
219

220
        auto& rhs = entry.second;
4✔
221
        for (auto& atom : symbolic::atoms(rhs)) {
5✔
222
            if (symbolic::is_nullptr(atom)) {
1✔
223
                continue;
×
224
            }
225
            auto& atom_type = this->function().type(atom->get_name());
1✔
226

227
            // Scalar integers
228
            if (atom_type.type_id() == types::TypeID::Scalar) {
1✔
229
                if (!types::is_integer(atom_type.primitive_type())) {
1✔
230
                    throw InvalidSDFGException("Assignment - RHS: must evaluate to integer type");
×
231
                }
232
                continue;
1✔
NEW
233
            } else if (atom_type.type_id() == types::TypeID::Pointer) {
×
UNCOV
234
                continue;
×
235
            } else {
NEW
236
                throw InvalidSDFGException("Assignment - RHS: must evaluate to integer or pointer type");
×
237
            }
238
        }
239
    }
240

241
    for (auto& atom : symbolic::atoms(condition)) {
61✔
242
        if (symbolic::is_nullptr(atom)) {
8✔
243
            continue;
×
244
        }
245
        auto& atom_type = this->function().type(atom->get_name());
8✔
246
        if (atom_type.type_id() != types::TypeID::Scalar && atom_type.type_id() != types::TypeID::Pointer) {
8✔
247
            throw InvalidSDFGException("Condition: must be integer type or pointer type");
×
248
        }
249
    }
250

251
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, this->sdfg_->graph_);
53✔
252
    assert(edge.second);
53✔
253

254
    auto res = this->sdfg_->edges_.insert(
106✔
255
        {edge.first,
106✔
256
         std::unique_ptr<control_flow::InterstateEdge>(new control_flow::InterstateEdge(
106✔
257
             this->new_element_id(), debug_info, edge.first, src, dst, condition, assignments
53✔
258
         ))}
259
    );
260

261
    assert(res.second);
53✔
262

263
    return *(*res.first).second;
53✔
264
};
×
265

266
void SDFGBuilder::remove_edge(const control_flow::InterstateEdge& edge) {
×
267
    auto desc = edge.edge();
×
268
    this->sdfg_->edges_.erase(desc);
×
269

270
    boost::remove_edge(desc, this->sdfg_->graph_);
×
271
};
×
272

273
std::tuple<control_flow::State&, control_flow::State&, control_flow::State&> SDFGBuilder::add_loop(
1✔
274
    const control_flow::State& state,
275
    sdfg::symbolic::Symbol iterator,
276
    sdfg::symbolic::Expression init,
277
    sdfg::symbolic::Condition cond,
278
    sdfg::symbolic::Expression update,
279
    const DebugInfo& debug_info
280
) {
281
    // Init: iterator = init
282
    auto& init_state = this->add_state_after(state, true, debug_info);
1✔
283
    const graph::Edge init_edge_desc = (*this->sdfg_->in_edges(init_state).begin()).edge_;
1✔
284
    auto& init_edge = this->sdfg_->edges_[init_edge_desc];
1✔
285
    init_edge->assignments_.insert({iterator, init});
1✔
286

287
    // Final state
288
    auto& final_state = this->add_state_after(init_state, false, debug_info);
1✔
289

290
    // Init -> early_exit -> final
291
    auto& early_exit_state = this->add_state(false, debug_info);
1✔
292
    this->add_edge(init_state, early_exit_state, symbolic::Not(cond));
1✔
293
    this->add_edge(early_exit_state, final_state);
1✔
294

295
    // Init -> header -> body
296
    auto& header_state = this->add_state(false, debug_info);
1✔
297
    this->add_edge(init_state, header_state, cond);
1✔
298

299
    auto& body_state = this->add_state(false, debug_info);
1✔
300
    this->add_edge(header_state, body_state);
1✔
301

302
    auto& update_state = this->add_state(false, debug_info);
1✔
303
    this->add_edge(body_state, update_state, {{iterator, update}});
1✔
304

305
    // Back edge and exit edge
306
    this->add_edge(update_state, header_state, cond);
1✔
307
    this->add_edge(update_state, final_state, symbolic::Not(cond));
1✔
308

309
    return {init_state, body_state, final_state};
1✔
310
};
×
311

312
/***** Section: Dataflow Graph *****/
313

314
data_flow::AccessNode& SDFGBuilder::
315
    add_access(control_flow::State& state, const std::string& data, const DebugInfo& debug_info) {
26✔
316
    auto& dataflow = state.dataflow();
26✔
317
    auto vertex = boost::add_vertex(dataflow.graph_);
26✔
318
    auto res = dataflow.nodes_.insert(
52✔
319
        {vertex,
26✔
320
         std::unique_ptr<
26✔
321
             data_flow::AccessNode>(new data_flow::AccessNode(this->new_element_id(), debug_info, vertex, dataflow, data)
26✔
322
         )}
323
    );
324

325
    return static_cast<data_flow::AccessNode&>(*(res.first->second));
26✔
326
};
×
327

328
data_flow::ConstantNode& SDFGBuilder::add_constant(
1✔
329
    control_flow::State& state, const std::string& data, const types::IType& type, const DebugInfo& debug_info
330
) {
331
    auto& dataflow = state.dataflow();
1✔
332
    auto vertex = boost::add_vertex(dataflow.graph_);
1✔
333
    auto res = dataflow.nodes_.insert(
2✔
334
        {vertex,
1✔
335
         std::unique_ptr<data_flow::ConstantNode>(
1✔
336
             new data_flow::ConstantNode(this->new_element_id(), debug_info, vertex, dataflow, data, type)
1✔
337
         )}
338
    );
339

340
    return static_cast<data_flow::ConstantNode&>(*(res.first->second));
1✔
341
};
×
342

343
data_flow::Tasklet& SDFGBuilder::add_tasklet(
13✔
344
    control_flow::State& state,
345
    const data_flow::TaskletCode code,
346
    const std::string& output,
347
    const std::vector<std::string>& inputs,
348
    const DebugInfo& debug_info
349
) {
350
    auto& dataflow = state.dataflow();
13✔
351
    auto vertex = boost::add_vertex(dataflow.graph_);
13✔
352
    auto res = dataflow.nodes_.insert(
26✔
353
        {vertex,
13✔
354
         std::unique_ptr<data_flow::Tasklet>(
13✔
355
             new data_flow::Tasklet(this->new_element_id(), debug_info, vertex, dataflow, code, output, inputs)
13✔
356
         )}
357
    );
358

359
    return static_cast<data_flow::Tasklet&>(*(res.first->second));
13✔
360
};
×
361

362
data_flow::Memlet& SDFGBuilder::add_memlet(
26✔
363
    control_flow::State& state,
364
    data_flow::DataFlowNode& src,
365
    const std::string& src_conn,
366
    data_flow::DataFlowNode& dst,
367
    const std::string& dst_conn,
368
    const data_flow::Subset& subset,
369
    const types::IType& base_type,
370
    const DebugInfo& debug_info
371
) {
372
    auto& dataflow = state.dataflow();
26✔
373
    auto edge = boost::add_edge(src.vertex_, dst.vertex_, dataflow.graph_);
26✔
374
    auto res = dataflow.edges_.insert(
52✔
375
        {edge.first,
52✔
376
         std::unique_ptr<data_flow::Memlet>(new data_flow::Memlet(
26✔
377
             this->new_element_id(), debug_info, edge.first, dataflow, src, src_conn, dst, dst_conn, subset, base_type
26✔
378
         ))}
379
    );
380

381
    auto& memlet = static_cast<data_flow::Memlet&>(*(res.first->second));
26✔
382

383
    return memlet;
26✔
384
};
×
385

386
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
387
    control_flow::State& state,
388
    data_flow::AccessNode& src,
389
    data_flow::Tasklet& dst,
390
    const std::string& dst_conn,
391
    const data_flow::Subset& subset,
392
    const types::IType& base_type,
393
    const DebugInfo& debug_info
394
) {
395
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, base_type, debug_info);
×
396
};
×
397

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

410
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
13✔
411
    control_flow::State& state,
412
    data_flow::AccessNode& src,
413
    data_flow::Tasklet& dst,
414
    const std::string& dst_conn,
415
    const data_flow::Subset& subset,
416
    const DebugInfo& debug_info
417
) {
418
    const types::IType* src_type = nullptr;
13✔
419
    if (auto cnode = dynamic_cast<data_flow::ConstantNode*>(&src)) {
13✔
420
        src_type = &cnode->type();
×
421
    } else {
×
422
        src_type = &this->sdfg_->type(src.data());
13✔
423
    }
424
    auto& base_type = types::infer_type(*this->sdfg_, *src_type, subset);
13✔
425
    if (base_type.type_id() != types::TypeID::Scalar) {
13✔
426
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
427
    }
428
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, *src_type, debug_info);
13✔
429
};
×
430

431
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
13✔
432
    control_flow::State& state,
433
    data_flow::Tasklet& src,
434
    const std::string& src_conn,
435
    data_flow::AccessNode& dst,
436
    const data_flow::Subset& subset,
437
    const DebugInfo& debug_info
438
) {
439
    auto& dst_type = this->function().type(dst.data());
13✔
440
    auto& base_type = types::infer_type(this->function(), dst_type, subset);
13✔
441
    if (base_type.type_id() != types::TypeID::Scalar) {
13✔
442
        throw InvalidSDFGException("Computational memlet must have a scalar type");
×
443
    }
444
    return this->add_memlet(state, src, src_conn, dst, "void", subset, dst_type, debug_info);
13✔
445
};
×
446

447
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
448
    control_flow::State& state,
449
    data_flow::AccessNode& src,
450
    data_flow::LibraryNode& dst,
451
    const std::string& dst_conn,
452
    const data_flow::Subset& subset,
453
    const types::IType& base_type,
454
    const DebugInfo& debug_info
455
) {
456
    return this->add_memlet(state, src, "void", dst, dst_conn, subset, base_type, debug_info);
×
457
};
×
458

459
data_flow::Memlet& SDFGBuilder::add_computational_memlet(
×
460
    control_flow::State& state,
461
    data_flow::LibraryNode& src,
462
    const std::string& src_conn,
463
    data_flow::AccessNode& dst,
464
    const data_flow::Subset& subset,
465
    const types::IType& base_type,
466
    const DebugInfo& debug_info
467
) {
468
    return this->add_memlet(state, src, src_conn, dst, "void", subset, base_type, debug_info);
×
469
};
×
470

471
data_flow::Memlet& SDFGBuilder::add_reference_memlet(
×
472
    control_flow::State& state,
473
    data_flow::AccessNode& src,
474
    data_flow::AccessNode& dst,
475
    const data_flow::Subset& subset,
476
    const types::IType& base_type,
477
    const DebugInfo& debug_info
478
) {
479
    return this->add_memlet(state, src, "void", dst, "ref", subset, base_type, debug_info);
×
480
};
×
481

482
data_flow::Memlet& SDFGBuilder::add_dereference_memlet(
×
483
    control_flow::State& state,
484
    data_flow::AccessNode& src,
485
    data_flow::AccessNode& dst,
486
    bool derefs_src,
487
    const types::IType& base_type,
488
    const DebugInfo& debug_info
489
) {
490
    if (derefs_src) {
×
491
        return this->add_memlet(state, src, "void", dst, "deref", {symbolic::zero()}, base_type, debug_info);
×
492
    } else {
493
        return this->add_memlet(state, src, "deref", dst, "void", {symbolic::zero()}, base_type, debug_info);
×
494
    }
495
};
×
496

497
} // namespace builder
498
} // 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

© 2025 Coveralls, Inc