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

daisytuner / sdfglib / 20770413849

06 Jan 2026 10:50PM UTC coverage: 62.168% (+21.4%) from 40.764%
20770413849

push

github

web-flow
Merge pull request #433 from daisytuner/clang-coverage

updates clang coverage flags

14988 of 24109 relevant lines covered (62.17%)

88.57 hits per line

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

71.14
/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) {
26✔
27
    switch (c) {
26✔
28
        case data_flow::TaskletCode::assign:
16✔
29
            return "=";
16✔
30
        case data_flow::TaskletCode::int_add:
2✔
31
        case data_flow::TaskletCode::fp_add:
4✔
32
            return "+";
4✔
33
        case data_flow::TaskletCode::int_sub:
×
34
        case data_flow::TaskletCode::fp_sub:
1✔
35
            return "-";
1✔
36
        case data_flow::TaskletCode::int_mul:
×
37
        case data_flow::TaskletCode::fp_mul:
4✔
38
            return "*";
4✔
39
        case data_flow::TaskletCode::int_udiv:
×
40
        case data_flow::TaskletCode::int_sdiv:
×
41
        case data_flow::TaskletCode::fp_div:
×
42
            return "/";
×
43
        case data_flow::TaskletCode::int_urem:
×
44
        case data_flow::TaskletCode::int_srem:
×
45
        case data_flow::TaskletCode::fp_rem:
×
46
            return "%";
×
47
        case data_flow::TaskletCode::fp_fma:
1✔
48
            return "fma";
1✔
49
        default:
×
50
            return "?";
×
51
    };
26✔
52
};
×
53

54
std::string Visualizer::expression(const std::string expr) {
121✔
55
    if (this->replacements_.empty()) return expr;
121✔
56
    std::string res = expr;
×
57
    size_t pos1 = 0, pos2 = 0;
×
58
    for (std::pair<const std::string, const std::string> replace : this->replacements_) {
×
59
        pos2 = res.find(replace.first);
×
60
        if (pos2 == res.npos) continue;
×
61
        pos1 = 0;
×
62
        std::stringstream res_tmp;
×
63
        while (pos2 < res.npos) {
×
64
            res_tmp << res.substr(pos1, pos2 - pos1) << replace.second;
×
65
            pos1 = pos2 + replace.first.size();
×
66
            pos2 = res.find(replace.first, pos1);
×
67
        }
×
68
        if (pos1 < res.npos) res_tmp << res.substr(pos1);
×
69
        res = res_tmp.str();
×
70
    }
×
71
    return res;
×
72
}
121✔
73

74
void Visualizer::visualizeNode(const StructuredSDFG& sdfg, const structured_control_flow::ControlFlowNode& node) {
47✔
75
    if (auto block = dynamic_cast<const structured_control_flow::Block*>(&node)) {
47✔
76
        this->visualizeBlock(sdfg, *block);
26✔
77
        return;
26✔
78
    }
26✔
79
    if (auto sequence = dynamic_cast<const structured_control_flow::Sequence*>(&node)) {
21✔
80
        this->visualizeSequence(sdfg, *sequence);
×
81
        return;
×
82
    }
×
83
    if (auto if_else = dynamic_cast<const structured_control_flow::IfElse*>(&node)) {
21✔
84
        this->visualizeIfElse(sdfg, *if_else);
3✔
85
        return;
3✔
86
    }
3✔
87
    if (auto while_loop = dynamic_cast<const structured_control_flow::While*>(&node)) {
18✔
88
        this->visualizeWhile(sdfg, *while_loop);
2✔
89
        return;
2✔
90
    }
2✔
91
    if (auto loop = dynamic_cast<const structured_control_flow::For*>(&node)) {
16✔
92
        this->visualizeFor(sdfg, *loop);
10✔
93
        return;
10✔
94
    }
10✔
95
    if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&node)) {
6✔
96
        this->visualizeReturn(sdfg, *return_node);
1✔
97
        return;
1✔
98
    }
1✔
99
    if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&node)) {
5✔
100
        this->visualizeBreak(sdfg, *break_node);
1✔
101
        return;
1✔
102
    }
1✔
103
    if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&node)) {
4✔
104
        this->visualizeContinue(sdfg, *continue_node);
1✔
105
        return;
1✔
106
    }
1✔
107
    if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&node)) {
3✔
108
        this->visualizeMap(sdfg, *map_node);
3✔
109
        return;
3✔
110
    }
3✔
111
    throw std::runtime_error("Unsupported control flow node");
