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

daisytuner / sdfglib / 20770413849

06 Jan 2026 10:50PM UTC coverage: 62.168% (+21.4%) from 40.764%
20770413849

push

github

web-flow
Merge pull request #433 from daisytuner/clang-coverage

updates clang coverage flags

14988 of 24109 relevant lines covered (62.17%)

88.57 hits per line

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

64.97
/src/codegen/code_generators/cuda_code_generator.cpp
1
#include "sdfg/codegen/code_generators/cuda_code_generator.h"
2

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

7
namespace sdfg {
8
namespace codegen {
9

10
CUDACodeGenerator::CUDACodeGenerator(
11
    StructuredSDFG& sdfg,
12
    analysis::AnalysisManager& analysis_manager,
13
    InstrumentationPlan& instrumentation_plan,
14
    ArgCapturePlan& arg_capture_plan,
15
    std::shared_ptr<CodeSnippetFactory> library_snippet_factory
16
)
17
    : CodeGenerator(sdfg, analysis_manager, instrumentation_plan, arg_capture_plan, std::move(library_snippet_factory)),
4✔
18
      language_extension_(sdfg) {
4✔
19
    if (sdfg.type() != FunctionType_NV_GLOBAL) {
4✔
20
        throw std::runtime_error("CUDACodeGenerator can only be used for GPU SDFGs");
×
21
    }
×
22
    if (!arg_capture_plan_.is_empty()) {
4✔
23
        DEBUG_PRINTLN("CUDACodeGenerator does not support capturing args/results!");
×
24
    }
×
25
};
4✔
26

27
bool CUDACodeGenerator::generate() {
3✔
28
    this->dispatch_includes();
3✔
29
    this->dispatch_structures();
3✔
30
    this->dispatch_globals();
3✔
31
    this->dispatch_schedule();
3✔
32
    return true;
3✔
33
};
3✔
34

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

44
    return "extern \"C\" __global__ void " + sdfg_.name() + "(" + arglist.str() + ")";
1✔
45
};
1✔
46

47
bool CUDACodeGenerator::as_source(const std::filesystem::path& header_path, const std::filesystem::path& source_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
    ofs_header << "#pragma once" << std::endl;
×
59
    ofs_header << this->includes_stream_.str() << std::endl;
×
60
    ofs_header << this->classes_stream_.str() << std::endl;
×
61
    ofs_header.close();
×
62

63
    ofs_source << "#include \"" << header_path.filename().string() << "\"" << std::endl;
×
64

65
    ofs_source << this->globals_stream_.str() << std::endl;
×
66

67
    append_function_source(ofs_source);
×
68

69
    ofs_source.close();
×
70

71
    return true;
×
72
};
×
73

74
void CUDACodeGenerator::append_function_source(std::ofstream& ofs_source) {
×
75
    ofs_source << this->function_definition() << std::endl;
×
76
    ofs_source << "{" << std::endl;
×
77
    ofs_source << this->main_stream_.str() << std::endl;
×
78
    ofs_source << "}" << std::endl;
×
79
}
×
80

81
void CUDACodeGenerator::dispatch_includes() {
3✔
82
    this->includes_stream_ << "#define "
3✔
83
                           << "__DAISY_NVVM__" << std::endl;
3✔
84
    this->includes_stream_ << "#include <cstdint>" << std::endl;
3✔
85
    this->includes_stream_ << "#include <daisy_rtl/daisy_rtl.h>" << std::endl;
3✔
86
};
3✔
87

88
void CUDACodeGenerator::dispatch_structures() {
3✔
89
    // Forward declarations
90
    for (auto& structure : sdfg_.structures()) {
3✔
91
        this->classes_stream_ << "struct " << structure << ";" << std::endl;
3✔
92
    }
3✔
93

94
    // Generate topology-sorted structure definitions
95
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> structures_graph;
3✔
96
    typedef boost::graph_traits<structures_graph>::vertex_descriptor Vertex;
3✔
97
    std::vector<std::string> names;
3✔
98
    for (auto& structure : sdfg_.structures()) {
3✔
99
        names.push_back(structure);
3✔
100
    }
3✔
101
    structures_graph graph(names.size());
3✔
102

103
    for (auto& structure : names) {
3✔
104
        auto& definition = sdfg_.structure(structure);
3✔
105
        for (size_t i = 0; i < definition.num_members(); i++) {
6✔
106
            auto member_type = &definition.member_type(symbolic::integer(i));
3✔
107
            while (dynamic_cast<const types::Array*>(member_type)) {
3✔
108
                auto array_type = static_cast<const types::Array*>(member_type);
×
109
                member_type = &array_type->element_type();
×
110
            }
×
111

112
            if (auto member_structure = dynamic_cast<const sdfg::types::Structure*>(member_type)) {
3✔
113
                boost::add_edge(
1✔
114
                    std::find(names.begin(), names.end(), member_structure->name()) - names.begin(),
1✔
115
                    std::find(names.begin(), names.end(), structure) - names.begin(),
1✔
116
                    graph
1✔
117
                );
1✔
118
            }
1✔
119
        }
3✔
120
    }
3✔
121

122
    std::list<Vertex> order;
3✔
123
    std::unordered_map<Vertex, boost::default_color_type> vertex_colors;
3✔
124
    boost::topological_sort(
3✔
125
        graph, std::back_inserter(order), boost::color_map(boost::make_assoc_property_map(vertex_colors))
3✔
126
    );
3✔
127
    order.reverse();
3✔
128

129
    for (auto& structure_index : order) {
3✔
130
        std::string structure = names.at(structure_index);
3✔
131
        auto& definition = sdfg_.structure(structure);
3✔
132
        this->classes_stream_ << "struct ";
3✔
133
        if (definition.is_packed()) {
3✔
134
            this->classes_stream_ << "__attribute__((packed)) ";
×
135
        }
×
136
        this->classes_stream_ << structure << std::endl;
3✔
137
        this->classes_stream_ << "{\n";
3✔
138

139
        for (size_t i = 0; i < definition.num_members(); i++) {
6✔
140
            auto& member_type = definition.member_type(symbolic::integer(i));
3✔
141
            if (dynamic_cast<const sdfg::types::Structure*>(&member_type)) {
3✔
142
                this->classes_stream_ << "struct ";
1✔
143
            }
1✔
144
            this->classes_stream_
3✔
145
                << language_extension_.declaration("member_" + std::to_string(i), member_type, false, true);
3✔
146
            this->classes_stream_ << ";" << std::endl;
3✔
147
        }
3✔
148

149
        this->classes_stream_ << "};" << std::endl;
3✔
150
    }
3✔
151
};
3✔
152

153
void CUDACodeGenerator::dispatch_globals() {
3✔
154
    for (auto& container : sdfg_.externals()) {
3✔
155
        auto& type = sdfg_.type(container);
1✔
156
        if (type.storage_type().is_nv_global()) {
1✔
157
            auto& base_type = dynamic_cast<const types::Pointer&>(type).pointee_type();
1✔
158
            if (sdfg_.linkage_type(container) == LinkageType_External) {
1✔
159
                this->globals_stream_ << "extern " << language_extension_.declaration(container, base_type) << ";"
1✔
160
                                      << std::endl;
1✔
161
            } else {
1✔
162
                this->globals_stream_ << "static " << language_extension_.declaration(container, base_type);
×
163
                if (!type.initializer().empty()) {
×
164
                    this->globals_stream_ << " = " << type.initializer();
×
165
                }
×
166
                this->globals_stream_ << ";" << std::endl;
×
167
            }
×
168
        }
1✔
169
        if (type.storage_type().is_nv_constant()) {
1✔
170
            assert(type.initializer().empty());
×
171
            auto& base_type = dynamic_cast<const types::Pointer&>(type).pointee_type();
×
172
            this->globals_stream_ << "__constant__ " << language_extension_.declaration(container, base_type, true)
×
173
                                  << ";" << std::endl;
×
174
        }
×
175
    }
1✔
176
};
3✔
177

178
void CUDACodeGenerator::dispatch_schedule() {
3✔
179
    // Declare shared memory
180
    for (auto& container : sdfg_.externals()) {
3✔
181
        auto& type = sdfg_.type(container);
1✔
182
        if (type.storage_type().is_nv_shared()) {
1✔
183
            this->main_stream_ << language_extension_.declaration(container, sdfg_.type(container)) << ";" << std::endl;
×
184
        }
×
185
    }
1✔
186

187
    // Declare transient containers
188
    for (auto& container : sdfg_.containers()) {
3✔
189
        if (!sdfg_.is_transient(container)) {
1✔
190
            continue;
1✔
191
        }
1✔
192

193
        std::string val = this->language_extension_.declaration(container, sdfg_.type(container), false, true);
×
194
        if (!val.empty()) {
×
195
            this->main_stream_ << val;
×
196
            this->main_stream_ << ";" << std::endl;
×
197
        }
×
198
    }
×
199

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

206
} // namespace codegen
207
} // 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