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

daisytuner / docc / 24845644334

23 Apr 2026 04:05PM UTC coverage: 64.104% (-0.06%) from 64.167%
24845644334

push

github

web-flow
Modular Compile process (#690)

 + DoccTarget to allow modularly adding support for snippets that need to be compiled differently (standalone, cross-compiled kernels or just with special compilers)
 + Builder infrastructure to define C/C++ build options with inheritance, overrides and ability to modify by plugins, extensions and targets as needed
 + The redirected handling of snippets based on the extension can contribute link-options when they have been used (the generic solution to highway support)
 + Model to handle any parallism for compile in its own class without having to touch the definitions and compile options
 + DoccPaths extended to resolve default plugin dirs (as used by et-plugin)
 + PrettyPrinter can write directly to another (file) stream instead of a local buffer
 * extended CodeGenerator to allow generating the header first and direct-to-file (its needed for all snippet & main compile, which could be parallel otherwise)
 + Defaults to parallel builds with as many cores as present
 + DOCC_DEBUG is more defined. A list of key-value pairs separated by ; or : Supported options: "dump" dump sdfgs, "build" add debug symbols, "build_threads=x" override thread count. less then 1 is the default auto-selection.
 + CodegenStats is integrated into the new Compiler concept. To reduce the impact of the asynchronicity, times are always measured, but only recored with the CodegenStats if enabled and later, in sequential places. The items recorded now include the sdfg & snippet names to identify slow parts
 + Switched MacOS tests over to inplace-python with only 1 build

224 of 347 new or added lines in 13 files covered. (64.55%)

2 existing lines in 2 files now uncovered.

30800 of 48047 relevant lines covered (64.1%)

573.39 hits per line

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

74.03
/sdfg/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

5
namespace sdfg {
6
namespace codegen {
7

8
std::string CCodeGenerator::function_definition() {
1✔
9
    /********** Arglist **********/
10
    std::vector<std::string> args;
1✔
11
    for (auto& container : this->sdfg_.arguments()) {
1✔
12
        args.push_back(language_extension_.declaration(container, this->sdfg_.type(container)));
×
13
    }
×
14

15
    std::stringstream arglist;
1✔
16
    arglist << sdfg::helpers::join(args, ", ");
1✔
17
    std::string arglist_str = arglist.str();
1✔
18
    if (arglist_str.empty()) {
1✔
19
        arglist_str = "void";
1✔
20
    }
1✔
21

22
    return "extern " + this->language_extension_.declaration("", sdfg_.return_type()) + this->externals_prefix_ +
1✔
23
           sdfg_.name() + "(" + arglist_str + ")";
1✔
24
};
1✔
25

26
void CCodeGenerator::emit_capture_context_init(std::ostream& ofs_source) const {
×
27
    std::string name = sdfg_.name();
×
28
    std::string arg_capture_path = sdfg_.metadata().at("arg_capture_path");
×
29

30
    ofs_source << "static void* __capture_ctx;" << std::endl;
×
31
    ofs_source << "static void __attribute__((constructor(1000))) __capture_ctx_init(void) {" << std::endl;
×
32
    ofs_source << "\t__capture_ctx = __daisy_capture_init(\"" << name << "\", \"" << arg_capture_path << "\");"
×
33
               << std::endl;
×
34
    ofs_source << "}" << std::endl;
×
35
    ofs_source << std::endl;
×
36
}
×
37

38
void CCodeGenerator::dispatch_header_includes(PrettyPrinter& out) {
10✔
39
#if defined(__linux__)
10✔
40
    out << "#include <alloca.h>" << std::endl;
10✔
41
    out << "#include <malloc.h>" << std::endl;
10✔
42
#endif
10✔
43

44
    out << "#include <math.h>" << std::endl;
10✔
45
    out << "#include <stdbool.h>" << std::endl;
10✔
46
    out << "#include <stdio.h>" << std::endl;
10✔
47
    out << "#include <stdlib.h>" << std::endl;
10✔
48
    out << "#include <string.h>" << std::endl;
10✔
49
    out << "#include <stdint.h>" << std::endl;
10✔
50

51
#if defined(__APPLE__)
52
    out << "#include <Accelerate/Accelerate.h>" << std::endl;
53
#else
54
    out << "#include <cblas.h>" << std::endl;
10✔
55
#endif
10✔
56

57
    out << "#include <daisy_rtl/daisy_rtl.h>" << std::endl;
10✔
58
};
10✔
59

60
void CCodeGenerator::dispatch_header_structures(PrettyPrinter& out) {
10✔
61
    // Forward declarations
62
    for (auto& structure : sdfg_.structures()) {
10✔
63
        out << "typedef struct " << structure << " " << structure << ";" << std::endl;
3✔
64
    }
3✔
65

66
    // Generate topology-sorted structure definitions
67
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> structures_graph;
10✔
68
    typedef boost::graph_traits<structures_graph>::vertex_descriptor Vertex;
10✔
69
    std::vector<std::string> names;
10✔
70
    for (auto& structure : sdfg_.structures()) {
10✔
71
        names.push_back(structure);
3✔
72
    }
3✔
73
    structures_graph graph(names.size());
10✔
74

75
    for (auto& structure : names) {
10✔
76
        auto& definition = sdfg_.structure(structure);
3✔
77
        for (size_t i = 0; i < definition.num_members(); i++) {
6✔
78
            auto member_type = &definition.member_type(symbolic::integer(i));
3✔
79
            while (dynamic_cast<const types::Array*>(member_type)) {
3✔
80
                auto array_type = static_cast<const types::Array*>(member_type);
×
81
                member_type = &array_type->element_type();
×
82
            }
×
83

84
            if (auto member_structure = dynamic_cast<const sdfg::types::Structure*>(member_type)) {
3✔
85
                boost::add_edge(
1✔
86
                    std::find(names.begin(), names.end(), member_structure->name()) - names.begin(),
1✔
87
                    std::find(names.begin(), names.end(), structure) - names.begin(),
1✔
88
                    graph
1✔
89
                );
1✔
90
            }
1✔
91
        }
3✔
92
    }
3✔
93

94
    std::list<Vertex> order;
10✔
95
    std::unordered_map<Vertex, boost::default_color_type> vertex_colors;
10✔
96
    boost::topological_sort(
10✔
97
        graph, std::back_inserter(order), boost::color_map(boost::make_assoc_property_map(vertex_colors))
10✔
98
    );
10✔
99
    order.reverse();
10✔
100

101
    for (auto& structure_index : order) {
10✔
102
        std::string structure = names.at(structure_index);
3✔
103
        auto& definition = sdfg_.structure(structure);
3✔
104
        out << "typedef struct ";
3✔
105
        if (definition.is_packed()) {
3✔
NEW
106
            out << "__attribute__((packed)) ";
×
107
        }
×
108
        out << structure << std::endl;
3✔
109
        out << "{\n";
3✔
110

111
        for (size_t i = 0; i < definition.num_members(); i++) {
6✔
112
            auto& member_type = definition.member_type(symbolic::integer(i));
3✔
113
            if (auto pointer_type = dynamic_cast<const sdfg::types::Pointer*>(&member_type)) {
3✔
114
                if (pointer_type->has_pointee_type() &&
×
115
                    dynamic_cast<const sdfg::types::Structure*>(&pointer_type->pointee_type())) {
×
NEW
116
                    out << "struct ";
×
117
                }
×
118
            }
×
119
            out << language_extension_.declaration("member_" + std::to_string(i), member_type, false, true);
3✔
120
            out << ";" << std::endl;
3✔
121
        }
3✔
122

123
        out << "} " << structure << ";" << std::endl;
3✔
124
    }
3✔
125
};
10✔
126

127
void CCodeGenerator::dispatch_globals() {
10✔
128
    // Declare globals
129
    for (auto& container : sdfg_.externals()) {
10✔
130
        // Function declarations
131
        if (dynamic_cast<const types::Function*>(&sdfg_.type(container))) {
1✔
132
            // Declare function
133
            this->globals_stream_ << "extern ";
×
134
            this->globals_stream_
×
135
                << language_extension_.declaration(this->externals_prefix_ + container, sdfg_.type(container)) << ";"
×
136
                << std::endl;
×
137
            continue;
×
138
        }
×
139

140
        // Other types must be pointers
141
        auto& type = dynamic_cast<const types::Pointer&>(sdfg_.type(container));
1✔
142
        assert(type.has_pointee_type() && "Externals must have a pointee type");
1✔
143
        auto& base_type = type.pointee_type();
1✔
144

145
        if (sdfg_.linkage_type(container) == LinkageType_External) {
1✔
146
            this->globals_stream_ << "extern "
1✔
147
                                  << language_extension_.declaration(this->externals_prefix_ + container, base_type)
1✔
148
                                  << ";" << std::endl;
1✔
149
        } else {
1✔
150
            this->globals_stream_ << "static "
×
151
                                  << language_extension_.declaration(this->externals_prefix_ + container, base_type);
×
152
            if (!type.initializer().empty()) {
×
153
                this->globals_stream_ << " = " << type.initializer();
×
154
            }
×
155
            this->globals_stream_ << ";" << std::endl;
×
156
        }
×
157
    }
1✔
158
};
10✔
159

160
void CCodeGenerator::dispatch_schedule() {
10✔
161
    // Allocate variables
162
    for (auto& container : sdfg_.containers()) {
10✔
163
        if (sdfg_.is_external(container)) {
8✔
164
            continue;
1✔
165
        }
1✔
166
        auto& type = sdfg_.type(container);
7✔
167

168
        // Declare transient
169
        if (sdfg_.is_transient(container)) {
7✔
170
            std::string val = this->language_extension_.declaration(container, sdfg_.type(container), false, true);
3✔
171
            if (!val.empty()) {
3✔
172
                this->main_stream_ << val;
3✔
173
                this->main_stream_ << ";" << std::endl;
3✔
174
            }
3✔
175
        }
3✔
176

177
        if (type.storage_type().allocation() == types::StorageType::AllocationType::Managed) {
7✔
178
            assert(
4✔
179
                !type.storage_type().allocation_size().is_null() &&
4✔
180
                "Managed allocations must have a valid allocation size"
4✔
181
            );
4✔
182
            if (type.storage_type().is_cpu_stack()) {
4✔
183
                this->main_stream_ << container << " = ";
×
184
                this->main_stream_
×
185
                    << "alloca(" << this->language_extension_.expression(type.storage_type().allocation_size()) << ")";
×
186
                this->main_stream_ << ";" << std::endl;
×
187
            } else if (type.storage_type().is_cpu_heap()) {
4✔
188
                this->main_stream_ << container << " = ";
4✔
189
                this->main_stream_ << this->externals_prefix_ << "malloc("
4✔
190
                                   << this->language_extension_.expression(type.storage_type().allocation_size())
4✔
191
                                   << ")";
4✔
192
                this->main_stream_ << ";" << std::endl;
4✔
193
            } else if (type.storage_type().is_nv_generic()) {
4✔
194
                this->main_stream_ << "cudaSetDevice(0);" << std::endl;
×
195
                this->main_stream_ << "cudaMalloc(&" << container << ", "
×
196
                                   << this->language_extension_.expression(type.storage_type().allocation_size())
×
197
                                   << ");" << std::endl;
×
198
            }
×
199
        }
4✔
200
    }
7✔
201

202
    auto dispatcher = create_dispatcher(
10✔
203
        language_extension_, sdfg_, analysis_manager_, sdfg_.root(), instrumentation_plan_, arg_capture_plan_
10✔
204
    );
10✔
205
    dispatcher->dispatch(this->main_stream_, this->globals_stream_, *this->library_snippet_factory_);
10✔
206

207
    if (sdfg_.root().size() == 0 ||
10✔
208
        !dynamic_cast<const structured_control_flow::Return*>(&(sdfg_.root().at(sdfg_.root().size() - 1)).first)) {
10✔
209
        // Free heap allocations
210
        for (auto& container : sdfg_.containers()) {
10✔
211
            if (sdfg_.is_external(container)) {
8✔
212
                continue;
1✔
213
            }
1✔
214
            auto& type = sdfg_.type(container);
7✔
215

216
            // Free if needed
217
            if (type.storage_type().deallocation() == types::StorageType::AllocationType::Managed) {
7✔
218
                if (type.storage_type().is_cpu_heap()) {
3✔
219
                    this->main_stream_ << this->externals_prefix_ << "free(" << container << ");" << std::endl;
3✔
220
                } else if (type.storage_type().is_nv_generic()) {
3✔
221
                    this->main_stream_ << "cudaSetDevice(0);" << std::endl;
×
222
                    this->main_stream_ << "cudaFree(" << container << ");" << std::endl;
×
223
                }
×
224
            }
3✔
225
        }
7✔
226
    }
10✔
227
};
10✔
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