×
112
}
3✔
113

114
void Visualizer::visualizeTasklet(data_flow::Tasklet const& tasklet) {
26✔
115
    std::string op = code_to_string(tasklet.code());
26✔
116
    std::vector<std::string> arguments;
26✔
117
    for (size_t i = 0; i < tasklet.inputs().size(); ++i) {
63✔
118
        arguments.push_back(this->expression(tasklet.input(i)));
37✔
119
    }
37✔
120

121
    if (tasklet.code() == data_flow::TaskletCode::assign) {
26✔
122
        this->stream_ << arguments.at(0);
16✔
123
    } else if (tasklet.code() == data_flow::TaskletCode::fp_fma) {
16✔
124
        if (arguments.size() != 3) throw std::runtime_error("FMA requires 3 arguments");
1✔
125
        this->stream_ << arguments.at(0) << " * " << arguments.at(1) << " + " << arguments.at(2);
1✔
126
    } else {
9✔
127
        this->stream_ << op << "(" << helpers::join(arguments, ", ") << ")";
9✔
128
    }
9✔
129
}
26✔
130

131
void Visualizer::visualizeForBounds(
132
    symbolic::Symbol const& indvar,
133
    symbolic::Expression const& init,
134
    symbolic::Condition const& condition,
135
    symbolic::Expression const& update
136
) {
13✔
137
    this->stream_ << indvar->get_name() << " = " << this->expression(init->__str__()) << "; "
13✔
138
                  << this->expression(condition->__str__()) << "; " << indvar->get_name() << " = "
13✔
139
                  << this->expression(update->__str__());
13✔
140
}
13✔
141

142
std::string Visualizer::subsetRangeString(data_flow::Subset const& subset, int subIdx) {
39✔
143
    auto& dim = subset.at(subIdx);
39✔
144
    return this->expression(dim->__str__());
39✔
145
}
39✔
146

147
/// @brief If known, use the type to better visualize structures. Then track the type as far as it goes.
148
void Visualizer::
149
    visualizeSubset(Function const& function, data_flow::Subset const& sub, types::IType const* type, int subIdx) {
95✔
150
    if (static_cast<int>(sub.size()) <= subIdx) {
95✔
151
        return;
56✔
152
    }
56✔
153
    if (auto structure_type = dynamic_cast<const types::Structure*>(type)) {
39✔
154
        types::StructureDefinition const& definition = function.structure(structure_type->name());
×
155

156
        auto memberIdx = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(sub.at(subIdx));
×
157
        if (!memberIdx.is_null()) {
×
158
            this->stream_ << ".member_" << this->expression(memberIdx->__str__());
×
159
            auto& member_type = definition.member_type(memberIdx);
×
160
            this->visualizeSubset(function, sub, &member_type, subIdx + 1);
×
161
        } else {
×
162
            this->stream_ << ".member[" << subsetRangeString(sub, subIdx) << "]";
×
163
            this->visualizeSubset(function, sub, nullptr, subIdx + 1);
×
164
        }
×
165
    } else if (auto array_type = dynamic_cast<const types::Array*>(type)) {
39✔
166
        this->stream_ << "[" << subsetRangeString(sub, subIdx) << "]";
16✔
167
        types::IType const& element_type = array_type->element_type();
16✔
168
        this->visualizeSubset(function, sub, &element_type, subIdx + 1);
16✔
169
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(type)) {
23✔
170
        this->stream_ << "[" << subsetRangeString(sub, subIdx) << "]";
22✔
171
        const types::IType* pointee_type;
22✔
172
        if (pointer_type->has_pointee_type()) {
22✔
173
            pointee_type = &pointer_type->pointee_type();
19✔
174
        } else {
19✔
175
            auto z = symbolic::zero();
3✔
176
            if (!symbolic::eq(sub.at(subIdx), z)) {
3✔
177
                this->stream_ << "#illgl";
1✔
178
            }
1✔
179
            pointee_type = nullptr;
3✔
180
        }
3✔
181
        this->visualizeSubset(function, sub, pointee_type, subIdx + 1);
22✔
182
    } else {
22✔
183
        if (type == nullptr) {
1✔
184
            this->stream_ << "(rogue)";
1✔
185
        }
1✔
186
        this->stream_ << "[" << subsetRangeString(sub, subIdx) << "]";
1✔
187
        visualizeSubset(function, sub, nullptr, subIdx + 1);
1✔
188
    }
1✔
189
}
39✔
190

191
} // namespace visualizer
192
} // 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