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

daisytuner / sdfglib / 16069945621

04 Jul 2025 08:56AM UTC coverage: 64.375% (-0.2%) from 64.606%
16069945621

push

github

web-flow
Merge pull request #137 from daisytuner/clang-format

runs clang-format on codebase

609 of 827 new or added lines in 63 files covered. (73.64%)

46 existing lines in 30 files now uncovered.

8578 of 13325 relevant lines covered (64.38%)

177.24 hits per line

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

87.18
/src/visualizer/visualizer.cpp
1
#include "sdfg/visualizer/visualizer.h"
2

3
#include <cassert>
4
#include <sstream>
5
#include <stdexcept>
6
#include <string>
7
#include <utility>
8
#include <vector>
9

10
#include "sdfg/data_flow/tasklet.h"
11
#include "sdfg/helpers/helpers.h"
12
#include "sdfg/structured_control_flow/block.h"
13
#include "sdfg/structured_control_flow/control_flow_node.h"
14
#include "sdfg/structured_control_flow/for.h"
15
#include "sdfg/structured_control_flow/if_else.h"
16
#include "sdfg/structured_control_flow/return.h"
17
#include "sdfg/structured_control_flow/sequence.h"
18
#include "sdfg/structured_control_flow/while.h"
19
#include "sdfg/symbolic/symbolic.h"
20
#include "sdfg/types/type.h"
21
#include "symengine/basic.h"
22

