Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor metadata-related cleanups #6759

Merged
merged 1 commit into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,11 @@ gengen
gen->set_generator_param_values(sub_generator_args);
return build_gradient_module ? gen->build_gradient_module(fn_name) : gen->build_module(fn_name);
};
compile_multitarget(function_name, output_files, targets, target_strings, module_factory, compiler_logger_factory);
// Pass target_strings for suffixes; if we omit this, we'll use *canonical* target strings
// for suffixes, but our caller might have passed non-canonical-but-still-legal target strings,
// and if we don't use those, the output filenames might not match what the caller expects.
const auto &suffixes = target_strings;
compile_multitarget(function_name, output_files, targets, suffixes, module_factory, compiler_logger_factory);
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,11 @@ void compile_multitarget(const std::string &fn_name,
user_assert(suffixes.empty() || suffixes.size() == targets.size())
<< "The suffixes list must be empty or the same length as the targets list.\n";

// Some tests were mistakenly passing filenames/pathnames here, which is not kosher
for (char c : "/\\") {
user_assert(fn_name.find(c) == std::string::npos) << "compile_multitarget: fn_name must not contain '" << c << "', but saw '" << fn_name << "'\n";
}

// The final target in the list is considered "baseline", and is used
// for (e.g.) the runtime and shared code. It is often just arch-bits-os
// with no other features (though this is *not* a requirement).
Expand Down
93 changes: 51 additions & 42 deletions test/correctness/compile_to_multitarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@

using namespace Halide;

std::string get_fname(const std::string &base) {
// Given a path like /path/to/some/file.ext, return file.ext
// If the path contains no separators (/ or \), just return it as-is
std::string leaf_name(const std::string &path) {
size_t sep = std::min(path.rfind('/'), path.rfind('\\'));
return path.substr(sep == std::string::npos ? 0 : sep + 1);
}

std::string get_output_path_prefix(const std::string &base) {
return Internal::get_test_tmp_dir() + "halide_test_correctness_compile_to_multitarget_" + base;
}

void test_compile_to_static_library(Func j) {
std::string fname = get_fname("c1");
std::string filename_prefix = get_output_path_prefix("c1");
const char *a = get_host_target().os == Target::Windows ? ".lib" : ".a";

std::vector<Target> targets = {
Expand All @@ -19,14 +26,14 @@ void test_compile_to_static_library(Func j) {
};

std::vector<std::string> files;
files.push_back(fname + ".h");
files.push_back(fname + a);
files.push_back(filename_prefix + ".h");
files.push_back(filename_prefix + a);

for (auto f : files) {
Internal::ensure_no_file_exists(f);
}

j.compile_to_multitarget_static_library(fname, j.infer_arguments(), targets);
j.compile_to_multitarget_static_library(filename_prefix, j.infer_arguments(), targets);

for (auto f : files) {
Internal::assert_file_exists(f);
Expand All @@ -37,7 +44,7 @@ void test_compile_to_static_library(Func j) {
}

void test_compile_to_object_files(Func j) {
std::string fname = get_fname("c2");
std::string filename_prefix = get_output_path_prefix("c2");
const char *o = get_host_target().os == Target::Windows ? ".obj" : ".o";

std::vector<std::string> target_strings = {
Expand All @@ -51,26 +58,26 @@ void test_compile_to_object_files(Func j) {
}

std::vector<std::string> files;
files.push_back(fname + ".h");
files.push_back(fname + "_runtime" + o);
files.push_back(fname + "_wrapper" + o);
files.push_back(filename_prefix + ".h");
files.push_back(filename_prefix + "_runtime" + o);
files.push_back(filename_prefix + "_wrapper" + o);
for (auto s : target_strings) {
files.push_back(fname + "-" + s + o);
files.push_back(filename_prefix + "-" + s + o);
}

for (auto f : files) {
Internal::ensure_no_file_exists(f);
}

j.compile_to_multitarget_object_files(fname, j.infer_arguments(), targets, target_strings);
j.compile_to_multitarget_object_files(filename_prefix, j.infer_arguments(), targets, target_strings);

for (auto f : files) {
Internal::assert_file_exists(f);
}
}

void test_compile_to_object_files_no_runtime(Func j) {
std::string fname = get_fname("c3");
std::string filename_prefix = get_output_path_prefix("c3");
const char *o = get_host_target().os == Target::Windows ? ".obj" : ".o";

std::vector<std::string> target_strings = {
Expand All @@ -84,25 +91,25 @@ void test_compile_to_object_files_no_runtime(Func j) {
}

std::vector<std::string> files;
files.push_back(fname + ".h");
files.push_back(fname + "_wrapper" + o);
files.push_back(filename_prefix + ".h");
files.push_back(filename_prefix + "_wrapper" + o);
for (auto s : target_strings) {
files.push_back(fname + "-" + s + o);
files.push_back(filename_prefix + "-" + s + o);
}

for (auto f : files) {
Internal::ensure_no_file_exists(f);
}

j.compile_to_multitarget_object_files(fname, j.infer_arguments(), targets, target_strings);
j.compile_to_multitarget_object_files(filename_prefix, j.infer_arguments(), targets, target_strings);

for (auto f : files) {
Internal::assert_file_exists(f);
}
}

void test_compile_to_object_files_single_target(Func j) {
std::string fname = get_fname("c4");
std::string filename_prefix = get_output_path_prefix("c4");
const char *o = get_host_target().os == Target::Windows ? ".obj" : ".o";

std::vector<std::string> target_strings = {
Expand All @@ -115,22 +122,22 @@ void test_compile_to_object_files_single_target(Func j) {
}

std::vector<std::string> files;
files.push_back(fname + ".h");
files.push_back(fname + o);
files.push_back(filename_prefix + ".h");
files.push_back(filename_prefix + o);

for (auto f : files) {
Internal::ensure_no_file_exists(f);
}

j.compile_to_multitarget_object_files(fname, j.infer_arguments(), targets, target_strings);
j.compile_to_multitarget_object_files(filename_prefix, j.infer_arguments(), targets, target_strings);

for (auto f : files) {
Internal::assert_file_exists(f);
}
}

void test_compile_to_everything(Func j, bool do_object) {
std::string fname = get_fname(do_object ? "c5" : "c6");
std::string filename_prefix = get_output_path_prefix(do_object ? "c5" : "c6");
const char *a = get_host_target().os == Target::Windows ? ".lib" : ".a";
const char *o = get_host_target().os == Target::Windows ? ".obj" : ".o";

Expand All @@ -149,18 +156,18 @@ void test_compile_to_everything(Func j, bool do_object) {
// single-file outputs
for (const char *ext : {".h", ".halide_generated.cpp", ".halide_compiler_log", ".py.cpp", ".pytorch.h", ".registration.cpp", ".schedule.h", a}) {
if (do_object && !strcmp(ext, a)) continue;
files.push_back(fname + ext);
files.push_back(filename_prefix + ext);
}
if (do_object) {
files.push_back(fname + "_runtime" + o);
files.push_back(fname + "_wrapper" + o);
files.push_back(filename_prefix + "_runtime" + o);
files.push_back(filename_prefix + "_wrapper" + o);
}

// multi-file outputs
for (const auto &s : target_strings) {
for (const char *ext : {".s", ".bc", ".featurization", ".ll", ".stmt", ".stmt.html", o}) {
if (!do_object && !strcmp(ext, o)) continue;
files.push_back(fname + "-" + s + ext);
files.push_back(filename_prefix + "-" + s + ext);
}
}

Expand All @@ -175,24 +182,24 @@ void test_compile_to_everything(Func j, bool do_object) {
return j.compile_to_module(args, name, target);
};
std::map<OutputFileType, std::string> outputs = {
{OutputFileType::assembly, fname + ".s"}, // IsMulti
{OutputFileType::bitcode, fname + ".bc"}, // IsMulti
{OutputFileType::c_header, fname + ".h"}, // IsSingle
{OutputFileType::c_source, fname + ".halide_generated.cpp"}, // IsSingle
{OutputFileType::compiler_log, fname + ".halide_compiler_log"}, // IsSingle
{OutputFileType::assembly, filename_prefix + ".s"}, // IsMulti
{OutputFileType::bitcode, filename_prefix + ".bc"}, // IsMulti
{OutputFileType::c_header, filename_prefix + ".h"}, // IsSingle
{OutputFileType::c_source, filename_prefix + ".halide_generated.cpp"}, // IsSingle
{OutputFileType::compiler_log, filename_prefix + ".halide_compiler_log"}, // IsSingle
// Note: compile_multitarget() doesn't produce cpp_stub output,
// even if you pass this in.
// {OutputFileType::cpp_stub, fname + ".stub.h"}, // IsSingle
{OutputFileType::featurization, fname + ".featurization"}, // IsMulti
{OutputFileType::llvm_assembly, fname + ".ll"}, // IsMulti
{OutputFileType::object, fname + o}, // IsMulti
{OutputFileType::python_extension, fname + ".py.cpp"}, // IsSingle
{OutputFileType::pytorch_wrapper, fname + ".pytorch.h"}, // IsSingle
{OutputFileType::registration, fname + ".registration.cpp"}, // IsSingle
{OutputFileType::schedule, fname + ".schedule.h"}, // IsSingle
{OutputFileType::static_library, fname + a}, // IsSingle
{OutputFileType::stmt, fname + ".stmt"}, // IsMulti
{OutputFileType::stmt_html, fname + ".stmt.html"}, // IsMulti
// {OutputFileType::cpp_stub, filename_prefix + ".stub.h"}, // IsSingle
{OutputFileType::featurization, filename_prefix + ".featurization"}, // IsMulti
{OutputFileType::llvm_assembly, filename_prefix + ".ll"}, // IsMulti
{OutputFileType::object, filename_prefix + o}, // IsMulti
{OutputFileType::python_extension, filename_prefix + ".py.cpp"}, // IsSingle
{OutputFileType::pytorch_wrapper, filename_prefix + ".pytorch.h"}, // IsSingle
{OutputFileType::registration, filename_prefix + ".registration.cpp"}, // IsSingle
{OutputFileType::schedule, filename_prefix + ".schedule.h"}, // IsSingle
{OutputFileType::static_library, filename_prefix + a}, // IsSingle
{OutputFileType::stmt, filename_prefix + ".stmt"}, // IsMulti
{OutputFileType::stmt_html, filename_prefix + ".stmt.html"}, // IsMulti
};
if (do_object) {
outputs.erase(OutputFileType::static_library);
Expand All @@ -205,7 +212,9 @@ void test_compile_to_everything(Func j, bool do_object) {
// it exists or not -- so just fill in with arbitrary strings.
return std::unique_ptr<Internal::CompilerLogger>(new Internal::JSONCompilerLogger("generator_name", "function_name", "autoscheduler_name", Target(), "generator_args", false));
};
compile_multitarget(fname, outputs, targets, target_strings, module_producer, compiler_logger_factory);
// The first argument to compile_multitarget is *function* name, not filename
std::string function_name = leaf_name(filename_prefix);
compile_multitarget(function_name, outputs, targets, target_strings, module_producer, compiler_logger_factory);

for (auto f : files) {
Internal::assert_file_exists(f);
Expand Down