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

daisytuner / sdfglib / 18691595059

21 Oct 2025 05:00PM UTC coverage: 61.604% (+0.4%) from 61.158%
18691595059

push

github

web-flow
Merge pull request #291 from daisytuner/allocation-hoisting

adds memory allocation hoisting pass

78 of 97 new or added lines in 6 files covered. (80.41%)

1 existing line in 1 file now uncovered.

9458 of 15353 relevant lines covered (61.6%)

92.42 hits per line

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

61.7
/src/codegen/code_generators/cpp_code_generator.cpp
1
#include "sdfg/codegen/code_generators/cpp_code_generator.h"
2

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

6
namespace sdfg {
7
namespace codegen {
8

9
std::string CPPCodeGenerator::function_definition() {
1✔
10
    /********** Arglist **********/
11
    std::vector<std::string> args;
1✔
12
    for (auto& container : sdfg_.arguments()) {
1✔
13
        args.push_back(language_extension_.declaration(container, sdfg_.type(container)));
×
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 \"C\" " + this->language_extension_.declaration("", sdfg_.return_type()) + sdfg_.name() + "(" +
2✔
23
           arglist_str + ")";
1✔
24
};
1✔
25

26
void CPPCodeGenerator::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 __daisy_capture_t* __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 CPPCodeGenerator::dispatch_includes() {
4✔
39
    this->includes_stream_ << "#include <alloca.h>" << std::endl;
4✔
40
    this->includes_stream_ << "#include <cmath>" << std::endl;
4✔
41
    this->includes_stream_ << "#include <cstdio>" << std::endl;
4✔
42
    this->includes_stream_ << "#include <cstdlib>" << std::endl;
4✔
43
    this->includes_stream_ << "#include <cstring>" << std::endl;
4✔
44
    this->includes_stream_ << "#include <cblas.h>" << std::endl;
4✔
45
    this->includes_stream_ << "#include <daisy_rtl/daisy_rtl.h>" << std::endl;
4✔
46
};
4✔
47

48
void CPPCodeGenerator::dispatch_structures() {
4✔
49
    // Forward declarations
50
    for (auto& structure : sdfg_.structures()) {
8✔
51
        this->classes_stream_ << "struct " << structure << ";" << std::endl;
4✔
52
    }
53

54
    // Generate topology-sorted structure definitions
55
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> structures_graph;
56
    typedef boost::graph_traits<structures_graph>::vertex_descriptor Vertex;
57
    std::vector<std::string> names;
4✔
58
    for (auto& structure : sdfg_.structures()) {
8✔
59
        names.push_back(structure);
4✔
60
    }
61
    structures_graph graph(names.size());
4✔
62

63
    for (auto& structure : names) {
8✔
64
        auto& definition = sdfg_.structure(structure);
4✔
65
        for (size_t i = 0; i < definition.num_members(); i++) {
8✔
66
            auto member_type = &definition.member_type(symbolic::integer(i));
4✔
67
            while (dynamic_cast<const types::Array*>(member_type)) {
4✔
68
                auto array_type = static_cast<const types::Array*>(member_type);
×
69
                member_type = &array_type->element_type();
×
70
            }
71

72
            if (auto member_structure = dynamic_cast<const sdfg::types::Structure*>(member_type)) {
4✔
73
                boost::add_edge(
1✔
74
                    std::find(names.begin(), names.end(), member_structure->name()) - names.begin(),
1✔
75
                    std::find(names.begin(), names.end(), structure) - names.begin(),
1✔
76
                    graph
77
                );
78
            }
1✔
79
        }
4✔
80
    }
81

82
    std::list<Vertex> order;
4✔
83
    std::unordered_map<Vertex, boost::default_color_type> vertex_colors;
4✔
84
    boost::topological_sort(
4✔
85
        graph, std::back_inserter(order), boost::color_map(boost::make_assoc_property_map(vertex_colors))
4✔
86
    );
87
    order.reverse();
4✔
88

89
    for (auto& structure_index : order) {
8✔
90
        std::string structure = names.at(structure_index);
4✔
91
        auto& definition = sdfg_.structure(structure);
4✔
92
        this->classes_stream_ << "struct ";
4✔
93
        if (definition.is_packed()) {
4✔
94
            this->classes_stream_ << "__attribute__((packed)) ";
1✔
95
        }
1✔
96
        this->classes_stream_ << structure << std::endl;
4✔
97
        this->classes_stream_ << "{\n";
4✔
98

99
        for (size_t i = 0; i < definition.num_members(); i++) {
8✔
100
            auto& member_type = definition.member_type(symbolic::integer(i));
4✔
101
            if (dynamic_cast<const sdfg::types::Structure*>(&member_type)) {
4✔
102
                this->classes_stream_ << "struct ";
1✔
103
            }
1✔
104
            this->classes_stream_
8✔
105
                << language_extension_.declaration("member_" + std::to_string(i), member_type, false, true);
4✔
106
            this->classes_stream_ << ";" << std::endl;
4✔
107
        }
4✔
108

109
        this->classes_stream_ << "};" << std::endl;
4✔
110
    }
4✔
111
};
4✔
112

113
void CPPCodeGenerator::dispatch_globals() {
4✔
114
    // Declare globals
115
    for (auto& container : sdfg_.externals()) {
5✔
116
        // Function declarations
117
        if (dynamic_cast<const types::Function*>(&sdfg_.type(container))) {
1✔
118
            this->globals_stream_ << "extern \"C\" ";
×
119
            this->globals_stream_
×
120
                << language_extension_.declaration(this->externals_prefix_ + container, sdfg_.type(container)) << ";"
×
121
                << std::endl;
×
122
            continue;
×
123
        }
124

125
        // Other types must be pointers
126
        auto& type = dynamic_cast<const types::Pointer&>(sdfg_.type(container));
1✔
127
        assert(type.has_pointee_type() && "Externals must have a pointee type");
2✔
128
        auto& base_type = type.pointee_type();
1✔
129

130
        if (sdfg_.linkage_type(container) == LinkageType_External) {
1✔
131
            this->globals_stream_ << "extern "
2✔
132
                                  << language_extension_.declaration(this->externals_prefix_ + container, base_type)
1✔
133
                                  << ";" << std::endl;
1✔
134
        } else {
1✔
135
            this->globals_stream_ << "static "
×
136
                                  << language_extension_.declaration(this->externals_prefix_ + container, base_type);
×
137
            if (!type.initializer().empty()) {
×
138
                this->globals_stream_ << " = " << type.initializer();
×
139
            }
×
140
            this->globals_stream_ << ";" << std::endl;
×
141
        }
142
    }
143
};
4✔
144

145
void CPPCodeGenerator::dispatch_schedule() {
4✔
146
    // Allocate variables
147
    for (auto& container : sdfg_.containers()) {
5✔
148
        if (sdfg_.is_external(container)) {
1✔
149
            continue;
1✔
150
        }
151
        auto& type = sdfg_.type(container);
×
152

153
        // Declare transient
154
        if (sdfg_.is_transient(container)) {
×
155
            std::string val = this->language_extension_.declaration(container, sdfg_.type(container), false, true);
×
156
            if (!val.empty()) {
×
157
                this->main_stream_ << val;
×
158
                this->main_stream_ << ";" << std::endl;
×
159
            }
×
160
        }
×
161

162
        // Allocate if needed
163
        if (type.storage_type().is_cpu_stack()) {
×
164
            if (type.storage_type().allocation_size().is_null()) {
×
165
                continue;
×
166
            }
167
            this->main_stream_ << container << " = ";
×
168
            this->main_stream_ << "alloca("
×
169
                               << this->language_extension_.expression(type.storage_type().allocation_size()) << ")";
×
170
            this->main_stream_ << ";" << std::endl;
×
171
        } else if (type.storage_type().is_cpu_heap()) {
×
172
            if (!type.storage_type().allocation_size().is_null()) {
×
173
                continue;
×
174
            }
175
            this->main_stream_ << container << " = ";
×
NEW
176
            this->main_stream_ << this->externals_prefix_ << "malloc("
×
177
                               << this->language_extension_.expression(type.storage_type().allocation_size()) << ")";
×
178
            this->main_stream_ << ";" << std::endl;
×
179
        } else {
×
180
            assert(false && "Only CPU_Stack and CPU_Heap storage types are supported in C codegen");
×
181
        }
182
    }
183

184
    auto dispatcher = create_dispatcher(language_extension_, sdfg_, sdfg_.root(), instrumentation_plan_);
4✔
185
    dispatcher->dispatch(this->main_stream_, this->globals_stream_, this->library_snippet_factory_);
4✔
186

187
    // Free heap allocations
188
    for (auto& container : sdfg_.containers()) {
5✔
189
        if (sdfg_.is_external(container)) {
1✔
190
            continue;
1✔
191
        }
192
        auto& type = sdfg_.type(container);
×
193

194
        // Free if needed
195
        if (type.storage_type().is_cpu_heap()) {
×
196
            if (type.storage_type().allocation_lifetime() == types::StorageType::AllocationLifetime::Lifetime_SDFG) {
×
NEW
197
                this->main_stream_ << this->externals_prefix_ << "free(" << container << ");" << std::endl;
×
198
            }
×
199
        }
×
200
    }
201
};
4✔
202

203
} // namespace codegen
204
} // 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