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

Post changes from #7291 to Codegen_Xtensa #7299

Merged
merged 1 commit into from
Jan 20, 2023
Merged
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
102 changes: 81 additions & 21 deletions src/CodeGen_Xtensa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,34 +159,38 @@ void CodeGen_Xtensa::compile(const LoweredFunc &f, const std::map<std::string, s

Stmt body = match_xtensa_patterns(f.body, target);

const auto emit_arg_decls = [&](const Type &ucon_type = Type()) {
const char *comma = "";
for (const auto &arg : args) {
stream << comma;
if (arg.is_buffer()) {
stream << "struct halide_buffer_t *"
<< print_name(arg.name)
<< "_buffer";
} else {
// If this arg is the user_context value, *and* ucon_type is valid,
// use ucon_type instead of arg.type.
const Type &t = (arg.name == "__user_context" && ucon_type.bits() != 0) ? ucon_type : arg.type;
stream << print_type(t, AppendSpace) << print_name(arg.name);
}
comma = ", ";
}
};

// Emit the function prototype
if (f.linkage == LinkageType::Internal) {
// If the function isn't public, mark it static.
stream << "static ";
}
stream << "HALIDE_FUNCTION_ATTRS\n";
stream << "int " << simple_name << "(";
for (size_t i = 0; i < args.size(); i++) {
if (args[i].is_buffer()) {
external_buffers.insert(args[i].name);
stream << "struct halide_buffer_t *"
<< print_name(args[i].name)
<< "_buffer";
} else {
stream << print_type(args[i].type, AppendSpace)
<< print_name(args[i].name);
}

if (i < args.size() - 1) {
stream << ", ";
}
}
emit_arg_decls();

if (is_header_or_extern_decl()) {
stream << ");\n";
} else {
stream << ") {\n";
indent += 1;
stream << ") ";
open_scope();

if (uses_gpu_for_loops) {
stream << get_indent() << "halide_error("
Expand Down Expand Up @@ -224,15 +228,71 @@ void CodeGen_Xtensa::compile(const LoweredFunc &f, const std::map<std::string, s
cache.clear();
}

indent -= 1;
stream << "}\n";
// Ensure we use open/close_scope, so that the cache doesn't try to linger
// across function boundaries for internal closures.
close_scope("");
}

if (f.linkage == LinkageType::ExternalPlusMetadata) {
// Workaround for https://github.com/halide/Halide/issues/635:
// For historical reasons, Halide-generated AOT code
// defines user_context as `void const*`, but expects all
// define_extern code with user_context usage to use `void *`. This
// usually isn't an issue, but if both the caller and callee of the
// pass a user_context, *and* c_plus_plus_name_mangling is enabled,
// we get link errors because of this dichotomy. Fixing this
// "correctly" (ie so that everything always uses identical types for
// user_context in all cases) will require a *lot* of downstream
// churn (see https://github.com/halide/Halide/issues/7298),
// so this is a workaround: Add a wrapper with `void*`
// ucon -> `void const*` ucon. In most cases this will be ignored
// (and probably dead-stripped), but in these cases it's critical.
//
// (Note that we don't check to see if c_plus_plus_name_mangling is
// enabled, since that would have to be done on the caller side, and
// this is purely a callee-side fix.)
if (f.linkage != LinkageType::Internal &&
output_kind == CPlusPlusImplementation &&
target.has_feature(Target::CPlusPlusMangling) &&
get_target().has_feature(Target::UserContext)) {

Type ucon_type = Type();
for (const auto &arg : args) {
if (arg.name == "__user_context") {
ucon_type = arg.type;
break;
}
}
if (ucon_type == type_of<void const *>()) {
stream << "\nHALIDE_FUNCTION_ATTRS\n";
stream << "int " << simple_name << "(";
emit_arg_decls(type_of<void *>());
stream << ") ";
open_scope();
stream << get_indent() << " return " << simple_name << "(";
const char *comma = "";
for (const auto &arg : args) {
if (arg.name == "__user_context") {
// Add an explicit cast here so we won't call ourselves into oblivion
stream << "(void const *)";
}
stream << comma << print_name(arg.name);
if (arg.is_buffer()) {
stream << "_buffer";
}
comma = ", ";
}
stream << ");\n";
close_scope("");
}
}

if (f.linkage == LinkageType::ExternalPlusArgv || f.linkage == LinkageType::ExternalPlusMetadata) {
// Emit the argv version
emit_argv_wrapper(simple_name, args);
}

// And also the metadata.
if (f.linkage == LinkageType::ExternalPlusMetadata) {
// Emit the metadata.
emit_metadata_getter(simple_name, args, metadata_name_map);
}

Expand Down