Skip to content

Commit

Permalink
Remove CCW vtable logic from ABI interfaces which don't need them (#1216
Browse files Browse the repository at this point in the history
)

* Remove CCW vtable logic from ABI interfaces which are exclusive interfaces unless they are overridable as we do not generate CCW for them.

* PR feedback
  • Loading branch information
manodasanW authored Jul 11, 2022
1 parent 2162566 commit 58796c9
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
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;
}
});

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

0 comments on commit 58796c9

Please sign in to comment.