• 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

57.52
/src/codegen/dispatchers/block_dispatcher.cpp
1
#include "sdfg/codegen/dispatchers/block_dispatcher.h"
2

3
#include "sdfg/codegen/dispatchers/node_dispatcher_registry.h"
4
#include "sdfg/codegen/instrumentation/instrumentation_info.h"
5

6
namespace sdfg {
7
namespace codegen {
8

9
BlockDispatcher::BlockDispatcher(
6✔
10
    LanguageExtension& language_extension,
11
    StructuredSDFG& sdfg,
12
    analysis::AnalysisManager& analysis_manager,
13
    structured_control_flow::Block& node,
14
    InstrumentationPlan& instrumentation_plan,
15
    ArgCapturePlan& arg_capture_plan
16
)
17
    : sdfg::codegen::
6✔
18
          NodeDispatcher(language_extension, sdfg, analysis_manager, node, instrumentation_plan, arg_capture_plan),
6✔
19
      node_(node) {
6✔
20

21
      };
6✔
22

23
void BlockDispatcher::dispatch_node(
5✔
24
    PrettyPrinter& main_stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory
25
) {
26
    if (node_.dataflow().nodes().empty()) {
5✔
27
        return;
4✔
28
    }
29

30
    DataFlowDispatcher dispatcher(this->language_extension_, sdfg_, node_.dataflow(), instrumentation_plan_);
1✔
31
    dispatcher.dispatch(main_stream, globals_stream, library_snippet_factory);
1✔
32
};
5✔
33

34
DataFlowDispatcher::DataFlowDispatcher(
10✔
35
    LanguageExtension& language_extension,
36
    const Function& sdfg,
37
    const data_flow::DataFlowGraph& data_flow_graph,
38
    const InstrumentationPlan& instrumentation_plan
39
)
40
    : language_extension_(language_extension), function_(sdfg), data_flow_graph_(data_flow_graph),
10✔
41
      instrumentation_plan_(instrumentation_plan) {
10✔
42

43
      };
10✔
44

45
void DataFlowDispatcher::
46
    dispatch(PrettyPrinter& stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory) {
10✔
47
    // Dispatch code nodes in topological order
48
    auto nodes = this->data_flow_graph_.topological_sort();
10✔
49
    for (auto& node : nodes) {
35✔
50
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(node)) {
25✔
51
            this->dispatch_tasklet(stream, *tasklet);
3✔
52
        } else if (auto libnode = dynamic_cast<const data_flow::LibraryNode*>(node)) {
25✔
53
            this->dispatch_library_node(stream, globals_stream, library_snippet_factory, *libnode);
1✔
54
        } else if (auto access_node = dynamic_cast<const data_flow::AccessNode*>(node)) {
22✔
55
            for (auto& edge : this->data_flow_graph_.out_edges(*access_node)) {
32✔
56
                if (edge.type() == data_flow::MemletType::Reference) {
11✔
57
                    this->dispatch_ref(stream, edge);
4✔
58
                } else if (edge.type() == data_flow::MemletType::Dereference_Src) {
11✔
59
                    this->dispatch_deref_src(stream, edge);
1✔
60
                } else if (edge.type() == data_flow::MemletType::Dereference_Dst) {
7✔
61
                    this->dispatch_deref_dst(stream, edge);
2✔
62
                }
2✔
63
            }
64
        } else {
21✔
65
            throw InvalidSDFGException("Codegen: Node type not supported");
×
66
        }
67
    }
68
};
10✔
69

70
void DataFlowDispatcher::dispatch_ref(PrettyPrinter& stream, const data_flow::Memlet& memlet) {
4✔
71
    stream << "{" << std::endl;
4✔
72
    stream.setIndent(stream.indent() + 4);
4✔
73

74
    auto& src = dynamic_cast<const data_flow::AccessNode&>(memlet.src());
4✔
75
    auto& dst = dynamic_cast<const data_flow::AccessNode&>(memlet.dst());
4✔
76

77
    auto& subset = memlet.subset();
4✔
78
    auto& base_type = memlet.base_type();
4✔
79

80
    stream << this->language_extension_.access_node(dst);
4✔
81
    stream << " = ";
4✔
82

83
    std::string src_name = this->language_extension_.access_node(src);
4✔
84
    if (dynamic_cast<const data_flow::ConstantNode*>(&src)) {
4✔
85
        stream << src_name;
2✔
86
        stream << this->language_extension_.subset(base_type, subset);
2✔
87
    } else {
2✔
88
        if (base_type.type_id() == types::TypeID::Pointer && !subset.empty()) {
2✔
89
            stream << "&";
1✔
90
            stream << "(" + this->language_extension_.type_cast(src_name, base_type) + ")";
1✔
91
            stream << this->language_extension_.subset(base_type, subset);
1✔
92
        } else {
1✔
93
            stream << "&";
1✔
94
            stream << src_name;
1✔
95
            stream << this->language_extension_.subset(base_type, subset);
1✔
96
        }
97
    }
98

99
    stream << ";";
4✔
100
    stream << std::endl;
4✔
101

102
    stream.setIndent(stream.indent() - 4);
4✔
103
    stream << "}" << std::endl;
4✔
104
};
4✔
105

106
void DataFlowDispatcher::dispatch_deref_src(PrettyPrinter& stream, const data_flow::Memlet& memlet) {
1✔
107
    stream << "{" << std::endl;
1✔
108
    stream.setIndent(stream.indent() + 4);
1✔
109

110
    auto& src = dynamic_cast<const data_flow::AccessNode&>(memlet.src());
1✔
111
    auto& dst = dynamic_cast<const data_flow::AccessNode&>(memlet.dst());
1✔
112
    auto& dst_type = this->function_.type(dst.data());
1✔
113
    auto& base_type = static_cast<const types::Pointer&>(memlet.base_type());
1✔
114

115
    switch (dst_type.type_id()) {
1✔
116
        // first-class values
117
        case types::TypeID::Scalar:
118
        case types::TypeID::Pointer: {
119
            stream << this->language_extension_.access_node(dst);
1✔
120
            stream << " = ";
1✔
121
            stream << "*";
1✔
122

123
            std::string src_name = this->language_extension_.access_node(src);
1✔
124
            stream << "(" << this->language_extension_.type_cast(src_name, base_type) << ")";
1✔
125
            break;
126
        }
1✔
127
        // composite values
128
        case types::TypeID::Array:
129
        case types::TypeID::Structure: {
130
            // Memcpy
131
            std::string dst_name = this->language_extension_.access_node(dst);
×
132
            std::string src_name = this->language_extension_.access_node(src);
×
133
            stream << "memcpy(" << "&" << dst_name;
×
134
            stream << ", ";
×
135
            stream << "(" << src_name << ")";
×
136
            stream << ", ";
×
137
            stream << "sizeof " << dst_name;
×
138
            stream << ")";
×
139
            break;
140
        }
×
141
        case types::TypeID::Reference:
142
        case types::TypeID::Function: {
143
            throw InvalidSDFGException("Memlet: Dereference memlets cannot have reference or function destination types"
×
144
            );
145
        }
146
    }
147
    stream << ";" << std::endl;
1✔
148

149
    stream.setIndent(stream.indent() - 4);
1✔
150
    stream << "}" << std::endl;
1✔
151
};
1✔
152

153
void DataFlowDispatcher::dispatch_deref_dst(PrettyPrinter& stream, const data_flow::Memlet& memlet) {
2✔
154
    stream << "{" << std::endl;
2✔
155
    stream.setIndent(stream.indent() + 4);
2✔
156

157
    auto& src = dynamic_cast<const data_flow::AccessNode&>(memlet.src());
2✔
158
    auto& dst = dynamic_cast<const data_flow::AccessNode&>(memlet.dst());
2✔
159
    const sdfg::types::IType* src_type;
160
    if (auto const_node = dynamic_cast<const data_flow::ConstantNode*>(&src)) {
2✔
161
        src_type = &const_node->type();
1✔
162
    } else {
1✔
163
        src_type = &this->function_.type(src.data());
1✔
164
    }
165
    auto& base_type = static_cast<const types::Pointer&>(memlet.base_type());
2✔
166

167
    switch (src_type->type_id()) {
2✔
168
        // first-class values
169
        case types::TypeID::Scalar:
170
        case types::TypeID::Pointer: {
171
            stream << "*";
2✔
172
            std::string dst_name = this->language_extension_.access_node(dst);
2✔
173
            stream << "(" << this->language_extension_.type_cast(dst_name, base_type) << ")";
2✔
174
            stream << " = ";
2✔
175

176
            stream << this->language_extension_.access_node(src);
2✔
177
            break;
178
        }
2✔
179
        // composite values
180
        case types::TypeID::Array:
181
        case types::TypeID::Structure: {
182
            // Memcpy
183
            std::string src_name = this->language_extension_.access_node(src);
×
184
            std::string dst_name = this->language_extension_.access_node(dst);
×
185
            stream << "memcpy(";
×
186
            stream << "(" << dst_name << ")";
×
187
            stream << ", ";
×
188
            stream << "&" << src_name;
×
189
            stream << ", ";
×
190
            stream << "sizeof " << src_name;
×
191
            stream << ")";
×
192
            break;
193
        }
×
194
        case types::TypeID::Function:
195
        case types::TypeID::Reference: {
196
            throw InvalidSDFGException("Memlet: Dereference memlets cannot have source of type Function or Reference");
×
197
        }
198
    }
199
    stream << ";" << std::endl;
2✔
200

201
    stream.setIndent(stream.indent() - 4);
2✔
202
    stream << "}" << std::endl;
2✔
203
};
2✔
204

205
void DataFlowDispatcher::dispatch_tasklet(PrettyPrinter& stream, const data_flow::Tasklet& tasklet) {
3✔
206
    stream << "{" << std::endl;
3✔
207
    stream.setIndent(stream.indent() + 4);
3✔
208

209
    bool is_unsigned = data_flow::is_unsigned(tasklet.code());
3✔
210

211
    for (auto& iedge : this->data_flow_graph_.in_edges(tasklet)) {
7✔
212
        auto& src = dynamic_cast<const data_flow::AccessNode&>(iedge.src());
4✔
213
        std::string src_name = this->language_extension_.access_node(src);
4✔
214

215
        std::string conn = iedge.dst_conn();
4✔
216
        auto& conn_type = dynamic_cast<const types::Scalar&>(iedge.result_type(this->function_));
4✔
217
        if (is_unsigned) {
4✔
218
            types::Scalar conn_type_unsigned(types::as_unsigned(conn_type.primitive_type()));
×
219
            stream << this->language_extension_.declaration(conn, conn_type_unsigned);
×
220
            stream << " = ";
×
221
        } else {
×
222
            stream << this->language_extension_.declaration(conn, conn_type);
4✔
223
            stream << " = ";
4✔
224
        }
225

226
        // Reinterpret cast for opaque pointers
227
        if (iedge.base_type().type_id() == types::TypeID::Pointer) {
4✔
228
            stream << "(" << this->language_extension_.type_cast(src_name, iedge.base_type()) << ")";
×
229
        } else {
×
230
            stream << src_name;
4✔
231
        }
232

233
        stream << this->language_extension_.subset(iedge.base_type(), iedge.subset()) << ";";
4✔
234
        stream << std::endl;
4✔
235
    }
4✔
236

237
    auto& oedge = *this->data_flow_graph_.out_edges(tasklet).begin();
3✔
238
    std::string out_conn = oedge.src_conn();
3✔
239
    auto& out_conn_type = dynamic_cast<const types::Scalar&>(oedge.result_type(this->function_));
3✔
240
    if (is_unsigned) {
3✔
241
        types::Scalar out_conn_type_unsigned(types::as_unsigned(out_conn_type.primitive_type()));
×
242
        stream << this->language_extension_.declaration(out_conn, out_conn_type_unsigned);
×
243
        stream << ";" << std::endl;
×
244
    } else {
×
245
        stream << this->language_extension_.declaration(out_conn, out_conn_type);
3✔
246
        stream << ";" << std::endl;
3✔
247
    }
248

249

250
    stream << std::endl;
3✔
251
    stream << out_conn << " = ";
3✔
252
    stream << this->language_extension_.tasklet(tasklet) << ";" << std::endl;
3✔
253
    stream << std::endl;
3✔
254

255
    // Write back
256
    for (auto& oedge : this->data_flow_graph_.out_edges(tasklet)) {
6✔
257
        auto& dst = dynamic_cast<const data_flow::AccessNode&>(oedge.dst());
3✔
258

259
        std::string dst_name = this->language_extension_.access_node(dst);
3✔
260

261
        // Reinterpret cast for opaque pointers
262
        if (oedge.base_type().type_id() == types::TypeID::Pointer) {
3✔
263
            stream << "(" << this->language_extension_.type_cast(dst_name, oedge.base_type()) << ")";
×
264
        } else {
×
265
            stream << dst_name;
3✔
266
        }
267

268
        stream << this->language_extension_.subset(oedge.base_type(), oedge.subset()) << " = ";
3✔
269
        stream << oedge.src_conn();
3✔
270
        stream << ";" << std::endl;
3✔
271
    }
3✔
272

273
    stream.setIndent(stream.indent() - 4);
3✔
274
    stream << "}" << std::endl;
3✔
275
};
3✔
276

277
void DataFlowDispatcher::dispatch_library_node(
1✔
278
    PrettyPrinter& stream,
279
    PrettyPrinter& globals_stream,
280
    CodeSnippetFactory& library_snippet_factory,
281
    const data_flow::LibraryNode& libnode
282
) {
283
    auto dispatcher_fn =
284
        LibraryNodeDispatcherRegistry::instance()
2✔
285
            .get_library_node_dispatcher(libnode.code().value() + "::" + libnode.implementation_type().value());
1✔
286
    if (dispatcher_fn) {
1✔
287
        auto dispatcher = dispatcher_fn(this->language_extension_, this->function_, this->data_flow_graph_, libnode);
1✔
288

289
        auto instrument_info = dispatcher->instrumentation_info();
1✔
290
        if (this->instrumentation_plan_.should_instrument(libnode)) {
1✔
291
            this->instrumentation_plan_.begin_instrumentation(libnode, stream, language_extension_, instrument_info);
×
292
        }
×
293

294
        dispatcher->dispatch(stream, globals_stream, library_snippet_factory);
1✔
295

296
        if (this->instrumentation_plan_.should_instrument(libnode)) {
1✔
297
            this->instrumentation_plan_.end_instrumentation(libnode, stream, language_extension_, instrument_info);
×
298
        }
×
299
    } else {
1✔
300
        throw std::runtime_error(
×
301
            "No library node dispatcher found for library node code: " + std::string(libnode.code().value())
×
302
        );
303
    }
304
};
1✔
305

306
LibraryNodeDispatcher::LibraryNodeDispatcher(
1✔
307
    LanguageExtension& language_extension,
308
    const Function& function,
309
    const data_flow::DataFlowGraph& data_flow_graph,
310
    const data_flow::LibraryNode& node
311
)
312
    : language_extension_(language_extension), function_(function), data_flow_graph_(data_flow_graph), node_(node) {};
1✔
313

314
void LibraryNodeDispatcher::
315
    dispatch(PrettyPrinter& stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory) {
×
316
    auto& graph = this->node_.get_parent();
×
317

318
    stream << "{" << std::endl;
×
319
    stream.setIndent(stream.indent() + 4);
×
320

321
    // Define and initialize inputs
322
    for (auto& iedge : graph.in_edges(this->node_)) {
×
323
        auto& src = dynamic_cast<const data_flow::AccessNode&>(iedge.src());
×
324
        std::string src_name = this->language_extension_.access_node(src);
×
325

326
        std::string conn = iedge.dst_conn();
×
327
        auto& conn_type = iedge.result_type(this->function_);
×
328
        if (conn_type.type_id() == types::TypeID::Array || conn_type.type_id() == types::TypeID::Structure) {
×
329
            // Handle array and structure types
330
            stream << this->language_extension_.declaration(conn, conn_type) << ";" << std::endl;
×
331
            stream << "memcpy(" << "&" << conn << ", " << "&" << src_name
×
NEW
332
                   << this->language_extension_.subset(iedge.base_type(), iedge.subset()) << ", sizeof " << conn << ");"
×
NEW
333
                   << std::endl;
×
334
        } else {
×
335
            stream << this->language_extension_.declaration(conn, conn_type);
×
336
            stream << " = ";
×
337

338
            // Reinterpret cast for opaque pointers
339
            if (dynamic_cast<const data_flow::ConstantNode*>(&src)) {
×
340
                stream << src_name;
×
341
            } else {
×
342
                if (iedge.base_type().type_id() == types::TypeID::Pointer) {
×
343
                    stream << "(" << this->language_extension_.type_cast(src_name, iedge.base_type()) << ")";
×
344
                } else {
×
345
                    stream << src_name;
×
346
                }
347
            }
348

NEW
349
            stream << this->language_extension_.subset(iedge.base_type(), iedge.subset()) << ";";
×
350
            stream << std::endl;
×
351
        }
352
    }
×
353

354
    // Define outputs
355
    for (auto& oedge : graph.out_edges(this->node_)) {
×
356
        if (std::find(this->node_.inputs().begin(), this->node_.inputs().end(), oedge.src_conn()) !=
×
357
            this->node_.inputs().end()) {
×
358
            continue;
×
359
        }
360

361
        auto& dst = dynamic_cast<const data_flow::AccessNode&>(oedge.dst());
×
362
        std::string dst_name = this->language_extension_.access_node(dst);
×
363

364
        std::string conn = oedge.src_conn();
×
365
        auto& conn_type = oedge.result_type(this->function_);
×
366
        if (conn_type.type_id() == types::TypeID::Array || conn_type.type_id() == types::TypeID::Structure) {
×
367
            // Handle array and structure types
368
            stream << this->language_extension_.declaration(conn, conn_type) << ";" << std::endl;
×
369
            stream << "memcpy(" << "&" << conn << ", " << "&" << dst_name
×
NEW
370
                   << this->language_extension_.subset(oedge.base_type(), oedge.subset()) << ", sizeof " << conn << ");"
×
NEW
371
                   << std::endl;
×
372
        } else {
×
373
            stream << this->language_extension_.declaration(conn, conn_type);
×
374
            stream << " = ";
×
375

376
            // Reinterpret cast for opaque pointers
377
            if (oedge.base_type().type_id() == types::TypeID::Pointer) {
×
378
                stream << "(" << this->language_extension_.type_cast(dst_name, oedge.base_type()) << ")";
×
379
            } else {
×
380
                stream << dst_name;
×
381
            }
382

NEW
383
            stream << this->language_extension_.subset(oedge.base_type(), oedge.subset()) << ";";
×
384
            stream << std::endl;
×
385
        }
386
    }
×
387

388
    stream << std::endl;
×
389

390
    this->dispatch_code(stream, globals_stream, library_snippet_factory);
×
391

392
    stream << std::endl;
×
393

394
    for (auto& oedge : this->data_flow_graph_.out_edges(this->node_)) {
×
395
        auto& dst = dynamic_cast<const data_flow::AccessNode&>(oedge.dst());
×
396
        if (this->function_.is_external(dst.data())) {
×
397
            continue;
×
398
        }
399

400
        std::string dst_name = this->language_extension_.access_node(dst);
×
401

402
        auto& result_type = oedge.result_type(this->function_);
×
403
        if (result_type.type_id() == types::TypeID::Array || result_type.type_id() == types::TypeID::Structure) {
×
404
            stream << "memcpy(" << "&" << dst_name
×
NEW
405
                   << this->language_extension_.subset(oedge.base_type(), oedge.subset()) << ", " << "&"
×
406
                   << oedge.src_conn() << ", sizeof " << oedge.src_conn() << ");" << std::endl;
×
407
        } else {
×
408
            stream << dst_name;
×
NEW
409
            stream << this->language_extension_.subset(oedge.base_type(), oedge.subset()) << " = ";
×
410
            stream << oedge.src_conn();
×
411
            stream << ";" << std::endl;
×
412
        }
413
    }
×
414

415
    stream.setIndent(stream.indent() - 4);
×
416
    stream << "}" << std::endl;
×
417
}
×
418

419
InstrumentationInfo LibraryNodeDispatcher::instrumentation_info() const {
1✔
420
    return InstrumentationInfo(ElementType_Unknown, TargetType_SEQUENTIAL, -1, node_.element_id(), {});
1✔
421
};
×
422

423

424
} // namespace codegen
425
} // 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