Skip to content

Commit 214388e

Browse files
authored
Fix several printing segfaults. (#8700)
* fix: segfaults printing undefined OutputImageParam, ImageParam, and Pipeline objects in Python * fix: segfault in Func::name() * fix: avoid touching the mtime of Halide.h (drive-by) Fixes #8699
1 parent 27763a1 commit 214388e

File tree

8 files changed

+70
-17
lines changed

8 files changed

+70
-17
lines changed

python_bindings/src/halide/halide_/PyImageParam.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,13 @@ void define_image_param(py::module &m) {
4444

4545
.def("__repr__", [](const OutputImageParam &im) -> std::string {
4646
std::ostringstream o;
47-
o << "<halide.OutputImageParam '" << im.name() << "'";
47+
o << "<halide.OutputImageParam ";
4848
if (!im.defined()) {
49-
o << " (undefined)";
49+
o << "OutputImageParam()";
5050
} else {
51-
// TODO: add dimensions to this
52-
o << " type " << halide_type_to_string(im.type());
51+
o << "'" << im.name() << "'"
52+
<< ", dims: " << im.dimensions()
53+
<< ", type: " << halide_type_to_string(im.type());
5354
}
5455
o << ">";
5556
return o.str();
@@ -79,12 +80,13 @@ void define_image_param(py::module &m) {
7980

8081
.def("__repr__", [](const ImageParam &im) -> std::string {
8182
std::ostringstream o;
82-
o << "<halide.ImageParam '" << im.name() << "'";
83+
o << "<halide.ImageParam ";
8384
if (!im.defined()) {
84-
o << " (undefined)";
85+
o << "ImageParam()";
8586
} else {
86-
// TODO: add dimensions to this
87-
o << " type " << halide_type_to_string(im.type());
87+
o << "'" << im.name() << "'"
88+
<< ", dims: " << im.dimensions()
89+
<< ", type: " << halide_type_to_string(im.type());
8890
}
8991
o << ">";
9092
return o.str();

python_bindings/src/halide/halide_/PyPipeline.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,19 @@ void define_pipeline(py::module &m) {
277277

278278
.def("__repr__", [](const Pipeline &p) -> std::string {
279279
std::ostringstream o;
280-
o << "<halide.Pipeline [";
281-
std::string comma;
282-
for (auto &f : p.outputs()) {
283-
o << comma << "'" << f.name() << "'";
284-
comma = ",";
280+
o << "<halide.Pipeline ";
281+
if (!p.defined()) {
282+
o << "Pipeline()";
283+
} else {
284+
o << "[";
285+
std::string comma;
286+
for (auto &f : p.outputs()) {
287+
o << comma << "'" << f.name() << "'";
288+
comma = ",";
289+
}
290+
o << "]";
285291
}
286-
o << "]>";
292+
o << ">";
287293
return o.str(); //
288294
});
289295

python_bindings/test/correctness/basics.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,6 @@ def test_unevaluated_funcref():
523523
g = hl.Func("g")
524524
g[x] = 2
525525

526-
print("------------------------")
527526
f = hl.Func("f")
528527
f[hl._] += g[hl._]
529528
assert list(f.realize([1])) == [2]
@@ -582,6 +581,23 @@ def test_implicit_update_by_float():
582581
assert f.realize([1])[0] == 0.5
583582

584583

584+
def test_print_ir():
585+
im = hl.ImageParam()
586+
assert str(im) == "<halide.ImageParam ImageParam()>"
587+
588+
im = hl.OutputImageParam()
589+
assert str(im) == "<halide.OutputImageParam OutputImageParam()>"
590+
591+
im = hl.ImageParam(hl.UInt(16), 2, "input")
592+
assert str(im) == "<halide.ImageParam 'input', dims: 2, type: uint16>"
593+
594+
r = hl.RDom()
595+
assert str(r) == "<halide.RDom RDom()>"
596+
597+
p = hl.Pipeline()
598+
assert str(p) == "<halide.Pipeline Pipeline()>"
599+
600+
585601
if __name__ == "__main__":
586602
test_compiletime_error()
587603
test_runtime_error()
@@ -605,3 +621,4 @@ def test_implicit_update_by_float():
605621
test_unevaluated_funcref()
606622
test_implicit_update_by_int()
607623
test_implicit_update_by_float()
624+
test_print_ir()

src/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,9 @@ set(LICENSE_PATH "${Halide_SOURCE_DIR}/LICENSE.txt")
469469
set(headers "$<TARGET_PROPERTY:Halide,HEADER_SET_private_headers>")
470470
add_custom_command(OUTPUT "${HALIDE_H}"
471471
COMMAND ${CMAKE_COMMAND} -E make_directory "$<SHELL_PATH:${Halide_BINARY_DIR}/include>"
472-
COMMAND build_halide_h "$<SHELL_PATH:${LICENSE_PATH}>" "${headers}" > "$<SHELL_PATH:${HALIDE_H}>"
472+
COMMAND build_halide_h "$<SHELL_PATH:${LICENSE_PATH}>" "${headers}" > "$<SHELL_PATH:${HALIDE_H}>.tmp"
473+
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<SHELL_PATH:${HALIDE_H}>.tmp" "$<SHELL_PATH:${HALIDE_H}>"
474+
COMMAND ${CMAKE_COMMAND} -E rm "$<SHELL_PATH:${HALIDE_H}>.tmp"
473475
DEPENDS build_halide_h "${LICENSE_PATH}" "${headers}"
474476
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
475477
COMMAND_EXPAND_LISTS

src/Func.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ Func::Func(const Expr &e)
8585

8686
Func::Func(Function f)
8787
: func(std::move(f)) {
88+
internal_assert(func.get_contents().defined())
89+
<< "Can't construct Func from undefined Function";
8890
}
8991

9092
const string &Func::name() const {

src/Func.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ class Func {
756756
* not contain free variables). */
757757
explicit Func(const Expr &e);
758758

759-
/** Construct a new Func to wrap an existing, already-define
759+
/** Construct a new Func to wrap an existing, already-defined
760760
* Function object. */
761761
explicit Func(Internal::Function f);
762762

test/error/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ tests(GROUPS error
2323
bad_ring_buffer.cpp
2424
bad_extern_split.cpp
2525
bad_fold.cpp
26+
bad_func_object.cpp
2627
bad_host_alignment.cpp
2728
bad_hoist_storage.cpp
2829
bad_partition_always.cpp

test/error/bad_func_object.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "Halide.h"
2+
using namespace Halide;
3+
4+
int main() {
5+
#ifdef HALIDE_WITH_EXCEPTIONS
6+
try {
7+
#endif
8+
const Internal::Function func{};
9+
const Func f{func}; // internal_assert
10+
11+
std::cout << f.name() << "\n"; // segfaults without above assert
12+
#ifdef HALIDE_WITH_EXCEPTIONS
13+
} catch (const InternalError &e) {
14+
// The harness rejects internal errors as they should typically not be
15+
// _expected_. However, we are directly testing a constructor invariant
16+
// check here, so an internal error is both expected and appropriate.
17+
throw std::runtime_error(e.what());
18+
}
19+
#endif
20+
21+
printf("Success!\n");
22+
return 0;
23+
}

0 commit comments

Comments
 (0)