23
namespace sdfg {
24
namespace visualizer {
25

26
constexpr const char* code_to_string(data_flow::TaskletCode c) {
181✔
27
    switch (c) {
181✔
28
        case data_flow::TaskletCode::assign:
29
            return "=";
10✔
30
        case data_flow::TaskletCode::neg:
31
            return "-";
1✔
32
        case data_flow::TaskletCode::add:
33
            return "+";
4✔
34
        case data_flow::TaskletCode::sub:
35
            return "-";
1✔
36
        case data_flow::TaskletCode::mul:
37
            return "*";
4✔
38
        case data_flow::TaskletCode::div:
39
            return "/";
1✔
40
        case data_flow::TaskletCode::fma:
41
            return "fma";
3✔
42
        case data_flow::TaskletCode::mod:
43
            return "%";
1✔
44
        case data_flow::TaskletCode::max:
45
            return "max";
1✔
46
        case data_flow::TaskletCode::min:
47
            return "min";
1✔
48
        case data_flow::TaskletCode::minnum:
49
            return "minnum";
1✔
50
        case data_flow::TaskletCode::maxnum:
51
            return "maxnum";
1✔
52
        case data_flow::TaskletCode::minimum:
53
            return "minimum";
1✔
54
        case data_flow::TaskletCode::maximum:
55
            return "maximum";
1✔
56
        case data_flow::TaskletCode::trunc:
57
            return "trunc";
1✔
58
        case data_flow::TaskletCode::logical_and:
59
            return "&&";
1✔
60
        case data_flow::TaskletCode::logical_or:
61
            return "||";
1✔
62
        case data_flow::TaskletCode::bitwise_and:
63
            return "&";
1✔
64
        case data_flow::TaskletCode::bitwise_or:
65
            return "|";
1✔
66
        case data_flow::TaskletCode::bitwise_xor:
67
            return "^";
1✔
68
        case data_flow::TaskletCode::bitwise_not:
69
            return "~";
1✔
70
        case data_flow::TaskletCode::shift_left:
71
            return "<<";
1✔
72
        case data_flow::TaskletCode::shift_right:
73
            return ">>";
1✔
74
        case data_flow::TaskletCode::olt:
75
            return "<";
1✔
76
        case data_flow::TaskletCode::ole:
77
            return "<=";
1✔
78
        case data_flow::TaskletCode::oeq:
79
            return "==";
1✔
80
        case data_flow::TaskletCode::one:
81
            return "!=";
1✔
82
        case data_flow::TaskletCode::oge:
83
            return ">=";
1✔
84
        case data_flow::TaskletCode::ogt:
85
            return ">";
1✔
86
        case data_flow::TaskletCode::ord:
87
            return "==";
1✔
88
        case data_flow::TaskletCode::ult:
89
            return "<";
1✔
90
        case data_flow::TaskletCode::ule:
91
            return "<=";
1✔
92
        case data_flow::TaskletCode::ueq:
93
            return "==";
1✔
94
        case data_flow::TaskletCode::une:
95
            return "!=";
1✔
96
        case data_flow::TaskletCode::uge:
97
            return ">=";
1✔
98
        case data_flow::TaskletCode::ugt:
99
            return ">";
1✔
100
        case data_flow::TaskletCode::uno:
101
            return "!=";
1✔
102
        case data_flow::TaskletCode::abs:
103
            return "abs";
1✔
104
        case data_flow::TaskletCode::acos:
105
            return "acos";
1✔
106
        case data_flow::TaskletCode::acosf:
107
            return "acosf";
1✔
108
        case data_flow::TaskletCode::acosl:
109
            return "acosl";
1✔
110
        case data_flow::TaskletCode::acosh:
111
            return "acosh";
1✔
112
        case data_flow::TaskletCode::acoshf:
113
            return "acoshf";
1✔
114
        case data_flow::TaskletCode::acoshl:
115
            return "acoshl";
1✔
116
        case data_flow::TaskletCode::asin:
117
            return "asin";
1✔
118
        case data_flow::TaskletCode::asinf:
119
            return "asinf";
1✔
120
        case data_flow::TaskletCode::asinl:
121
            return "asinl";
1✔
122
        case data_flow::TaskletCode::asinh:
123
            return "asinh";
1✔
124
        case data_flow::TaskletCode::asinhf:
125
            return "asinhf";
1✔
126
        case data_flow::TaskletCode::asinhl:
127
            return "asinhl";
1✔
128
        case data_flow::TaskletCode::atan:
129
            return "atan";
1✔
130
        case data_flow::TaskletCode::atanf:
131
            return "atanf";
1✔
132
        case data_flow::TaskletCode::atanl:
133
            return "atanl";
1✔
134
        case data_flow::TaskletCode::atan2:
135
            return "atan2";
1✔
136
        case data_flow::TaskletCode::atan2f:
137
            return "atan2f";
1✔
138
        case data_flow::TaskletCode::atan2l:
139
            return "atan2l";
1✔
140
        case data_flow::TaskletCode::atanh:
141
            return "atanh";
1✔
142
        case data_flow::TaskletCode::atanhf:
143
            return "atanhf";
1✔
144
        case data_flow::TaskletCode::atanhl:
145
            return "atanhl";
1✔
146
        case data_flow::TaskletCode::cabs:
147
            return "cabs";
1✔
148
        case data_flow::TaskletCode::cabsf:
149
            return "cabsf";
1✔
150
        case data_flow::TaskletCode::cabsl:
151
            return "cabsl";
1✔
152
        case data_flow::TaskletCode::ceil:
153
            return "ceil";
1✔
154
        case data_flow::TaskletCode::ceilf:
155
            return "ceilf";
1✔
156
        case data_flow::TaskletCode::ceill:
157
            return "ceill";
1✔
158
        case data_flow::TaskletCode::copysign:
159
            return "copysign";
1✔
160
        case data_flow::TaskletCode::copysignf:
161
            return "copysignf";
1✔
162
        case data_flow::TaskletCode::copysignl:
163
            return "copysignl";
1✔
164
        case data_flow::TaskletCode::cos:
165
            return "cos";
1✔
166
        case data_flow::TaskletCode::cosf:
167
            return "cosf";
1✔
168
        case data_flow::TaskletCode::cosl:
169
            return "cosl";
1✔
170
        case data_flow::TaskletCode::cosh:
171
            return "cosh";
1✔
172
        case data_flow::TaskletCode::coshf:
173
            return "coshf";
1✔
174
        case data_flow::TaskletCode::coshl:
175
            return "coshl";
1✔
176
        case data_flow::TaskletCode::cbrt:
177
            return "cbrt";
1✔
178
        case data_flow::TaskletCode::cbrtf:
179
            return "cbrtf";
1✔
180
        case data_flow::TaskletCode::cbrtl:
181
            return "cbrtl";
1✔
182
        case data_flow::TaskletCode::exp10:
183
            return "exp10";
1✔
184
        case data_flow::TaskletCode::exp10f:
185
            return "exp10f";
1✔
186
        case data_flow::TaskletCode::exp10l:
187
            return "exp10l";
1✔
188
        case data_flow::TaskletCode::exp2:
189
            return "exp2";
1✔
190
        case data_flow::TaskletCode::exp2f:
191
            return "exp2f";
1✔
192
        case data_flow::TaskletCode::exp2l:
193
            return "exp2l";
1✔
194
        case data_flow::TaskletCode::exp:
195
            return "exp";
1✔
196
        case data_flow::TaskletCode::expf:
197
            return "expf";
1✔
198
        case data_flow::TaskletCode::expl:
199
            return "expl";
1✔
200
        case data_flow::TaskletCode::expm1:
201
            return "expm1";
1✔
202
        case data_flow::TaskletCode::expm1f:
203
            return "expm1f";
1✔
204
        case data_flow::TaskletCode::expm1l:
205
            return "expm1l";
1✔
206
        case data_flow::TaskletCode::fabs:
207
            return "fabs";
1✔
208
        case data_flow::TaskletCode::fabsf:
209
            return "fabsf";
1✔
210
        case data_flow::TaskletCode::fabsl:
211
            return "fabsl";
1✔
212
        case data_flow::TaskletCode::floor:
213
            return "floor";
1✔
214
        case data_flow::TaskletCode::floorf:
215
            return "floorf";
1✔
216
        case data_flow::TaskletCode::floorl:
217
            return "floorl";
1✔
218
        case data_flow::TaskletCode::fls:
219
            return "fls";
1✔
220
        case data_flow::TaskletCode::flsl:
221
            return "flsl";
1✔
222
        case data_flow::TaskletCode::fmax:
223
            return "fmax";
1✔
224
        case data_flow::TaskletCode::fmaxf:
225
            return "fmaxf";
1✔
226
        case data_flow::TaskletCode::fmaxl:
227
            return "fmaxl";
1✔
228
        case data_flow::TaskletCode::fmin:
229
            return "fmin";
1✔
230
        case data_flow::TaskletCode::fminf:
231
            return "fminf";
1✔
232
        case data_flow::TaskletCode::fminl:
233
            return "fminl";
1✔
234
        case data_flow::TaskletCode::fmod:
235
            return "fmod";
1✔
236
        case data_flow::TaskletCode::fmodf:
237
            return "fmodf";
1✔
238
        case data_flow::TaskletCode::fmodl:
239
            return "fmodl";
1✔
240
        case data_flow::TaskletCode::frexp:
241
            return "frexp";
1✔
242
        case data_flow::TaskletCode::frexpf:
243
            return "frexpf";
1✔
244
        case data_flow::TaskletCode::frexpl:
245
            return "frexpl";
1✔
246
        case data_flow::TaskletCode::labs:
247
            return "labs";
1✔
248
        case data_flow::TaskletCode::ldexp:
249
            return "ldexp";
1✔
250
        case data_flow::TaskletCode::ldexpf:
251
            return "ldexpf";
1✔
252
        case data_flow::TaskletCode::ldexpl:
253
            return "ldexpl";
1✔
254
        case data_flow::TaskletCode::log10:
255
            return "log10";
1✔
256
        case data_flow::TaskletCode::log10f:
257
            return "log10f";
1✔
258
        case data_flow::TaskletCode::log10l:
259
            return "log10l";
1✔
260
        case data_flow::TaskletCode::log2:
261
            return "log2";
1✔
262
        case data_flow::TaskletCode::log2f:
263
            return "log2f";
1✔
264
        case data_flow::TaskletCode::log2l:
265
            return "log2l";
1✔
266
        case data_flow::TaskletCode::log:
267
            return "log";
1✔
268
        case data_flow::TaskletCode::logf:
269
            return "logf";
1✔
270
        case data_flow::TaskletCode::logl:
271
            return "logl";
1✔
272
        case data_flow::TaskletCode::logb:
273
            return "logb";
1✔
274
        case data_flow::TaskletCode::logbf:
275
            return "logbf";
1✔
276
        case data_flow::TaskletCode::logbl:
277
            return "logbl";
1✔
278
        case data_flow::TaskletCode::log1p:
279
            return "log1p";
1✔
280
        case data_flow::TaskletCode::log1pf:
281
            return "log1pf";
1✔
282
        case data_flow::TaskletCode::log1pl:
283
            return "log1pl";
1✔
284
        case data_flow::TaskletCode::modf:
285
            return "modf";
1✔
286
        case data_flow::TaskletCode::modff:
287
            return "modff";
1✔
288
        case data_flow::TaskletCode::modfl:
289
            return "modfl";
1✔
290
        case data_flow::TaskletCode::nearbyint:
291
            return "nearbyint";
1✔
292
        case data_flow::TaskletCode::nearbyintf:
293
            return "nearbyintf";
1✔
294
        case data_flow::TaskletCode::nearbyintl:
295
            return "nearbyintl";
1✔
296
        case data_flow::TaskletCode::pow:
297
            return "pow";
1✔
298
        case data_flow::TaskletCode::powf:
299
            return "powf";
1✔
300
        case data_flow::TaskletCode::powl:
301
            return "powl";
1✔
302
        case data_flow::TaskletCode::rint:
303
            return "rint";
1✔
304
        case data_flow::TaskletCode::rintf:
305
            return "rintf";
1✔
306
        case data_flow::TaskletCode::rintl:
307
            return "rintl";
1✔
308
        case data_flow::TaskletCode::round:
309
            return "round";
1✔
310
        case data_flow::TaskletCode::roundf:
311
            return "roundf";
1✔
312
        case data_flow::TaskletCode::roundl:
313
            return "roundl";
1✔
314
        case data_flow::TaskletCode::roundeven:
315
            return "roundeven";
1✔
316
        case data_flow::TaskletCode::roundevenf:
317
            return "roundevenf";
1✔
318
        case data_flow::TaskletCode::roundevenl:
319
            return "roundevenl";
1✔
320
        case data_flow::TaskletCode::sin:
321
            return "sin";
1✔
322
        case data_flow::TaskletCode::sinf:
323
            return "sinf";
1✔
324
        case data_flow::TaskletCode::sinl:
325
            return "sinl";
1✔
326
        case data_flow::TaskletCode::sinh:
327
            return "sinh";
1✔
328
        case data_flow::TaskletCode::sinhf:
329
            return "sinhf";
1✔
330
        case data_flow::TaskletCode::sinhl:
331
            return "sinhl";
1✔
332
        case data_flow::TaskletCode::sqrt:
333
            return "sqrt";
1✔
334
        case data_flow::TaskletCode::sqrtf:
335
            return "sqrtf";
1✔
336
        case data_flow::TaskletCode::sqrtl:
337
            return "sqrtl";
1✔
338
        case data_flow::TaskletCode::rsqrt:
339
            return "rsqrt";
1✔
340
        case data_flow::TaskletCode::rsqrtf:
341
            return "rsqrtf";
1✔
342
        case data_flow::TaskletCode::rsqrtl:
343
            return "rsqrtl";
1✔
344
        case data_flow::TaskletCode::tan:
345
            return "tan";
1✔
346
        case data_flow::TaskletCode::tanf:
347
            return "tanf";
1✔
348
        case data_flow::TaskletCode::tanl:
349
            return "tanl";
1✔
350
        case data_flow::TaskletCode::tanh:
351
            return "tanh";
1✔
352
        case data_flow::TaskletCode::tanhf:
353
            return "tanhf";
1✔
354
        case data_flow::TaskletCode::tanhl:
355
            return "tanhl";
1✔
356
    };
357
    throw InvalidSDFGException("code_to_string: Unsupported tasklet code");
×
358
};
181✔
359

360
std::string Visualizer::expression(const std::string expr) {
290✔
361
    if (this->replacements_.empty()) return expr;
290✔
362
    std::string res = expr;
×
363
    size_t pos1 = 0, pos2 = 0;
×
364
    for (std::pair<const std::string, const std::string> replace : this->replacements_) {
×
365
        pos2 = res.find(replace.first);
×
366
        if (pos2 == res.npos) continue;
×
367
        pos1 = 0;
×
368
        std::stringstream res_tmp;
×
369
        while (pos2 < res.npos) {
×
370
            res_tmp << res.substr(pos1, pos2 - pos1) << replace.second;
×
371
            pos1 = pos2 + replace.first.size();
×
372
            pos2 = res.find(replace.first, pos1);
×
373
        }
374
        if (pos1 < res.npos) res_tmp << res.substr(pos1);
×
375
        res = res_tmp.str();
×
376
    }
×
377
    return res;
×
378
}
290✔
379

380
void Visualizer::visualizeNode(const StructuredSDFG& sdfg, const structured_control_flow::ControlFlowNode& node) {
199✔
381
    if (auto block = dynamic_cast<const structured_control_flow::Block*>(&node)) {
199✔
382
        this->visualizeBlock(sdfg, *block);
181✔
383
        return;
181✔
384
    }
385
    if (auto sequence = dynamic_cast<const structured_control_flow::Sequence*>(&node)) {
18✔
386
        this->visualizeSequence(sdfg, *sequence);
×
387
        return;
×
388
    }
389
    if (auto if_else = dynamic_cast<const structured_control_flow::IfElse*>(&node)) {
18✔
390
        this->visualizeIfElse(sdfg, *if_else);
3✔
391
        return;
3✔
392
    }
393
    if (auto while_loop = dynamic_cast<const structured_control_flow::While*>(&node)) {
15✔
394
        this->visualizeWhile(sdfg, *while_loop);
2✔
395
        return;
2✔
396
    }
397
    if (auto loop = dynamic_cast<const structured_control_flow::For*>(&node)) {
13✔
398
        this->visualizeFor(sdfg, *loop);
10✔
399
        return;
10✔
400
    }
401
    if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&node)) {
3✔
402
        this->visualizeReturn(sdfg, *return_node);
1✔
403
        return;
1✔
404
    }
405
    if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&node)) {
2✔
406
        this->visualizeBreak(sdfg, *break_node);
1✔
407
        return;
1✔
408
    }
