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

daisytuner / sdfglib / 18122167774

30 Sep 2025 07:25AM UTC coverage: 61.108% (-0.01%) from 61.119%
18122167774

push

github

web-flow
Merge pull request #253 from daisytuner/type-rec-hotfix

Hotfix: dim_idx larger than range dims in analyze_type_rec

10 of 41 new or added lines in 2 files covered. (24.39%)

2 existing lines in 1 file now uncovered.

9567 of 15656 relevant lines covered (61.11%)

111.31 hits per line

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

58.04
/src/codegen/code_generator.cpp
1
#include "sdfg/codegen/code_generator.h"
2
#include <symengine/constants.h>
3
#include <symengine/dict.h>
4
#include <symengine/number.h>
5
#include "sdfg/analysis/analysis.h"
6
#include "sdfg/analysis/mem_access_range_analysis.h"
7
#include "sdfg/analysis/type_analysis.h"
8
#include "sdfg/codegen/instrumentation/capture_var_plan.h"
9
#include "sdfg/symbolic/symbolic.h"
10
#include "sdfg/types/structure.h"
11

12
namespace sdfg {
13
namespace codegen {
14

15
std::tuple<int, types::PrimitiveType> CodeGenerator::analyze_type_rec(
5✔
16
    symbolic::Expression* dims,
17
    int max_dim,
18
    int dim_idx,
19
    const types::IType& type,
20
    int arg_idx,
21
    const analysis::MemAccessRange* range,
22
    analysis::AnalysisManager& analysis_manager,
23
    const StructuredSDFG& sdfg,
24
    std::string var_name
25
) {
26
    if (dim_idx > max_dim) {
5✔
27
        std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << ": data nesting deeper than " << max_dim
×
28
                  << ", ignoring" << std::endl;
×
29
        return std::make_tuple(-1, types::Void);
×
30
    }
31

32
    if (auto* scalarType = dynamic_cast<const types::Scalar*>(&type)) {
5✔
33
        return std::make_tuple(dim_idx, scalarType->primitive_type());
3✔
34
    } else if (auto structureType = dynamic_cast<const sdfg::types::Structure*>(&type)) {
2✔
35
        return std::make_tuple(dim_idx, types::Void);
×
36
    } else if (auto* arrayType = dynamic_cast<const types::Array*>(&type)) {
2✔
37
        dims[dim_idx] = arrayType->num_elements();
1✔
38
        auto& inner = arrayType->element_type();
1✔
39

40
        return analyze_type_rec(dims, max_dim, dim_idx + 1, inner, arg_idx, range, analysis_manager, sdfg, var_name);
1✔
41
    } else if (auto* ptrType = dynamic_cast<const types::Pointer*>(&type)) {
1✔
42
        if (!range || range->is_undefined()) {
1✔
NEW
43
            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
44
                      << ": missing range, cannot capture!" << std::endl;
×
NEW
45
            return std::make_tuple(-2, types::Void);
×
46
        }
47
        if (range->dims().size() <= dim_idx) {
1✔
NEW
48
            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
49
                      << ": missing dimension in range, cannot capture!" << std::endl;
×
NEW
50
            return std::make_tuple(-2, types::Void);
×
51
        }
52
        const auto& dim = range->dims().at(dim_idx);
1✔
53
        if (!symbolic::eq(dim.first, symbolic::zero())) {
1✔
NEW
54
            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx << ": has upper bound "
×
NEW
55
                      << dim.second->__str__() << ", but does not start at 0, cannot capture" << std::endl;
×
NEW
56
            return std::make_tuple(-2, types::Void);
×
57
        }
58

59
        dims[dim_idx] = symbolic::add(dim.second, symbolic::one());
1✔
60
        const types::IType* inner = nullptr;
1✔
61
        if (ptrType->has_pointee_type()) {
1✔
62
            inner = &(ptrType->pointee_type());
1✔
63
        } else {
1✔
NEW
64
            if (dim_idx > 0) {
×
NEW
65
                std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
66
                          << ": missing pointee type for dim > 0, cannot capture!" << std::endl;
×
NEW
67
                return std::make_tuple(-2, types::Void);
×
68
            } else {
NEW
69
                auto& type_analysis = analysis_manager.get<analysis::TypeAnalysis>();
×
NEW
70
                auto outer = type_analysis.get_outer_type(var_name);
×
NEW
71
                if (outer != nullptr) {
×
NEW
72
                    if (auto* ptrType_new = dynamic_cast<const types::Pointer*>(outer)) {
×
NEW
73
                        if (ptrType_new->has_pointee_type()) {
×
NEW
74
                            inner = &(ptrType_new->pointee_type());
×
75
                        } else {
×
76
                            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
77
                                      << ": missing pointee type, cannot capture!" << std::endl;
×
78
                            return std::make_tuple(-2, types::Void);
×
79
                        }
UNCOV
80
                    }
×
NEW
81
                } else {
×
NEW
82
                    std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
83
                              << ": could not infer type from container, cannot capture!" << std::endl;
×
NEW
84
                    return std::make_tuple(-2, types::Void);
×
85
                }
86
            }
NEW
87
            if (inner == nullptr) {
×
NEW
88
                std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
NEW
89
                          << ": could not infer type from container, cannot capture!" << std::endl;
×
UNCOV
90
                return std::make_tuple(-2, types::Void);
×
91
            }
92
        }
93

94
        return analyze_type_rec(dims, max_dim, dim_idx + 1, *inner, arg_idx, range, analysis_manager, sdfg, var_name);
1✔
95
    }
96

NEW
97
    std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << ": unsupported type " << type.print()
×
NEW
98
              << ", cannot capture!" << std::endl;
×
NEW
99
    return std::make_tuple(-1, types::Void);
×
100
}
5✔
101

102
bool CodeGenerator::add_capture_plan(
3✔
103
    const std::string& var_name,
104
    int arg_idx,
105
    bool is_external,
106
    std::vector<CaptureVarPlan>& plan,
107
    const analysis::MemAccessRanges& ranges
108
) {
109
    const types::IType* type = nullptr;
3✔
110
    if (is_external) {
3✔
111
        auto& pointer_type = dynamic_cast<const types::Pointer&>(sdfg_.type(var_name));
1✔
112
        assert(pointer_type.has_pointee_type() && "Externals must have a pointee type");
2✔
113
        type = &pointer_type.pointee_type();
1✔
114
    } else {
1✔
115
        type = &sdfg_.type(var_name);
2✔
116
    }
117

118
    const auto* range = ranges.get(var_name);
3✔
119

120
    analysis::AnalysisManager analysis_manager(sdfg_);
3✔
121

122
    symbolic::Expression dims[3];
9✔
123

124
    int dim_count = 0;
3✔
125
    types::PrimitiveType inner_type;
126

127
    std::tie(dim_count, inner_type) =
3✔
128
        analyze_type_rec(dims, 3, 0, *type, arg_idx, range, analysis_manager, sdfg_, var_name);
3✔
129

130
    bool is_read = range ? range->saw_read() : true;
3✔
131
    bool is_written = range ? range->saw_write() : true;
3✔
132

133
    if (dim_count == 0) {
3✔
134
        plan.emplace_back(
4✔
135
            is_read || is_written, is_written && is_external, CaptureVarType::CapRaw, arg_idx, is_external, inner_type
2✔
136
        );
137
    } else if (dim_count == 1) {
3✔
138
        plan.emplace_back(is_read, is_written, CaptureVarType::Cap1D, arg_idx, is_external, inner_type, dims[0]);
×
139
    } else if (dim_count == 2) {
1✔
140
        plan.emplace_back(is_read, is_written, CaptureVarType::Cap2D, arg_idx, is_external, inner_type, dims[0], dims[1]);
1✔
141
    } else if (dim_count == 3) {
1✔
142
        plan.emplace_back(
×
143
            is_read, is_written, CaptureVarType::Cap3D, arg_idx, is_external, inner_type, dims[0], dims[1], dims[2]
×
144
        );
145
    } else {
×
146
        return false;
×
147
    }
148

149
    return true;
3✔
150
}
3✔
151

152
std::unique_ptr<std::vector<CaptureVarPlan>> CodeGenerator::create_capture_plans() {
1✔
153
    auto name = sdfg_.name();
1✔
154

155
    analysis::AnalysisManager analysis_manager(sdfg_);
1✔
156
    const auto& args = sdfg_.arguments();
1✔
157
    auto& exts = sdfg_.externals();
1✔
158
    const auto& ranges = analysis_manager.get<analysis::MemAccessRanges>();
1✔
159

160
    auto plan = std::make_unique<std::vector<CaptureVarPlan>>();
1✔
161

162
    bool working = true;
1✔
163

164
    int arg_idx = -1;
1✔
165
    for (auto& arg_name : args) {
3✔
166
        ++arg_idx;
2✔
167

168
        working &= add_capture_plan(arg_name, arg_idx, false, *plan.get(), ranges);
2✔
169
    }
170

171
    for (auto& arg_name : exts) {
2✔
172
        if (sdfg_.type(arg_name).type_id() == types::TypeID::Function) {
1✔
173
            continue;
×
174
        }
175
        ++arg_idx;
1✔
176

177
        working &= add_capture_plan(arg_name, arg_idx, true, *plan.get(), ranges);
1✔
178
    }
179

180
    if (!working) {
1✔
181
        std::cerr << "In '" << name << "': could not create capture plan, returning empty plan" << std::endl;
×
182
        return std::make_unique<std::vector<CaptureVarPlan>>();
×
183
    }
184

185
    return plan;
1✔
186
}
1✔
187

188
} // namespace codegen
189
} // 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