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

daisytuner / docc / 23087278095

14 Mar 2026 11:44AM UTC coverage: 63.927% (+0.3%) from 63.617%
23087278095

push

github

web-flow
Merge pull request #568 from daisytuner/dead-data-elimination

Working on memory ownership & escape analysis

475 of 637 new or added lines in 28 files covered. (74.57%)

6 existing lines in 3 files now uncovered.

26010 of 40687 relevant lines covered (63.93%)

402.05 hits per line

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

38.46
/sdfg/src/data_flow/library_nodes/call_node.cpp
1
#include "sdfg/data_flow/library_nodes/call_node.h"
2

3
namespace sdfg {
4
namespace data_flow {
5

6
CallNode::CallNode(
7
    size_t element_id,
8
    const DebugInfo& debug_info,
9
    const graph::Vertex vertex,
10
    data_flow::DataFlowGraph& parent,
11
    const std::string& callee_name,
12
    const std::vector<std::string>& outputs,
13
    const std::vector<std::string>& inputs
14
)
15
    : LibraryNode(
8✔
16
          element_id,
8✔
17
          debug_info,
8✔
18
          vertex,
8✔
19
          parent,
8✔
20
          LibraryNodeType_Call,
8✔
21
          outputs,
8✔
22
          inputs,
8✔
23
          true,
8✔
24
          data_flow::ImplementationType_NONE
8✔
25
      ),
8✔
26
      callee_name_(callee_name) {}
8✔
27

28
const std::string& CallNode::callee_name() const { return this->callee_name_; }
3✔
29

30
bool CallNode::is_void(const Function& sdfg) const { return outputs_.empty() || outputs_.at(0) != "_ret"; }
9✔
31

32
bool CallNode::is_indirect_call(const Function& sdfg) const {
×
33
    auto& type = sdfg.type(this->callee_name_);
×
34
    return dynamic_cast<const types::Pointer*>(&type) != nullptr;
×
35
}
×
36

37
void CallNode::validate(const Function& function) const {
9✔
38
    LibraryNode::validate(function);
9✔
39

40
    if (!function.exists(this->callee_name_)) {
9✔
41
        throw InvalidSDFGException("CallNode: Function '" + this->callee_name_ + "' does not exist.");
×
42
    }
×
43
    auto& type = function.type(this->callee_name_);
9✔
44
    if (!dynamic_cast<const types::Function*>(&type) && !dynamic_cast<const types::Pointer*>(&type)) {
9✔
45
        throw InvalidSDFGException("CallNode: '" + this->callee_name_ + "' is not a function or pointer.");
×
46
    }
×
47

48
    if (auto func_type = dynamic_cast<const types::Function*>(&type)) {
9✔
49
        if (!function.is_external(this->callee_name_)) {
9✔
50
            throw InvalidSDFGException("CallNode: Function '" + this->callee_name_ + "' must be declared.");
×
51
        }
×
52
        if (!func_type->is_var_arg() && inputs_.size() != func_type->num_params()) {
9✔
53
            throw InvalidSDFGException(
×
54
                "CallNode: Number of inputs does not match number of function parameters. Expected " +
×
55
                std::to_string(func_type->num_params()) + ", got " + std::to_string(inputs_.size())
×
56
            );
×
57
        }
×
58
        if (!this->is_void(function) && outputs_.size() < 1) {
9✔
59
            throw InvalidSDFGException(
×
60
                "CallNode: Non-void function must have at least one output to store the return value."
×
61
            );
×
62
        }
×
63
    }
9✔
64
}
9✔
65

66
symbolic::SymbolSet CallNode::symbols() const { return {symbolic::symbol(this->callee_name_)}; }
9✔
67

68
std::unique_ptr<data_flow::DataFlowNode> CallNode::
69
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
70
    return std::make_unique<CallNode>(element_id, debug_info_, vertex, parent, callee_name_, outputs_, inputs_);
×
71
}
×
72

NEW
73
std::string CallNode::toStr() const { return LibraryNode::toStr() + "('" + callee_name_ + "')"; }
×
74

UNCOV
75
void CallNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {}
×
76

77
nlohmann::json CallNodeSerializer::serialize(const data_flow::LibraryNode& library_node) {
3✔
78
    const CallNode& node = static_cast<const CallNode&>(library_node);
3✔
79

80
    nlohmann::json j;
3✔
81
    j["code"] = node.code().value();
3✔
82
    j["callee_name"] = node.callee_name();
3✔
83
    j["outputs"] = node.outputs();
3✔
84
    j["inputs"] = node.inputs();
3✔
85

86
    return j;
3✔
87
}
3✔
88

89
data_flow::LibraryNode& CallNodeSerializer::deserialize(
90
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
91
) {
3✔
92
    assert(j.contains("code"));
3✔
93
    assert(j.contains("callee_name"));
3✔
94
    assert(j.contains("outputs"));
3✔
95
    assert(j.contains("inputs"));
3✔
96
    assert(j.contains("debug_info"));
3✔
97

98
    auto code = j["code"].get<std::string>();
3✔
99
    if (code != LibraryNodeType_Call.value()) {
3✔
100
        throw InvalidSDFGException("Invalid library node code");
×
101
    }
×
102

103
    sdfg::serializer::JSONSerializer serializer;
3✔
104
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
3✔
105

106
    std::string callee_name = j["callee_name"].get<std::string>();
3✔
107
    auto outputs = j["outputs"].get<std::vector<std::string>>();
3✔
108
    auto inputs = j["inputs"].get<std::vector<std::string>>();
3✔
109

110
    return builder.add_library_node<CallNode>(parent, debug_info, callee_name, outputs, inputs);
3✔
111
}
3✔
112

113
CallNodeDispatcher::CallNodeDispatcher(
114
    codegen::LanguageExtension& language_extension,
115
    const Function& function,
116
    const data_flow::DataFlowGraph& data_flow_graph,
117
    const CallNode& node
118
)
119
    : codegen::LibraryNodeDispatcher(language_extension, function, data_flow_graph, node) {}
×
120

121
void CallNodeDispatcher::dispatch_code(
122
    codegen::PrettyPrinter& stream,
123
    codegen::PrettyPrinter& globals_stream,
124
    codegen::CodeSnippetFactory& library_snippet_factory
125
) {
×
126
    auto& node = static_cast<const CallNode&>(node_);
×
127

128
    if (!node.is_void(function_)) {
×
129
        stream << node.outputs().at(0) << " = ";
×
130
    }
×
131
    if (node.is_indirect_call(function_)) {
×
132
        auto& graph = node.get_parent();
×
133

134
        // Collect return memlet
135
        const data_flow::Memlet* ret_memlet = nullptr;
×
136
        for (auto& oedge : graph.out_edges(node)) {
×
137
            if (oedge.src_conn() == "_ret") {
×
138
                ret_memlet = &oedge;
×
139
                break;
×
140
            }
×
141
        }
×
142

143
        // Collect input memlets
144
        std::unordered_map<std::string, const data_flow::Memlet*> input_memlets;
×
145
        for (auto& iedge : graph.in_edges(node)) {
×
146
            input_memlets[iedge.dst_conn()] = &iedge;
×
147
        }
×
148

149
        // Cast callee to function pointer type
150
        std::string func_ptr_type;
×
151

152
        // Return type
153
        if (ret_memlet) {
×
154
            auto ret_type = ret_memlet->result_type(function_);
×
155
            func_ptr_type = language_extension_.declaration("", *ret_type) + " (*)";
×
156
        } else {
×
157
            func_ptr_type = "void (*)";
×
158
        }
×
159

160
        // Parameters
161
        func_ptr_type += "(";
×
162
        for (size_t i = 0; i < node.inputs().size(); i++) {
×
163
            auto memlet_in = input_memlets.find(node.inputs().at(i));
×
164
            assert(memlet_in != input_memlets.end());
×
165
            auto in_type = memlet_in->second->result_type(function_);
×
166
            func_ptr_type += language_extension_.declaration("", *in_type);
×
167
            if (i < node.inputs().size() - 1) {
×
168
                func_ptr_type += ", ";
×
169
            }
×
170
        }
×
171
        func_ptr_type += ")";
×
172

173
        if (this->language_extension_.language() == "C") {
×
174
            stream << "((" << func_ptr_type << ") " << node.callee_name() << ")" << "(";
×
175
        } else if (this->language_extension_.language() == "C++") {
×
176
            stream << "reinterpret_cast<" << func_ptr_type << ">(" << node.callee_name() << ")" << "(";
×
177
        }
×
178
    } else {
×
179
        stream << this->language_extension_.external_prefix() << node.callee_name() << "(";
×
180
    }
×
181
    for (size_t i = 0; i < node.inputs().size(); ++i) {
×
182
        stream << node.inputs().at(i);
×
183
        if (i < node.inputs().size() - 1) {
×
184
            stream << ", ";
×
185
        }
×
186
    }
×
187
    stream << ")" << ";";
×
188
    stream << std::endl;
×
189
}
×
190

191
} // namespace data_flow
192
} // 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