409
    if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&node)) {
1✔
410
        this->visualizeContinue(sdfg, *continue_node);
1✔
411
        return;
1✔
412
    }
413
    if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&node)) {
×
414
        this->visualizeMap(sdfg, *map_node);
×
415
        return;
×
416
    }
417
    throw std::runtime_error("Unsupported control flow node");
×
418
}
199✔
419

420
void Visualizer::visualizeTasklet(data_flow::Tasklet const& tasklet) {
181✔
421
    std::string op = code_to_string(tasklet.code());
181✔
422
    std::vector<std::string> arguments;
181✔
423
    for (size_t i = 0; i < tasklet.inputs().size(); ++i) {
406✔
424
        std::string arg = tasklet.input(i).first;
225✔
425
        if (!tasklet.needs_connector(i)) {
225✔
426
            if (arg != "NAN" && arg != "INFINITY") {
212✔
427
                if (tasklet.input(i).second.primitive_type() == types::PrimitiveType::Float) arg += "f";
212✔
428
            }
212✔
429
        }
212✔
430
        arguments.push_back(this->expression(arg));
225✔
431
    }
225✔
432

433
    if (tasklet.code() == data_flow::TaskletCode::assign) {
181✔
434
        this->stream_ << arguments.at(0);
10✔
435
    } else if (tasklet.code() == data_flow::TaskletCode::fma) {
181✔
436
        if (arguments.size() != 3) throw std::runtime_error("FMA requires 3 arguments");
3✔
437
        this->stream_ << arguments.at(0) << " * " << arguments.at(1) << " + " << arguments.at(2);
3✔
438
    } else if (data_flow::is_infix(tasklet.code())) {
171✔
439
        switch (data_flow::arity(tasklet.code())) {
32✔
440
            case 1:
441
                this->stream_ << op << " " << arguments.at(0);
×
442
                break;
×
443
            case 2:
444
                this->stream_ << arguments.at(0) << " " << op << " " << arguments.at(1);
32✔
445
                break;
32✔
446
            default:
447
                throw std::runtime_error("Unsupported arity");
×
448
        }
449
    } else {
32✔
450
        this->stream_ << op << "(" << helpers::join(arguments, ", ") << ")";
136✔
451
    }
452
}
181✔
453

