object-introspection/types/std_unordered_multimap_type.toml
Jake Hillion 4c047b5f91 tbv2: add is_primitive to output
C++ has a concept of Primitive which holds in the type graph. However we don't
currently expose this information to the end user. Expose this from the OIL
iterator to allow future features like primitive rollups.

This affects containers like maps which have a fake `[]` element with no type.
They use this to group together the key/value in a map and to account for any
per element storage overhead. Currently the decision is to make the fake `[]`
element a primitive if all of its children are primitives. This allows for more
effective primitive rollups if that is implemented. This implementation detail
may be changed in future.

Test Plan:
- CI
- Updated simple tests.
2024-01-16 11:14:13 +00:00

130 lines
3.6 KiB
TOML

[info]
type_name = "std::unordered_multimap"
stub_template_params = [2,3,4]
ctype = "STD_UNORDERED_MULTIMAP_TYPE"
header = "unordered_map"
# Old:
typeName = "std::unordered_multimap<"
ns = ["namespace std"]
numTemplateParams = 2
replaceTemplateParamIndex = [2, 3]
allocatorIndex = 4
[codegen]
decl = """
template<class K, class T, class H, class KE, class A>
void getSizeType(const %1%<K, T, H, KE, A> &container, size_t& returnArg);
"""
func = """
template<class K, class T, class H, class KE, class A>
void getSizeType(const %1%<K, T, H, KE, A> &container, size_t& returnArg)
{
constexpr size_t nodeSize = sizeof(typename %1%<K, T, H, KE, A>::node_type);
size_t bucketCount = container.bucket_count();
size_t numElems = container.size();
SAVE_SIZE(sizeof(%1%<K, T, H, KE, A>) + (nodeSize * numElems) + (bucketCount * sizeof(uintptr_t)));
SAVE_DATA((uintptr_t)nodeSize);
SAVE_DATA((uintptr_t)bucketCount);
SAVE_DATA((uintptr_t)numElems);
for (auto const& it : container)
{
getSizeType(it.first, returnArg);
getSizeType(it.second, returnArg);
}
}
"""
traversal_func = """
auto tail = returnArg
.write((uintptr_t)&container)
.write(container.bucket_count())
.write(container.size());
for (const auto &it : container) {
tail = tail.delegate([&ctx, &it](auto ret) {
return OIInternal::getSizeType<Ctx>(ctx, it, ret);
});
}
return tail.finish();
"""
[[codegen.processor]]
type = "types::st::VarInt<DB>"
func = """
el.pointer = std::get<ParsedData::VarInt>(d.val).value;
"""
[[codegen.processor]]
type = "types::st::VarInt<DB>"
func = """
// Using the container's capacity to temporarily store the number of buckets
// TODO: Is there another way to pass a value across processors?
el.container_stats.emplace(result::Element::ContainerStats {
.capacity = std::get<ParsedData::VarInt>(d.val).value,
});
"""
[[codegen.processor]]
type = """
types::st::List<DB, types::st::Pair<DB,
typename TypeHandler<Ctx, T0>::type,
typename TypeHandler<Ctx, T1>::type>>
"""
func = """
#ifdef __GLIBCXX__
/* Use libstdc++ implementation __details to compute the size of Nodes and Buckets.
*
* See the source of <bits/hashtable_policy.h>:
* https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00536_source.html
*/
using OI_value_type = std::pair<const T0, T1>;
using OI_Hash_node =
std::__detail::_Hash_node<
OI_value_type,
std::__cache_default<OI_value_type, T2>::value>;
using OI_bucket = std::__detail::_Hash_node_base;
static constexpr size_t element_size = sizeof(OI_Hash_node);
static constexpr size_t bucket_size = sizeof(OI_bucket);
#else
static_assert(false && "No known element_size for sets. See types/set_type.toml");
#endif
auto list = std::get<ParsedData::List>(d.val);
// Reading the bucket count that was stored in `capacity` by the processor above.
size_t bucket_count = el.container_stats->capacity;
el.exclusive_size += bucket_count * bucket_size;
el.exclusive_size += list.length * (element_size - sizeof(T0));
// Overwrite the bucket count stored in `capacity` with the actual container's values.
el.container_stats.emplace(result::Element::ContainerStats {
.capacity = list.length,
.length = list.length,
});
static constexpr std::array<inst::Field, 2> element_fields{
make_field<Ctx, T0>("key"),
make_field<Ctx, T1>("value"),
};
static constexpr auto element = inst::Field{
element_size,
element_size - sizeof(T0) - sizeof(T1),
"[]",
std::array<std::string_view, 0>{},
element_fields,
std::array<inst::ProcessorInst, 0>{},
element_fields[0].is_primitive && element_fields[1].is_primitive,
};
for (size_t i = 0; i < list.length; i++)
stack_ins(element);
"""