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

Remove CCW vtable logic from ABI interfaces which don't need them #1216

Merged
merged 3 commits into from
Jul 11, 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
46 changes: 43 additions & 3 deletions src/cswinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5993,11 +5993,51 @@ public static Guid PIID = Vftbl.PIID;

bool write_abi_interface(writer& w, TypeDef const& type)
{

bool is_generic = distance(type.GenericParam()) > 0;
XLANG_ASSERT(get_category(type) == category::interface_type);
auto type_name = write_type_name_temp(w, type, "%", typedef_name_type::ABI);

// For exclusive interfaces which aren't overridable interfaces that are implemented by unsealed types,
// we do not need any of the Do_Abi functions or the vtable logic as we will not create CCWs for them.
// But we are still keeping the interface itself for any helper type lookup that may happen for like GUID lookup.
if (!is_generic &&
is_exclusive_to(type) &&
// check for !authored type
!(settings.component && settings.filter.includes(type)))
{
bool hasOverridableAttribute = false;
auto exclusive_to_type = get_exclusive_to_type(type);
for (auto&& iface : exclusive_to_type.InterfaceImpl())
{
for_typedef(w, get_type_semantics(iface.Interface()), [&](auto interface_type)
{
if (type == interface_type && is_overridable(iface))
{
hasOverridableAttribute = true;
manodasanW marked this conversation as resolved.
Show resolved Hide resolved
}
});

if (hasOverridableAttribute)
{
break;
}
}

if (!hasOverridableAttribute)
{
w.write(R"(%
internal interface % : %
{
}
)",
bind<write_guid_attribute>(type),
type_name,
bind<write_type_name>(type, typedef_name_type::CCW, false)
);
return true;
}
}

auto nongenerics_class = w.write_temp("%_Delegates", bind<write_typedef_name>(type, typedef_name_type::ABI, false));

std::vector<std::string> nongeneric_delegates;
Expand All @@ -6017,7 +6057,7 @@ internal unsafe interface % : %
type_name,
bind<write_type_name>(type, typedef_name_type::CCW, false),
[&](writer& w) {
w.write(distance(type.GenericParam()) > 0 ? "public static Guid PIID = Vftbl.PIID;\n\n" : "");
w.write(is_generic ? "public static Guid PIID = Vftbl.PIID;\n\n" : "");
},
// Vftbl
bind([&](writer& w)
Expand Down Expand Up @@ -7652,4 +7692,4 @@ bind<write_event_invoke_args>(invokeMethodSig));
typeNameToDefinitionMap[eventTypeCode] = eventClass;
}
}
}
}
19 changes: 19 additions & 0 deletions src/cswinrt/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ namespace cswinrt
return get_category(type) == category::interface_type && has_attribute(type, "Windows.Foundation.Metadata"sv, "ExclusiveToAttribute"sv);
}

TypeDef get_exclusive_to_type(TypeDef const& type)
{
if (auto exclusive_to_attr = get_attribute(type, "Windows.Foundation.Metadata"sv, "ExclusiveToAttribute"sv))
{
auto sig = exclusive_to_attr.Value();
auto const& fixed_args = sig.FixedArgs();
XLANG_ASSERT(fixed_args.size() == 1);
auto sys_type = std::get<ElemSig::SystemType>(std::get<ElemSig>(fixed_args[0].value).value);
return type.get_cache().find_required(sys_type.name);
}

throw_invalid("Exclusive type not found");
}

bool is_overridable(InterfaceImpl const& interfaceImpl)
{
return has_attribute(interfaceImpl, "Windows.Foundation.Metadata"sv, "OverridableAttribute"sv);
}

bool is_projection_internal(TypeDef const& type)
{
return has_attribute(type, "WinRT.Interop"sv, "ProjectionInternalAttribute"sv);
Expand Down