454
void Visualizer::visualizeForBounds(
10✔
455
    symbolic::Symbol const& indvar,
456
    symbolic::Expression const& init,
457
    symbolic::Condition const& condition,
458
    symbolic::Expression const& update
459
) {
460
    this->stream_ << indvar->get_name() << " = " << this->expression(init->__str__()) << "; "
20✔
461
                  << this->expression(condition->__str__()) << "; " << indvar->get_name() << " = "
10✔
462
                  << this->expression(update->__str__());
10✔
463
}
10✔
464

465
/// @brief If known, use the type to better visualize structures. Then track the type as far as it goes.
466
void Visualizer::
467
    visualizeSubset(Function const& function, data_flow::Subset const& sub, types::IType const* type, int subIdx) {
228✔
468
    if (static_cast<int>(sub.size()) <= subIdx) {
228✔
469
        return;
199✔
470
    }
471
    if (auto structure_type = dynamic_cast<const types::Structure*>(type)) {
29✔
472
        types::StructureDefinition const& definition = function.structure(structure_type->name());
×
473
        this->stream_ << ".member_" << this->expression(sub.at(subIdx)->__str__());
×
474
        auto member = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(sub.at(0));
×
475
        types::IType const& member_type = definition.member_type(member);
×
NEW
476
        this->visualizeSubset(function, sub, &member_type, subIdx + 1);
×
477
    } else if (auto array_type = dynamic_cast<const types::Array*>(type)) {
29✔
478
        this->stream_ << "[" << this->expression(sub.at(subIdx)->__str__()) << "]";
6✔
479
        data_flow::Subset element_subset(sub.begin() + 1, sub.end());
6✔
480
        types::IType const& element_type = array_type->element_type();
6✔
481
        this->visualizeSubset(function, sub, &element_type, subIdx + 1);
6✔
482
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(type)) {
29✔
483
        this->stream_ << "[" << this->expression(sub.at(subIdx)->__str__()) << "]";
23✔
484
        types::IType const& pointee_type = pointer_type->pointee_type();
23✔
485
        this->visualizeSubset(function, sub, &pointee_type, subIdx + 1);
23✔
486
    } else {
23✔
487
        if (type != nullptr) {
×
488
            this->stream_ << "(rogue)";
×
489
        }
×
490
        this->stream_ << "[" << this->expression(sub.at(subIdx)->__str__()) << "]";
×
NEW
491
        visualizeSubset(function, sub, nullptr, subIdx + 1);
×
492
    }
493
}
228✔
494

495
} // namespace visualizer
496
} // 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