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

daisytuner / docc / 24791492727

22 Apr 2026 05:00PM UTC coverage: 63.898%. First build
24791492727

Pull #690

github

web-flow
Merge 28e482eae into 8dc5e5aa7
Pull Request #690: Modular Compile process

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

30674 of 48005 relevant lines covered (63.9%)

572.91 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