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

daisytuner / sdfglib / 15656007340

14 Jun 2025 08:51PM UTC coverage: 13.234% (-49.9%) from 63.144%
15656007340

Pull #76

github

web-flow
Merge 9586c8161 into 413c53212
Pull Request #76: New Loop Dependency Analysis

361 of 465 new or added lines in 7 files covered. (77.63%)

6215 existing lines in 110 files now uncovered.

1612 of 12181 relevant lines covered (13.23%)

13.64 hits per line

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

0.0
/src/codegen/code_generators/c_code_generator.cpp
1
#include "sdfg/codegen/code_generators/c_code_generator.h"
2

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

7
namespace sdfg {
8
namespace codegen {
9

UNCOV
10
CCodeGenerator::CCodeGenerator(StructuredSDFG& sdfg)
×
UNCOV
11
    : CodeGenerator(sdfg, InstrumentationStrategy::NONE) {
×
UNCOV
12
    if (sdfg.type() != FunctionType_CPU) {
×
13
        throw std::runtime_error("CCodeGenerator can only be used for CPU SDFGs");
×
14
    }
UNCOV
15
};
×
16

17
CCodeGenerator::CCodeGenerator(StructuredSDFG& sdfg,
×
18
                               InstrumentationStrategy instrumentation_strategy)
19
    : CodeGenerator(sdfg, instrumentation_strategy) {
×
20
    if (sdfg.type() != FunctionType_CPU) {
×
21
        throw std::runtime_error("CCodeGenerator can only be used for CPU SDFGs");
×
22
    }
23
};
×
24

UNCOV
25
bool CCodeGenerator::generate() {
×
UNCOV
26
    this->dispatch_includes();
×
UNCOV
27
    this->dispatch_structures();
×
UNCOV
28
    this->dispatch_globals();
×
UNCOV
29
    this->dispatch_schedule();
×
UNCOV
30
    return true;
×
31
};
32

UNCOV
33
std::string CCodeGenerator::function_definition() {
×
34
    /********** Arglist **********/
UNCOV
35
    std::vector<std::string> args;
×
UNCOV
36
    for (auto& container : sdfg_.arguments()) {
×
37
        args.push_back(language_extension_.declaration(container, sdfg_.type(container)));
×
38
    }
UNCOV
39
    std::stringstream arglist;
×
UNCOV
40
    arglist << sdfg::helpers::join(args, ", ");
×
41

UNCOV
42
    return "extern void " + sdfg_.name() + "(" + arglist.str() + ")";
×
UNCOV
43
};
×
44

45
bool CCodeGenerator::as_source(const std::filesystem::path& header_path,
×
46
                               const std::filesystem::path& source_path,
47
                               const std::filesystem::path& library_path) {
48
    std::ofstream ofs_header(header_path, std::ofstream::out);
×
49
    if (!ofs_header.is_open()) {
×
50
        return false;
×
51
    }
52

53
    std::ofstream ofs_source(source_path, std::ofstream::out);
×
54
    if (!ofs_source.is_open()) {
×
55
        return false;
×
56
    }
57

58
    std::ofstream ofs_library(library_path, std::ofstream::out);
×
59
    if (!ofs_library.is_open()) {
×
60
        return false;
×
61
    }
62

63
    ofs_header << "#pragma once" << std::endl;
×
64
    ofs_header << this->includes_stream_.str() << std::endl;
×
65
    ofs_header << this->classes_stream_.str() << std::endl;
×
66
    ofs_header.close();
×
67

68
    ofs_source << "#include \"" << header_path.filename().string() << "\"" << std::endl;
×
69
    ofs_source << this->globals_stream_.str() << std::endl;
×
70
    ofs_source << this->function_definition() << std::endl;
×
71
    ofs_source << "{" << std::endl;
×
72

73
    if (instrumentation_strategy_ != InstrumentationStrategy::NONE) {
×
74
        ofs_source << "__daisy_instrument_init();" << std::endl;
×
75
    }
×
76

77
    ofs_source << this->main_stream_.str() << std::endl;
×
78

79
    if (instrumentation_strategy_ != InstrumentationStrategy::NONE) {
×
80
        ofs_source << "__daisy_instrument_finalize();" << std::endl;
×
81
    }
×
82

83
    ofs_source << "}" << std::endl;
×
84
    ofs_source.close();
×
85

86
    auto library_content = this->library_stream_.str();
×
87
    if (library_content.empty()) {
×
88
        ofs_library.close();
×
89
        return true;
×
90
    }
91

92
    ofs_library << "#include \"" << header_path.filename().string() << "\"" << std::endl;
×
93
    ofs_library << std::endl;
×
94

95
    ofs_library << "#undef HWY_TARGET_INCLUDE" << std::endl;
×
96
    ofs_library << "#define HWY_TARGET_INCLUDE " << library_path.filename() << std::endl;
×
97
    ofs_library << "#include <hwy/foreach_target.h>" << std::endl;
×
98
    ofs_library << "#include <hwy/highway.h>" << std::endl;
×
99
    ofs_library << "#include <hwy/contrib/math/math-inl.h>" << std::endl;
×
100
    ofs_library << std::endl;
×
101

102
    ofs_library << library_content << std::endl;
×
103
    ofs_library.close();
×
104

105
    return true;
×
106
};
×
107

UNCOV
108
void CCodeGenerator::dispatch_includes() {
×
UNCOV
109
    this->includes_stream_ << "#include <math.h>" << std::endl;
×
UNCOV
110
    this->includes_stream_ << "#include <stdbool.h>" << std::endl;
×
UNCOV
111
    this->includes_stream_ << "#include <stdlib.h>" << std::endl;
×
UNCOV
112
    if (this->instrumentation_strategy_ != InstrumentationStrategy::NONE)
×
113
        this->includes_stream_ << "#include <daisy_rtl.h>" << std::endl;
×
114

UNCOV
115
    this->includes_stream_ << "#define __daisy_min(a,b) ((a)<(b)?(a):(b))" << std::endl;
×
UNCOV
116
    this->includes_stream_ << "#define __daisy_max(a,b) ((a)>(b)?(a):(b))" << std::endl;
×
UNCOV
117
    this->includes_stream_ << "#define __daisy_fma(a,b,c) a * b + c" << std::endl;
×
UNCOV
118
};
×
119

UNCOV
120
void CCodeGenerator::dispatch_structures() {
×
121
    // Forward declarations
UNCOV
122
    for (auto& structure : sdfg_.structures()) {
×
UNCOV
123
        this->classes_stream_ << "typedef struct " << structure << " " << structure << ";"
×
UNCOV
124
                              << std::endl;
×
125
    }
126

127
    // Generate topology-sorted structure definitions
128
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> structures_graph;
129
    typedef boost::graph_traits<structures_graph>::vertex_descriptor Vertex;
UNCOV
130
    std::vector<std::string> names;
×
UNCOV
131
    for (auto& structure : sdfg_.structures()) {
×
UNCOV
132
        names.push_back(structure);
×
133
    }
UNCOV
134
    structures_graph graph(names.size());
×
135

UNCOV
136
    for (auto& structure : names) {
×
UNCOV
137
        auto& definition = sdfg_.structure(structure);
×
UNCOV
138
        for (size_t i = 0; i < definition.num_members(); i++) {
×
UNCOV
139
            auto member_type = &definition.member_type(symbolic::integer(i));
×
UNCOV
140
            while (dynamic_cast<const types::Array*>(member_type)) {
×
141
                auto array_type = static_cast<const types::Array*>(member_type);
×
142
                member_type = &array_type->element_type();
×
143
            }
144

UNCOV
145
            if (auto member_structure = dynamic_cast<const sdfg::types::Structure*>(member_type)) {
×
UNCOV
146
                boost::add_edge(
×
UNCOV
147
                    std::find(names.begin(), names.end(), member_structure->name()) - names.begin(),
×
UNCOV
148
                    std::find(names.begin(), names.end(), structure) - names.begin(), graph);
×
UNCOV
149
            }
×
UNCOV
150
        }
×
151
    }
152

UNCOV
153
    std::list<Vertex> order;
×
UNCOV
154
    std::unordered_map<Vertex, boost::default_color_type> vertex_colors;
×
UNCOV
155
    boost::topological_sort(graph, std::back_inserter(order),
×
UNCOV
156
                            boost::color_map(boost::make_assoc_property_map(vertex_colors)));
×
UNCOV
157
    order.reverse();
×
158

UNCOV
159
    for (auto& structure_index : order) {
×
UNCOV
160
        std::string structure = names.at(structure_index);
×
UNCOV
161
        auto& definition = sdfg_.structure(structure);
×
UNCOV
162
        this->classes_stream_ << "typedef struct ";
×
UNCOV
163
        if (definition.is_packed()) {
×
164
            this->classes_stream_ << "__attribute__((packed)) ";
×
165
        }
×
UNCOV
166
        this->classes_stream_ << structure << std::endl;
×
UNCOV
167
        this->classes_stream_ << "{\n";
×
168

UNCOV
169
        for (size_t i = 0; i < definition.num_members(); i++) {
×
UNCOV
170
            auto& member_type = definition.member_type(symbolic::integer(i));
×
UNCOV
171
            if (auto pointer_type = dynamic_cast<const sdfg::types::Pointer*>(&member_type)) {
×
172
                if (dynamic_cast<const sdfg::types::Structure*>(&pointer_type->pointee_type())) {
×
173
                    this->classes_stream_ << "struct ";
×
174
                }
×
175
            }
×
UNCOV
176
            this->classes_stream_ << language_extension_.declaration("member_" + std::to_string(i),
×
UNCOV
177
                                                                     member_type, false, true);
×
UNCOV
178
            this->classes_stream_ << ";" << std::endl;
×
UNCOV
179
        }
×
180

UNCOV
181
        this->classes_stream_ << "} " << structure << ";" << std::endl;
×
UNCOV
182
    }
×
UNCOV
183
};
×
184

UNCOV
185
void CCodeGenerator::dispatch_globals() {
×
UNCOV
186
    for (auto& container : sdfg_.externals()) {
×
UNCOV
187
        this->globals_stream_ << "extern "
×
UNCOV
188
                              << language_extension_.declaration(container, sdfg_.type(container))
×
UNCOV
189
                              << ";" << std::endl;
×
190
    }
UNCOV
191
};
×
192

UNCOV
193
void CCodeGenerator::dispatch_schedule() {
×
194
    // Map external variables to internal variables
UNCOV
195
    for (auto& container : sdfg_.containers()) {
×
UNCOV
196
        if (!sdfg_.is_internal(container)) {
×
UNCOV
197
            continue;
×
198
        }
199
        std::string external_name =
200
            container.substr(0, container.length() - external_suffix.length());
×
201
        this->main_stream_ << language_extension_.declaration(container, sdfg_.type(container));
×
202
        this->main_stream_ << " = "
×
203
                           << language_extension_.type_cast("&" + external_name,
×
204
                                                            sdfg_.type(container));
×
205
        this->main_stream_ << ";" << std::endl;
×
206
    }
×
207

208
    // Declare transient containers
UNCOV
209
    for (auto& container : sdfg_.containers()) {
×
UNCOV
210
        if (!sdfg_.is_transient(container)) {
×
UNCOV
211
            continue;
×
212
        }
213

214
        std::string val =
215
            this->language_extension_.declaration(container, sdfg_.type(container), false, true);
×
216
        if (!val.empty()) {
×
217
            this->main_stream_ << val;
×
218
            this->main_stream_ << ";" << std::endl;
×
219
        }
×
220
    }
×
221

222
    // Add instrumentation
UNCOV
223
    auto instrumentation = create_instrumentation(instrumentation_strategy_, sdfg_);
×
224

UNCOV
225
    auto dispatcher = create_dispatcher(language_extension_, sdfg_, sdfg_.root(), *instrumentation);
×
UNCOV
226
    dispatcher->dispatch(this->main_stream_, this->globals_stream_, this->library_stream_);
×
UNCOV
227
};
×
228

229
}  // namespace codegen
230
}  // 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