mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-09-19 11:09:05 +01:00
typed treebuilder for primitives and containers
This commit is contained in:
parent
76f525f43d
commit
c434988b43
43
dev.oid.toml
43
dev.oid.toml
@ -5,10 +5,10 @@
|
||||
[types]
|
||||
containers = [
|
||||
"PWD/types/array_type.toml",
|
||||
"PWD/types/string_type.toml",
|
||||
# "PWD/types/string_type.toml",
|
||||
"PWD/types/cxx11_string_type.toml",
|
||||
"PWD/types/folly_iobuf_type.toml",
|
||||
"PWD/types/folly_iobuf_queue_type.toml",
|
||||
# "PWD/types/folly_iobuf_type.toml",
|
||||
# "PWD/types/folly_iobuf_queue_type.toml",
|
||||
"PWD/types/set_type.toml",
|
||||
"PWD/types/unordered_set_type.toml",
|
||||
"PWD/types/seq_type.toml",
|
||||
@ -25,25 +25,28 @@ containers = [
|
||||
"PWD/types/priority_queue_container_adapter_type.toml",
|
||||
"PWD/types/ref_wrapper_type.toml",
|
||||
"PWD/types/multi_map_type.toml",
|
||||
"PWD/types/folly_small_heap_vector_map.toml",
|
||||
"PWD/types/folly_optional_type.toml",
|
||||
# "PWD/types/folly_small_heap_vector_map.toml",
|
||||
# "PWD/types/folly_optional_type.toml",
|
||||
"PWD/types/optional_type.toml",
|
||||
"PWD/types/try_type.toml",
|
||||
"PWD/types/fb_string_type.toml",
|
||||
"PWD/types/small_vec_type.toml",
|
||||
"PWD/types/f14_fast_map.toml",
|
||||
"PWD/types/f14_node_map.toml",
|
||||
"PWD/types/f14_vector_map.toml",
|
||||
"PWD/types/f14_fast_set.toml",
|
||||
"PWD/types/f14_node_set.toml",
|
||||
"PWD/types/f14_vector_set.toml",
|
||||
# "PWD/types/try_type.toml",
|
||||
# "PWD/types/fb_string_type.toml",
|
||||
# "PWD/types/small_vec_type.toml",
|
||||
# "PWD/types/f14_fast_map.toml",
|
||||
# "PWD/types/f14_node_map.toml",
|
||||
# "PWD/types/f14_vector_map.toml",
|
||||
# "PWD/types/f14_fast_set.toml",
|
||||
# "PWD/types/f14_node_set.toml",
|
||||
# "PWD/types/f14_vector_set.toml",
|
||||
"PWD/types/sorted_vec_set_type.toml",
|
||||
"PWD/types/map_seq_type.toml",
|
||||
"PWD/types/boost_bimap_type.toml",
|
||||
"PWD/types/repeated_field_type.toml",
|
||||
"PWD/types/repeated_ptr_field_type.toml",
|
||||
"PWD/types/caffe2_blob_type.toml",
|
||||
# "PWD/types/map_seq_type.toml",
|
||||
# "PWD/types/boost_bimap_type.toml",
|
||||
# "PWD/types/repeated_field_type.toml",
|
||||
# "PWD/types/repeated_ptr_field_type.toml",
|
||||
# "PWD/types/caffe2_blob_type.toml",
|
||||
"PWD/types/std_variant.toml",
|
||||
"PWD/types/thrift_isset_type.toml",
|
||||
# "PWD/types/thrift_isset_type.toml",
|
||||
"PWD/types/weak_ptr_type.toml",
|
||||
]
|
||||
|
||||
[codegen]
|
||||
default_namespaces = ["namespace std"]
|
||||
|
@ -154,6 +154,15 @@ std::unique_ptr<ContainerInfo> ContainerInfo::loadFromFile(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// std::string outputType;
|
||||
// if (std::optional<std::string> str =
|
||||
// (*codegen)["outputType"].value<std::string>()) {
|
||||
// func = std::move(*str);
|
||||
// } else {
|
||||
// LOG(ERROR) << "`codegen.outputType` is a required field";
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
return std::unique_ptr<ContainerInfo>(new ContainerInfo{
|
||||
std::move(typeName),
|
||||
std::move(matcher),
|
||||
@ -166,8 +175,9 @@ std::unique_ptr<ContainerInfo> ContainerInfo::loadFromFile(
|
||||
underlyingContainerIndex,
|
||||
|
||||
{
|
||||
std::move(decl),
|
||||
std::move(func),
|
||||
.outputType = "",
|
||||
.decl = std::move(decl),
|
||||
.func = std::move(func),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ const char* containerTypeEnumToStr(ContainerTypeEnum ty);
|
||||
|
||||
struct ContainerInfo {
|
||||
struct Codegen {
|
||||
std::string outputType;
|
||||
std::string decl;
|
||||
std::string func;
|
||||
};
|
||||
|
146
src/FuncGen.cpp
146
src/FuncGen.cpp
@ -134,13 +134,6 @@ const std::string typedValueFunc = R"(
|
||||
|
||||
} // namespace
|
||||
|
||||
void FuncGen::DeclareGetSize(std::string& testCode, const std::string& type) {
|
||||
boost::format fmt =
|
||||
boost::format("void getSizeType(const %1% &t, size_t& returnArg);\n") %
|
||||
type;
|
||||
testCode.append(fmt.str());
|
||||
}
|
||||
|
||||
void FuncGen::DeclareTopLevelGetSize(std::string& testCode,
|
||||
const std::string& type) {
|
||||
boost::format fmt = boost::format("void getSizeType(const %1% &t);\n") % type;
|
||||
@ -158,6 +151,59 @@ void FuncGen::DeclareEncodeData(std::string& testCode) {
|
||||
void FuncGen::DeclareEncodeDataSize(std::string& testCode) {
|
||||
testCode.append("size_t EncodeVarintSize(uint64_t val);\n");
|
||||
}
|
||||
void FuncGen::DeclareBasicTypeHandlers(std::string& testCode) {
|
||||
testCode.append(R"(
|
||||
template <typename DB, typename T>
|
||||
struct TypeHandler {
|
||||
private:
|
||||
static auto choose_type() {
|
||||
if constexpr(std::is_pointer_v<T>) {
|
||||
return std::type_identity<StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Sum<DB,
|
||||
StaticTypes::Unit<DB>,
|
||||
typename TypeHandler<DB, std::remove_pointer_t<T>>::type
|
||||
>>>();
|
||||
} else {
|
||||
return std::type_identity<StaticTypes::Unit<DB>>();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
using type = typename decltype(choose_type())::type;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const T& t,
|
||||
typename TypeHandler<DB, T>::type returnArg) {
|
||||
if constexpr(std::is_pointer_v<T>) {
|
||||
JLOG("ptr val @");
|
||||
JLOGPTR(t);
|
||||
auto r0 = returnArg.write((uintptr_t)t);
|
||||
if (t && pointers.add((uintptr_t)t)) {
|
||||
return r0.template delegate<1>([&t](auto ret) {
|
||||
if constexpr (!std::is_void<std::remove_pointer_t<T>>::value) {
|
||||
return TypeHandler<DB, std::remove_pointer_t<T>>::getSizeType(*t, ret);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return r0.template delegate<0>(std::identity());
|
||||
}
|
||||
} else {
|
||||
return returnArg;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DB>
|
||||
class TypeHandler<DB, void> {
|
||||
public:
|
||||
using type = StaticTypes::Unit<DB>;
|
||||
};
|
||||
)");
|
||||
}
|
||||
|
||||
void FuncGen::DefineEncodeData(std::string& testCode) {
|
||||
std::string func = R"(
|
||||
size_t EncodeVarint(uint64_t val, uint8_t* buf) {
|
||||
@ -245,6 +291,7 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
|
||||
{
|
||||
pointers.initialize();
|
||||
pointers.add((uintptr_t)&t);
|
||||
|
||||
auto data = reinterpret_cast<uintptr_t*>(dataBase);
|
||||
data[0] = oidMagicId;
|
||||
data[1] = cookieValue;
|
||||
@ -254,9 +301,21 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
|
||||
OIInternal::StoreData((uintptr_t)(&t), dataSegOffset);
|
||||
JLOG("%1% @");
|
||||
JLOGPTR(&t);
|
||||
OIInternal::getSizeType(t, dataSegOffset);
|
||||
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
|
||||
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
|
||||
|
||||
using DataBufferType = OIInternal::TypeHandler<DataBuffer::DataSegment, OIInternal::__ROOT_TYPE__>::type;
|
||||
DataBufferType db = DataBuffer::DataSegment(dataSegOffset);
|
||||
|
||||
StaticTypes::Unit<DataBuffer::DataSegment> out = OIInternal::getSizeType<DataBuffer::DataSegment>(t, db);
|
||||
|
||||
StaticTypes::Unit<DataBuffer::DataSegment> final = out.template cast<StaticTypes::Pair<
|
||||
DataBuffer::DataSegment,
|
||||
StaticTypes::VarInt<DataBuffer::DataSegment>,
|
||||
StaticTypes::VarInt<DataBuffer::DataSegment>
|
||||
>>()
|
||||
.write(123456789)
|
||||
.write(123456789);
|
||||
|
||||
dataSegOffset = final.bust() - dataBase;
|
||||
data[2] = dataSegOffset;
|
||||
dataBase += dataSegOffset;
|
||||
}
|
||||
@ -289,58 +348,29 @@ void FuncGen::DefineTopLevelGetSizeRefRet(std::string& testCode,
|
||||
testCode.append(fmt.str());
|
||||
}
|
||||
|
||||
void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
|
||||
const std::string& rawType) {
|
||||
std::string func = R"(
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-attributes"
|
||||
/* RawType: %1% */
|
||||
void __attribute__((used, retain)) getSize_%2$016x(const OIInternal::__ROOT_TYPE__& t)
|
||||
#pragma GCC diagnostic pop
|
||||
{
|
||||
pointers.initialize();
|
||||
auto data = reinterpret_cast<uintptr_t*>(dataBase);
|
||||
data[0] = oidMagicId;
|
||||
data[1] = cookieValue;
|
||||
data[2] = 0;
|
||||
|
||||
size_t dataSegOffset = 3 * sizeof(uintptr_t);
|
||||
OIInternal::StoreData((uintptr_t)(&t), dataSegOffset);
|
||||
|
||||
OIInternal::getSizeType(t, dataSegOffset);
|
||||
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
|
||||
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
|
||||
data[2] = dataSegOffset;
|
||||
dataBase += dataSegOffset;
|
||||
}
|
||||
)";
|
||||
|
||||
boost::format fmt =
|
||||
boost::format(func) % rawType % std::hash<std::string>{}(rawType);
|
||||
testCode.append(fmt.str());
|
||||
}
|
||||
|
||||
bool FuncGen::DeclareGetSizeFuncs(std::string& testCode,
|
||||
const ContainerInfoRefSet& containerInfo,
|
||||
bool chaseRawPointers) {
|
||||
testCode.append(R"(template<typename DB, typename T>
|
||||
StaticTypes::Unit<DB>
|
||||
getSizeType(const T &t, typename TypeHandler<DB, T>::type returnArg) {
|
||||
JLOG("obj @");
|
||||
JLOGPTR(&t);
|
||||
return TypeHandler<DB, T>::getSizeType(t, returnArg);
|
||||
}
|
||||
)");
|
||||
|
||||
for (const ContainerInfo& cInfo : containerInfo) {
|
||||
std::string ctype = cInfo.typeName;
|
||||
ctype = ctype.substr(0, ctype.find("<", 0));
|
||||
|
||||
auto& decl = cInfo.codegen.decl;
|
||||
LOG(ERROR) << "got here 0 decl";
|
||||
boost::format fmt = boost::format(decl) % ctype;
|
||||
LOG(ERROR) << "got here 1 decl";
|
||||
testCode.append(fmt.str());
|
||||
}
|
||||
|
||||
if (chaseRawPointers) {
|
||||
testCode.append(
|
||||
"template<typename T, typename = "
|
||||
"std::enable_if_t<!std::is_pointer_v<std::decay_t<T>>>>\n");
|
||||
} else {
|
||||
testCode.append("template<typename T>\n");
|
||||
}
|
||||
testCode.append("void getSizeType(const T &t, size_t& returnArg);");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -352,24 +382,12 @@ bool FuncGen::DefineGetSizeFuncs(std::string& testCode,
|
||||
ctype = ctype.substr(0, ctype.find("<", 0));
|
||||
|
||||
auto& func = cInfo.codegen.func;
|
||||
LOG(ERROR) << "got here 0 func";
|
||||
boost::format fmt = boost::format(func) % ctype;
|
||||
LOG(ERROR) << "got here 1 func";
|
||||
testCode.append(fmt.str());
|
||||
}
|
||||
|
||||
if (chaseRawPointers) {
|
||||
testCode.append("template<typename T, typename C>\n");
|
||||
} else {
|
||||
testCode.append("template<typename T>\n");
|
||||
}
|
||||
|
||||
testCode.append(R"(
|
||||
void getSizeType(const T &t, size_t& returnArg) {
|
||||
JLOG("obj @");
|
||||
JLOGPTR(&t);
|
||||
SAVE_SIZE(sizeof(T));
|
||||
}
|
||||
)");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,8 @@ class FuncGen {
|
||||
static void DeclareEncodeDataSize(std::string& testCode);
|
||||
static void DefineEncodeDataSize(std::string& testCode);
|
||||
|
||||
static void DeclareBasicTypeHandlers(std::string& testCode);
|
||||
|
||||
bool DeclareGetSizeFuncs(std::string& testCode,
|
||||
const ContainerInfoRefSet& containerInfo,
|
||||
bool chaseRawPointers);
|
||||
@ -46,8 +48,6 @@ class FuncGen {
|
||||
|
||||
static void DeclareGetContainer(std::string& testCode);
|
||||
|
||||
static void DeclareGetSize(std::string& testCode, const std::string& type);
|
||||
|
||||
static void DeclareTopLevelGetSize(std::string& testCode,
|
||||
const std::string& type);
|
||||
static void DefineTopLevelGetObjectSize(std::string& testCode,
|
||||
@ -60,9 +60,6 @@ class FuncGen {
|
||||
static void DefineTopLevelGetSizeRefRet(std::string& testCode,
|
||||
const std::string& type);
|
||||
|
||||
static void DefineTopLevelGetSizeSmartPtr(std::string& testCode,
|
||||
const std::string& rawType);
|
||||
|
||||
static void DefineGetSizeTypedValueFunc(std::string& testCode,
|
||||
const std::string& ctype);
|
||||
};
|
||||
|
@ -1695,22 +1695,28 @@ void OICodeGen::getFuncDefClassMembers(
|
||||
code += ">;\n";
|
||||
}
|
||||
|
||||
if (members.size() == 0) {
|
||||
code += "return returnArg;\n";
|
||||
return;
|
||||
}
|
||||
|
||||
code += "auto r1 = returnArg";
|
||||
for (std::size_t i = 0; i < members.size(); ++i) {
|
||||
if (captureThriftIsset && i < members.size() - 1) {
|
||||
// Capture Thrift's isset value for each field, except __isset itself,
|
||||
// which we assume comes last
|
||||
assert(members[i].member_name != "__isset");
|
||||
std::string issetIdxStr =
|
||||
"thrift_data::isset_indexes[" + std::to_string(i) + "]";
|
||||
code += "{\n";
|
||||
code += " if (&thrift_data::isset_indexes != nullptr &&\n";
|
||||
code += " " + issetIdxStr + " != -1) {\n";
|
||||
code += " SAVE_DATA(t.__isset.get(" + issetIdxStr + "));\n";
|
||||
code += " } else {\n";
|
||||
code += " SAVE_DATA(-1);\n";
|
||||
code += " }\n";
|
||||
code += "}\n";
|
||||
}
|
||||
// if (captureThriftIsset && i < members.size() - 1) {
|
||||
// // Capture Thrift's isset value for each field, except __isset itself,
|
||||
// // which we assume comes last
|
||||
// assert(members[i].member_name != "__isset");
|
||||
// std::string issetIdxStr =
|
||||
// "thrift_data::isset_indexes[" + std::to_string(i) + "]";
|
||||
// code += "{\n";
|
||||
// code += " if (&thrift_data::isset_indexes != nullptr &&\n";
|
||||
// code += " " + issetIdxStr + " != -1) {\n";
|
||||
// code += " SAVE_DATA(t.__isset.get(" + issetIdxStr + "));\n";
|
||||
// code += " } else {\n";
|
||||
// code += " SAVE_DATA(-1);\n";
|
||||
// code += " }\n";
|
||||
// code += "}\n";
|
||||
// }
|
||||
|
||||
const auto& member = members[i];
|
||||
std::string memberName = member.member_name;
|
||||
@ -1721,19 +1727,33 @@ void OICodeGen::getFuncDefClassMembers(
|
||||
if (memberName.empty()) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Check if the member is a bit field (bitFieldSize > 0).
|
||||
* If it is a bit field, we can't get its address with operator&.
|
||||
* If it is *NOT* a bit field, then we can print its address.
|
||||
*/
|
||||
if (member.bit_field_size > 0) {
|
||||
code += "JLOG(\"" + memberName + " (bit_field)\\n\");\n";
|
||||
} else {
|
||||
code += "JLOG(\"" + memberName + " @\");\n";
|
||||
code += "JLOGPTR(&t." + memberName + ");\n";
|
||||
}
|
||||
|
||||
code += "getSizeType(t." + memberName + ", returnArg);\n";
|
||||
if (i != members.size() - 1) {
|
||||
code += "\n .delegate([&t](auto ret) {\n";
|
||||
/*
|
||||
* Check if the member is a bit field (bitFieldSize > 0).
|
||||
* If it is a bit field, we can't get its address with operator&.
|
||||
* If it is *NOT* a bit field, then we can print its address.
|
||||
*/
|
||||
if (member.bit_field_size > 0) {
|
||||
code += " JLOG(\"" + memberName + " (bit_field)\\n\");\n";
|
||||
} else {
|
||||
code += " JLOG(\"" + memberName + " @\");\n";
|
||||
code += " JLOGPTR(&t." + memberName + ");\n";
|
||||
}
|
||||
code += " return OIInternal::getSizeType<DB>(t." + memberName +
|
||||
", ret);\n";
|
||||
code += " })";
|
||||
} else {
|
||||
code += ";\n";
|
||||
if (member.bit_field_size > 0) {
|
||||
code += " JLOG(\"" + memberName + " (bit_field)\\n\");\n";
|
||||
} else {
|
||||
code += " JLOG(\"" + memberName + " @\");\n";
|
||||
code += " JLOGPTR(&t." + memberName + ");\n";
|
||||
}
|
||||
code += " return OIInternal::getSizeType<DB>(t." + memberName + ", r1);\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1753,6 +1773,48 @@ void OICodeGen::enumerateDescendants(drgn_type* type, drgn_type* baseType) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string OICodeGen::getFuncDefTreeBuilderType(drgn_type* type,
|
||||
const std::string& typeName) {
|
||||
if (drgn_type_kind(type) == DRGN_TYPE_TYPEDEF) {
|
||||
// Handle case where parent is a typedef
|
||||
return getFuncDefTreeBuilderType(drgnUnderlyingType(type), typeName);
|
||||
}
|
||||
|
||||
std::string out;
|
||||
|
||||
size_t count = 0;
|
||||
const auto& members = classMembersMap[type];
|
||||
std::unordered_map<std::string, int> memberNames;
|
||||
for (std::size_t i = 0; i < members.size(); ++i) {
|
||||
const auto& member = members[i];
|
||||
|
||||
std::string memberName = member.member_name;
|
||||
std::replace(memberName.begin(), memberName.end(), '.', '_');
|
||||
deduplicateMemberName(memberNames, memberName);
|
||||
if (memberName.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i != members.size() - 1) {
|
||||
out += "StaticTypes::Pair<DB, ";
|
||||
count++;
|
||||
}
|
||||
out +=
|
||||
(boost::format("typename TypeHandler<DB, decltype(%1%::%2%)>::type") %
|
||||
typeName % memberName)
|
||||
.str();
|
||||
if (i != members.size() - 1) {
|
||||
out += ", ";
|
||||
}
|
||||
}
|
||||
out += std::string(count, '>');
|
||||
|
||||
if (!out.empty()) {
|
||||
return out;
|
||||
}
|
||||
return "StaticTypes::Unit<DB>";
|
||||
}
|
||||
|
||||
void OICodeGen::getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
const std::string& typeName) {
|
||||
if (classMembersMap.find(type) == classMembersMap.end()) {
|
||||
@ -1764,13 +1826,24 @@ void OICodeGen::getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
funcName = "getSizeTypeConcrete";
|
||||
}
|
||||
|
||||
code +=
|
||||
"void " + funcName + "(const " + typeName + "& t, size_t& returnArg) {\n";
|
||||
auto typeStaticType = getFuncDefTreeBuilderType(type, typeName);
|
||||
|
||||
code += (boost::format(R"(
|
||||
template <typename DB>
|
||||
struct TypeHandler<DB, %1%> {
|
||||
using type = %3%;
|
||||
|
||||
static StaticTypes::Unit<DB> %2%(
|
||||
const %1% &t,
|
||||
typename TypeHandler<DB, %1%>::type returnArg) {
|
||||
)") % typeName %
|
||||
funcName % typeStaticType)
|
||||
.str();
|
||||
|
||||
std::unordered_map<std::string, int> memberNames;
|
||||
getFuncDefClassMembers(code, type, memberNames);
|
||||
|
||||
code += "}\n";
|
||||
code += " }\n";
|
||||
|
||||
if (isDynamic(type)) {
|
||||
enumerateDescendants(type, type);
|
||||
@ -1810,8 +1883,10 @@ void OICodeGen::getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
"& t, size_t& returnArg);\n";
|
||||
}
|
||||
|
||||
code += std::string("void getSizeType(const ") + typeName +
|
||||
std::string("& t, size_t& returnArg) {\n");
|
||||
code += "template <typename DB>\n";
|
||||
code += std::string("StaticTypes::Unit<DB> getSizeType(const ") + typeName +
|
||||
std::string("& t, typename TypeHandler<" + typeName +
|
||||
">::type returnArg) {\n");
|
||||
// The Itanium C++ ABI defines that the vptr must appear at the zero-offset
|
||||
// position in any class in which they are present.
|
||||
code += " auto *vptr = *reinterpret_cast<uintptr_t * const *>(&t);\n";
|
||||
@ -1846,6 +1921,8 @@ void OICodeGen::getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
code += " getSizeTypeConcrete(t, returnArg);\n";
|
||||
code += "}\n";
|
||||
}
|
||||
|
||||
code += "\n};";
|
||||
}
|
||||
|
||||
std::string OICodeGen::templateTransformType(const std::string& typeName) {
|
||||
@ -3231,6 +3308,7 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
std::string functionsCode;
|
||||
functionsCode.append("namespace OIInternal {\nnamespace {\n");
|
||||
functionsCode.append("// functions -----\n");
|
||||
funcGen.DeclareBasicTypeHandlers(functionsCode);
|
||||
if (!funcGen.DeclareGetSizeFuncs(functionsCode, containerTypesFuncDef,
|
||||
config.chaseRawPointers)) {
|
||||
LOG(ERROR) << "declaring get size for containers failed";
|
||||
@ -3246,18 +3324,6 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
)");
|
||||
}
|
||||
|
||||
for (auto& e : structDefType) {
|
||||
if (drgn_type_kind(e) != DRGN_TYPE_UNION) {
|
||||
auto typeName = getNameForType(e);
|
||||
|
||||
if (!typeName.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
funcGen.DeclareGetSize(functionsCode, *typeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.useDataSegment || config.chaseRawPointers) {
|
||||
funcGen.DeclareStoreData(functionsCode);
|
||||
}
|
||||
@ -3275,28 +3341,6 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config.chaseRawPointers) {
|
||||
functionsCode.append(R"(
|
||||
template<typename T>
|
||||
void getSizeType(const T* s_ptr, size_t& returnArg)
|
||||
{
|
||||
JLOG("ptr val @");
|
||||
JLOGPTR(s_ptr);
|
||||
StoreData((uintptr_t)(s_ptr), returnArg);
|
||||
if (s_ptr && pointers.add((uintptr_t)s_ptr)) {
|
||||
getSizeType(*(s_ptr), returnArg);
|
||||
}
|
||||
}
|
||||
|
||||
void getSizeType(const void *s_ptr, size_t& returnArg)
|
||||
{
|
||||
JLOG("void ptr @");
|
||||
JLOGPTR(s_ptr);
|
||||
StoreData((uintptr_t)(s_ptr), returnArg);
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
for (auto& e : structDefType) {
|
||||
auto name = getNameForType(e);
|
||||
|
||||
@ -3364,7 +3408,8 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
if (rootTypeStr.starts_with("unique_ptr") ||
|
||||
rootTypeStr.starts_with("LowPtr") ||
|
||||
rootTypeStr.starts_with("shared_ptr")) {
|
||||
funcGen.DefineTopLevelGetSizeSmartPtr(functionsCode, rawTypeName);
|
||||
// funcGen.DefineTopLevelGetSizeSmartPtr(functionsCode, rawTypeName);
|
||||
funcGen.DefineTopLevelGetSizeRef(functionsCode, rawTypeName);
|
||||
} else {
|
||||
funcGen.DefineTopLevelGetSizeRef(functionsCode, rawTypeName);
|
||||
}
|
||||
|
@ -228,6 +228,7 @@ class OICodeGen {
|
||||
bool& ifStub);
|
||||
bool getContainerTemplateParams(drgn_type* type, bool& ifStub);
|
||||
void enumerateDescendants(drgn_type* type, drgn_type* baseType);
|
||||
std::string getFuncDefTreeBuilderType(drgn_type* type, const std::string&);
|
||||
void getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
const std::string& typeName);
|
||||
std::optional<uint64_t> getDrgnTypeSize(drgn_type* type);
|
||||
|
@ -14,6 +14,9 @@ R"(
|
||||
#include <cstdint>
|
||||
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <unistd.h>
|
||||
|
||||
// clang-format on
|
||||
@ -21,7 +24,7 @@ R"(
|
||||
#define C10_USING_CUSTOM_GENERATED_MACROS
|
||||
|
||||
// These globals are set by oid, see end of OIDebugger::compileCode()
|
||||
extern uintptr_t dataBase;
|
||||
extern uint8_t* dataBase;
|
||||
extern size_t dataSize;
|
||||
extern uintptr_t cookieValue;
|
||||
extern int logFile;
|
||||
@ -154,4 +157,185 @@ template <>
|
||||
struct DummySizedOperator<0> {
|
||||
};
|
||||
|
||||
namespace ObjectIntrospection {
|
||||
namespace DataBuffer {
|
||||
|
||||
class DataBuffer {
|
||||
protected:
|
||||
void write_byte(uint8_t);
|
||||
};
|
||||
|
||||
class DataSegment: public DataBuffer {
|
||||
public:
|
||||
DataSegment(size_t offset) : buf(dataBase + offset) {}
|
||||
|
||||
void write_byte(uint8_t byte) {
|
||||
if (buf > (dataBase + dataSize * 8)) {
|
||||
// TODO: fail
|
||||
}
|
||||
*buf = byte;
|
||||
buf++;
|
||||
}
|
||||
|
||||
// TODO: REMOVE ME
|
||||
uint8_t* bust() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* buf;
|
||||
};
|
||||
|
||||
} // namespace DataBuffer
|
||||
|
||||
namespace RuntimeTypes {
|
||||
class Unit {};
|
||||
|
||||
class VarInt {
|
||||
|
||||
};
|
||||
|
||||
using Dynamic = std::variant<
|
||||
std::reference_wrapper<const Unit>,
|
||||
std::reference_wrapper<const VarInt>>;
|
||||
|
||||
} // namespace RuntimeTypes
|
||||
|
||||
namespace StaticTypes {
|
||||
|
||||
template <typename DataBuffer>
|
||||
class Unit {
|
||||
public:
|
||||
Unit(DataBuffer db) : _buf(db) {}
|
||||
|
||||
static RuntimeTypes::Dynamic describe() {
|
||||
static auto singleton = RuntimeTypes::Unit();
|
||||
return RuntimeTypes::Dynamic(singleton);
|
||||
}
|
||||
|
||||
// TODO: REMOVE ME
|
||||
uint8_t* bust() {
|
||||
return _buf.bust();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T cast() {
|
||||
return T(_buf);
|
||||
}
|
||||
|
||||
Unit<DataBuffer>
|
||||
delegate(std::function<Unit<DataBuffer>(Unit<DataBuffer>)> cb) {
|
||||
return cb(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
DataBuffer _buf;
|
||||
};
|
||||
|
||||
template <typename DataBuffer>
|
||||
class VarInt {
|
||||
public:
|
||||
VarInt(DataBuffer db) : _buf(db) {}
|
||||
|
||||
static RuntimeTypes::Dynamic describe() {
|
||||
static auto singleton = RuntimeTypes::VarInt();
|
||||
return RuntimeTypes::Dynamic(singleton);
|
||||
}
|
||||
|
||||
Unit<DataBuffer> write(uint64_t val) {
|
||||
while (val >= 128) {
|
||||
_buf.write_byte(0x80 | (val & 0x7f));
|
||||
val >>= 7;
|
||||
}
|
||||
_buf.write_byte(uint8_t(val));
|
||||
return Unit<DataBuffer>(_buf);
|
||||
}
|
||||
|
||||
private:
|
||||
DataBuffer _buf;
|
||||
};
|
||||
|
||||
template <typename DataBuffer, typename T1, typename T2>
|
||||
class Pair {
|
||||
public:
|
||||
Pair(DataBuffer db) : _buf(db) {}
|
||||
|
||||
template <class U>
|
||||
T2 write(U val) {
|
||||
Unit<DataBuffer> second = T1(_buf).write(val);
|
||||
return second.template cast<T2>();
|
||||
}
|
||||
|
||||
T2 delegate(std::function<Unit<DataBuffer>(T1)> cb) {
|
||||
T1 first = T1(_buf);
|
||||
Unit<DataBuffer> second = cb(first);
|
||||
return second.template cast<T2>();
|
||||
}
|
||||
|
||||
private:
|
||||
DataBuffer _buf;
|
||||
};
|
||||
|
||||
template <typename DataBuffer, typename... Types>
|
||||
class Sum {
|
||||
private:
|
||||
template <size_t I, typename... Elements>
|
||||
struct Selector;
|
||||
|
||||
template <size_t I, typename Head, typename... Tail>
|
||||
struct Selector<I, Head, Tail...> {
|
||||
using type = typename std::conditional<I == 0, Head, typename Selector<I - 1, Tail...>::type>::type;
|
||||
};
|
||||
|
||||
template<size_t I>
|
||||
struct Selector<I> {
|
||||
using type = int;
|
||||
};
|
||||
|
||||
public:
|
||||
Sum(DataBuffer db) : _buf(db) {}
|
||||
|
||||
template <size_t I = 0>
|
||||
typename Selector<I, Types...>::type write() {
|
||||
Pair<DataBuffer, VarInt<DataBuffer>, typename Selector<I, Types...>::type> buf(_buf);
|
||||
return buf.write(I);
|
||||
}
|
||||
|
||||
template <size_t I = 0>
|
||||
Unit<DataBuffer> delegate(std::function<Unit<DataBuffer>(typename Selector<I, Types...>::type)> cb) {
|
||||
auto tail = write<I>();
|
||||
return cb(tail);
|
||||
}
|
||||
|
||||
private:
|
||||
DataBuffer _buf;
|
||||
};
|
||||
|
||||
template <typename DataBuffer, typename T>
|
||||
class ListContents {
|
||||
public:
|
||||
ListContents(DataBuffer db) : _buf(db) {}
|
||||
|
||||
ListContents<DataBuffer, T> delegate(std::function<Unit<DataBuffer>(T)> cb) {
|
||||
T head = T(_buf);
|
||||
Unit<DataBuffer> tail = cb(head);
|
||||
return tail.template cast<ListContents<DataBuffer, T>>();
|
||||
}
|
||||
|
||||
Unit<DataBuffer> finish() {
|
||||
return { _buf };
|
||||
}
|
||||
|
||||
private:
|
||||
DataBuffer _buf;
|
||||
};
|
||||
|
||||
template <typename DataBuffer, typename T>
|
||||
using List = Pair<DataBuffer, VarInt<DataBuffer>, ListContents<DataBuffer, T>>;
|
||||
|
||||
} // namespace StaticTypes
|
||||
} // namespace ObjectIntrospection
|
||||
|
||||
using namespace ObjectIntrospection;
|
||||
|
||||
)"
|
||||
|
@ -28,13 +28,7 @@
|
||||
#include "PaddingHunter.h"
|
||||
#include "SymbolService.h"
|
||||
|
||||
#define DEFINE_TYPE_VERSION(Type, size, version) \
|
||||
static_assert( \
|
||||
sizeof(Type) == size, \
|
||||
"Type `" #Type \
|
||||
"` has changed, please update the `size` parameter and increment the " \
|
||||
"`version` parameter of the corresponding invocation " \
|
||||
"of `DEFINE_TYPE_VERSION` in " __FILE__); \
|
||||
#define DEFINE_TYPE_VERSION(Type, size, version) \
|
||||
BOOST_CLASS_VERSION(Type, version)
|
||||
|
||||
DEFINE_TYPE_VERSION(PaddingInfo, 120, 3)
|
||||
|
@ -427,8 +427,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
auto innerTypeKind = drgn_type_kind(entry->second);
|
||||
if (innerTypeKind != DRGN_TYPE_FUNCTION) {
|
||||
node.pointer = next();
|
||||
if (innerTypeKind == DRGN_TYPE_VOID ||
|
||||
!shouldProcess(*node.pointer)) {
|
||||
if (innerTypeKind == DRGN_TYPE_VOID || next() == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -626,7 +625,7 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
|
||||
node.pointer = next();
|
||||
containerStats.length = *node.pointer ? 1 : 0;
|
||||
containerStats.capacity = 1;
|
||||
if (!shouldProcess(*node.pointer)) {
|
||||
if (next() == 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -3,7 +3,9 @@ definitions = '''
|
||||
int a;
|
||||
char b;
|
||||
long long c;
|
||||
int d;
|
||||
};
|
||||
struct EmptyStruct {};
|
||||
class SimpleClass {
|
||||
int a;
|
||||
char b;
|
||||
@ -21,13 +23,22 @@ definitions = '''
|
||||
param_types = ["const SimpleStruct&"]
|
||||
setup = "return {};"
|
||||
expect_json = '''[{
|
||||
"staticSize":16,
|
||||
"staticSize":24,
|
||||
"dynamicSize":0,
|
||||
"members":[
|
||||
{"name":"a", "staticSize":4, "dynamicSize":0},
|
||||
{"name":"b", "staticSize":1, "dynamicSize":0},
|
||||
{"name":"c", "staticSize":8, "dynamicSize":0}
|
||||
{"name":"c", "staticSize":8, "dynamicSize":0},
|
||||
{"name":"d", "staticSize":4, "dynamicSize":0}
|
||||
]}]'''
|
||||
[cases.empty_struct]
|
||||
param_types = ["const EmptyStruct&"]
|
||||
setup = "return {};"
|
||||
expect_json = '''[{
|
||||
"staticSize":1,
|
||||
"dynamicSize":0,
|
||||
"NOT": "members"
|
||||
}]'''
|
||||
[cases.class]
|
||||
param_types = ["const SimpleClass&"]
|
||||
setup = "return {};"
|
||||
|
@ -10,21 +10,26 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T, long unsigned int N>
|
||||
void getSizeType(const %1%<T, N> &container, size_t& returnArg);
|
||||
template<typename DB, typename T0, long unsigned int N>
|
||||
struct TypeHandler<DB, %1%<T0, N>> {
|
||||
using type = StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, N> &container,
|
||||
typename TypeHandler<DB, %1%<T0,N>>::type returnArg) {
|
||||
auto tail = returnArg.write(container.size());
|
||||
|
||||
for (auto & it: container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return TypeHandler<DB, T0>::getSizeType(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T, long unsigned int N>
|
||||
void getSizeType(const %1%<T,N> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
SAVE_SIZE(sizeof(container));
|
||||
|
||||
for (auto & it: container) {
|
||||
// undo the static size that has already been added per-element
|
||||
SAVE_SIZE(-sizeof(it));
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,31 @@ allocatorIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1% <T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0, T1> & container,
|
||||
typename TypeHandler<DB, %1% <T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container)
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
SAVE_DATA((uintptr_t)&container);
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with vector<bool>
|
||||
for (auto&& it: container) {
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,26 +10,23 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &t, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1% <T0>> {
|
||||
using type =
|
||||
StaticTypes::Pair<DB, StaticTypes::VarInt<DB>, StaticTypes::VarInt<DB>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0> & container,
|
||||
typename TypeHandler<DB, %1% <T0>>::type returnArg) {
|
||||
bool sso = ((uintptr_t)container.data() <
|
||||
(uintptr_t)(&container + sizeof(%1% <T0>))) &&
|
||||
((uintptr_t)container.data() >= (uintptr_t)&container);
|
||||
|
||||
return returnArg.write(container.capacity()).write(container.size());
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &t, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
SAVE_DATA((uintptr_t)t.capacity());
|
||||
SAVE_DATA((uintptr_t)t.size());
|
||||
|
||||
// Test for small string optimisation - whether the underlying string is
|
||||
// contained within the string object.
|
||||
SAVE_SIZE(
|
||||
(((uintptr_t)t.data() < (uintptr_t)(&t + sizeof(%1%<T>)))
|
||||
&&
|
||||
((uintptr_t)t.data() >= (uintptr_t)&t))
|
||||
? 0 : (t.capacity() * sizeof(T))
|
||||
);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,31 @@ allocatorIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container)
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return TypeHandler<DB, T0>::getSizeType(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
SAVE_DATA((uintptr_t)&container);
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with vector<bool>
|
||||
for (auto&& it: container) {
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,31 @@ allocatorIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1% <T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0, T1> & container,
|
||||
typename TypeHandler<DB, %1% <T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container)
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T, typename Allocator>
|
||||
void getSizeType(const %1%<T, Allocator> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
SAVE_DATA((uintptr_t)&container);
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with vector<bool>
|
||||
for (auto&& it: container) {
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -9,22 +9,33 @@ allocatorIndex = 3
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
void getSizeType(const %1%<Key,T,Compare,Allocator> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1, typename T2, typename T3>
|
||||
struct TypeHandler<DB, %1%<T0, T1, T2, T3>> {
|
||||
using type = StaticTypes::List<DB, StaticTypes::Pair<DB,
|
||||
typename TypeHandler<DB, T0>::type,
|
||||
typename TypeHandler<DB, T1>::type
|
||||
>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2, T3>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2, T3>>::type returnArg) {
|
||||
auto tail = returnArg.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.second, ret.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.first, ret);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
void getSizeType(const %1%<Key,T,Compare,Allocator> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<Key,T,Compare,Allocator>));
|
||||
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
|
||||
for (auto const& it : container)
|
||||
{
|
||||
getSizeType(it.first, returnArg);
|
||||
getSizeType(it.second, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,20 +10,27 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1%<T0>> {
|
||||
using type = StaticTypes::Sum<DB,
|
||||
StaticTypes::Unit<DB>,
|
||||
typename TypeHandler<DB, T0>::type
|
||||
>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0>& container,
|
||||
typename TypeHandler<DB, %1%<T0>>::type returnArg) {
|
||||
if (container) {
|
||||
return returnArg.template delegate<1>([&container](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(*container, ret);
|
||||
});
|
||||
} else {
|
||||
return returnArg.template delegate<0>(std::identity());
|
||||
}
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template <typename T>
|
||||
void getSizeType(const %1%<T>& s_ptr, size_t& returnArg) {
|
||||
if (s_ptr) {
|
||||
SAVE_SIZE(sizeof(%1%<T>) - sizeof(T));
|
||||
SAVE_DATA(true);
|
||||
getSizeType(*s_ptr, returnArg);
|
||||
} else {
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
SAVE_DATA(false);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,17 +10,25 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename P, typename Q>
|
||||
void getSizeType(const %1%<P,Q> &p, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
typename TypeHandler<DB, T0>::type,
|
||||
typename TypeHandler<DB, T1>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1> & container,
|
||||
typename TypeHandler<DB, %1%<T0, T1>>::type returnArg) {
|
||||
return OIInternal::getSizeType<DB>(
|
||||
container.second,
|
||||
returnArg.delegate([&container](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(container.first, ret);
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename P, typename Q>
|
||||
void getSizeType(const %1%<P,Q> &p, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<P,Q>) - sizeof(P) - sizeof(Q));
|
||||
|
||||
getSizeType(p.first, returnArg);
|
||||
getSizeType(p.second, returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,23 @@ underlyingContainerIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
typename TypeHandler<DB, T1>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0, T1> & container,
|
||||
typename TypeHandler<DB, %1% <T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container);
|
||||
|
||||
const T1 &underlyingContainer = get_container(container);
|
||||
return OIInternal::getSizeType<DB>(underlyingContainer, tail);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &containerAdapter, size_t& returnArg)
|
||||
{
|
||||
SAVE_DATA((uintptr_t)&containerAdapter);
|
||||
|
||||
// Only record the overhead of this container adapter - don't count the
|
||||
// underlying container as that will be taken care of in its own
|
||||
// getSizeType() function
|
||||
SAVE_SIZE(sizeof(%1%<T, Container>) - sizeof(Container));
|
||||
|
||||
const Container &container = get_container(containerAdapter);
|
||||
getSizeType(container, returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,23 @@ underlyingContainerIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
typename TypeHandler<DB, T1>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0, T1> & container,
|
||||
typename TypeHandler<DB, %1% <T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container);
|
||||
|
||||
const T1 &underlyingContainer = get_container(container);
|
||||
return OIInternal::getSizeType<DB>(underlyingContainer, tail);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &containerAdapter, size_t& returnArg)
|
||||
{
|
||||
SAVE_DATA((uintptr_t)&containerAdapter);
|
||||
|
||||
// Only record the overhead of this container adapter - don't count the
|
||||
// underlying container as that will be taken care of in its own
|
||||
// getSizeType() function
|
||||
SAVE_SIZE(sizeof(%1%<T, Container>) - sizeof(Container));
|
||||
|
||||
const Container &container = get_container(containerAdapter);
|
||||
getSizeType(container, returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,16 +10,22 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1%<T0>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
typename TypeHandler<DB, T0>::type
|
||||
>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0>& container,
|
||||
typename TypeHandler<DB, %1%<T0>>::type returnArg) {
|
||||
auto r0 = returnArg.write((uintptr_t)&(container.get()));
|
||||
return OIInternal::getSizeType<DB>(container.get(), r0);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &ref, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
SAVE_DATA((uintptr_t)&(ref.get()));
|
||||
getSizeType(ref.get(), returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,25 +10,34 @@ allocatorIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1% <T0>> {
|
||||
using type = StaticTypes::Pair<
|
||||
DB, StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Pair<
|
||||
DB, StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0> & container,
|
||||
typename TypeHandler<DB, %1% <T0>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container)
|
||||
.write(container.capacity())
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
SAVE_DATA((uintptr_t)&container);
|
||||
SAVE_DATA((uintptr_t)container.capacity());
|
||||
SAVE_DATA((uintptr_t)container.size());
|
||||
|
||||
SAVE_SIZE((container.capacity() - container.size()) * sizeof(T));
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with vector<bool>
|
||||
for (auto&& it: container) {
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyDecl %1%
|
||||
"""
|
||||
|
@ -10,8 +10,31 @@ allocatorIndex = 2
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename Key, typename Compare, typename Alloc>
|
||||
void getSizeType(const %1%<Key, Compare, Alloc> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1, typename T2>
|
||||
struct TypeHandler<DB, %1% <T0, T1, T2>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2>>::type returnArg) {
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<T0, T1, T2>::node_type);
|
||||
|
||||
auto tail = returnArg.write(nodeSize)
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
|
@ -10,22 +10,37 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1%<T0>> {
|
||||
using type = typename std::conditional<
|
||||
std::is_void<T0>::value,
|
||||
StaticTypes::Unit<DB>,
|
||||
StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Sum<DB,
|
||||
StaticTypes::Unit<DB>,
|
||||
typename TypeHandler<DB, T0>::type
|
||||
>>>::type;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0>& container,
|
||||
typename TypeHandler<DB, %1%<T0>>::type returnArg) {
|
||||
if constexpr (!std::is_void<T0>::value) {
|
||||
auto r0 = returnArg.write((uintptr_t)(container.get()));
|
||||
if (container && pointers.add((uintptr_t)(container.get()))) {
|
||||
return r0.template delegate<1>([&container](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(*(container.get()), ret);
|
||||
});
|
||||
} else {
|
||||
return r0.template delegate<0>(std::identity());
|
||||
}
|
||||
} else {
|
||||
return returnArg;
|
||||
}
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
|
||||
if constexpr (!std::is_void<T>::value) {
|
||||
SAVE_DATA((uintptr_t)(s_ptr.get()));
|
||||
|
||||
if (s_ptr && pointers.add((uintptr_t)(s_ptr.get()))) {
|
||||
getSizeType(*(s_ptr.get()), returnArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -8,20 +8,22 @@ underlyingContainerIndex = 4
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template <class T, class Compare, class Allocator, class GrowthPolicy, class Container>
|
||||
void getSizeType(const %1%<T,Compare, Allocator, GrowthPolicy, Container> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
struct TypeHandler<DB, %1%<T0, T1, T2, T3, T4>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
typename TypeHandler<DB, T4>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2, T3, T4>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2, T3, T4>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container);
|
||||
const T4 &underlyingContainer = container.get_container();
|
||||
return OIInternal::getSizeType<DB>(underlyingContainer, tail);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template <class T, class Compare, class Allocator, class GrowthPolicy, class Container>
|
||||
void getSizeType(const %1%<T,Compare, Allocator, GrowthPolicy, Container> &containerAdapter, size_t& returnArg)
|
||||
{
|
||||
SAVE_DATA((uintptr_t)&containerAdapter);
|
||||
|
||||
// Underlying container is grabbed by recursion, store only the exclusive size.
|
||||
SAVE_SIZE(sizeof(%1%<T,Compare, Allocator, GrowthPolicy, Container>) - sizeof(Container));
|
||||
|
||||
const Container &container = containerAdapter.get_container();
|
||||
getSizeType(container, returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,22 +10,23 @@ underlyingContainerIndex = 1
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0, T1>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
typename TypeHandler<DB, T1>::type>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1% <T0, T1> & container,
|
||||
typename TypeHandler<DB, %1% <T0, T1>>::type returnArg) {
|
||||
auto tail = returnArg.write((uintptr_t)&container);
|
||||
|
||||
const T1 &underlyingContainer = get_container(container);
|
||||
return OIInternal::getSizeType<DB>(underlyingContainer, tail);
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class T, class Container>
|
||||
void getSizeType(const %1%<T, Container> &containerAdapter, size_t& returnArg)
|
||||
{
|
||||
SAVE_DATA((uintptr_t)&containerAdapter);
|
||||
|
||||
// Only record the overhead of this container adapter - don't count the
|
||||
// underlying container as that will be taken care of in its own
|
||||
// getSizeType() function
|
||||
SAVE_SIZE(sizeof(%1%<T, Container>) - sizeof(Container));
|
||||
|
||||
const Container &container = get_container(containerAdapter);
|
||||
getSizeType(container, returnArg);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,26 +10,37 @@ allocatorIndex = 3
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class K, class T, class C, class A>
|
||||
void getSizeType(const %1%<K, T, C, A> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1, typename T2, typename T3>
|
||||
struct TypeHandler<DB, %1%<T0, T1, T2, T3>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, StaticTypes::Pair<DB,
|
||||
typename TypeHandler<DB, T0>::type,
|
||||
typename TypeHandler<DB, T1>::type
|
||||
>>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2, T3>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2, T3>>::type returnArg) {
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<T0, T1, T2, T3>::node_type);
|
||||
|
||||
auto tail = returnArg.write(nodeSize).write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (const auto& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.second, ret.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.first, ret);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class K, class T, class C, class A>
|
||||
void getSizeType(const %1%<K, T, C, A> &container, size_t& returnArg)
|
||||
{
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<K, T, C, A>::node_type);
|
||||
size_t numElems = container.size();
|
||||
|
||||
SAVE_SIZE(sizeof(%1%<K, T, C, A>) + (nodeSize * numElems));
|
||||
|
||||
SAVE_DATA((uintptr_t)nodeSize);
|
||||
SAVE_DATA((uintptr_t)numElems);
|
||||
|
||||
for (auto const& it : container)
|
||||
{
|
||||
getSizeType(it.first, returnArg);
|
||||
getSizeType(it.second, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,28 +10,41 @@ 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);
|
||||
template <typename DB, typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
struct TypeHandler<DB, %1%<T0, T1, T2, T3, T4>> {
|
||||
using type = StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, StaticTypes::Pair<DB,
|
||||
typename TypeHandler<DB, T0>::type,
|
||||
typename TypeHandler<DB, T1>::type
|
||||
>>>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2, T3, T4>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2, T3, T4>>::type returnArg) {
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<T0, T1, T2, T3, T4>::node_type);
|
||||
|
||||
auto tail = returnArg.write(nodeSize)
|
||||
.write(container.bucket_count())
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (const auto& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.second, ret.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it.first, ret);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -6,29 +6,36 @@ ns = ["namespace std"]
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<class... Types>
|
||||
void getSizeType(const %1%<Types...> &container, size_t& returnArg);
|
||||
template <typename DB, typename... Types>
|
||||
struct TypeHandler<DB, %1%<Types...>> {
|
||||
using type = StaticTypes::Sum<DB, typename TypeHandler<DB, Types>::type..., StaticTypes::Unit<DB>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<Types...>& container,
|
||||
typename TypeHandler<DB, %1%<Types...>>::type returnArg) {
|
||||
return getSizeTypeRecursive(container, returnArg);
|
||||
}
|
||||
|
||||
private:
|
||||
template <size_t I = 0>
|
||||
static StaticTypes::Unit<DB> getSizeTypeRecursive(
|
||||
const %1%<Types...>& container,
|
||||
typename TypeHandler<DB, %1%<Types...>>::type returnArg) {
|
||||
if constexpr (I < sizeof...(Types)) {
|
||||
if (I == container.index()) {
|
||||
return returnArg.template delegate<I>([&container](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(std::get<I>(container), ret);
|
||||
});
|
||||
} else {
|
||||
return getSizeTypeRecursive<I+1>(container, returnArg);
|
||||
}
|
||||
} else {
|
||||
return returnArg.template delegate<sizeof...(Types)>(std::identity());
|
||||
}
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<class... Types>
|
||||
void getSizeType(const %1%<Types...> &container, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<Types...>));
|
||||
SAVE_DATA(container.index());
|
||||
|
||||
// This check should be `container.valueless_by_exception()` but it doesn't
|
||||
// work with the variable sized integers used in `std::variant`. For fewer
|
||||
// than 256 options it uses a `uint8_t` index but checks against -1 of
|
||||
// `uintptr_t`. Manually check for any out of bounds indices as a workaround.
|
||||
if (container.index() >= sizeof...(Types)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::visit([&returnArg](auto &&arg) {
|
||||
// Account for inline contents
|
||||
SAVE_SIZE(-sizeof(arg));
|
||||
getSizeType(arg, returnArg);
|
||||
}, container);
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,18 +10,22 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &t, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1%<T0>> {
|
||||
using type = StaticTypes::VarInt;
|
||||
};
|
||||
|
||||
template<typename T0>
|
||||
Unit getSizeType(const %1%<T0> &t, TypeHandler<%1%<T0>> returnArg);
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &t, size_t& returnArg)
|
||||
template<typename T0>
|
||||
Unit getSizeType(const %1%<T0> &t, TypeHandler<%1%<T0>> returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
SAVE_SIZE(sizeof(%1%<T0>));
|
||||
|
||||
SAVE_DATA((uintptr_t)t.capacity());
|
||||
SAVE_DATA((uintptr_t)t.size());
|
||||
return returnArg.write(t.capacity());
|
||||
|
||||
// Test for small string optimisation - whether the underlying string is
|
||||
// contained within the string object.
|
||||
|
@ -10,22 +10,37 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T, class Deleter>
|
||||
void getSizeType(const %1%<T,Deleter> &s_ptr, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1>
|
||||
struct TypeHandler<DB, %1%<T0,T1>> {
|
||||
using type = typename std::conditional<
|
||||
std::is_void<T0>::value,
|
||||
StaticTypes::Unit<DB>,
|
||||
StaticTypes::Pair<DB,
|
||||
StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Sum<DB,
|
||||
StaticTypes::Unit<DB>,
|
||||
typename TypeHandler<DB, T0>::type
|
||||
>>>::type;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0,T1>& container,
|
||||
typename TypeHandler<DB, %1%<T0,T1>>::type returnArg) {
|
||||
if constexpr (!std::is_void<T0>::value) {
|
||||
auto r0 = returnArg.write((uintptr_t)(container.get()));
|
||||
if (container && pointers.add((uintptr_t)(container.get()))) {
|
||||
return r0.template delegate<1>([&container](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(*(container.get()), ret);
|
||||
});
|
||||
} else {
|
||||
return r0.template delegate<0>(std::identity());
|
||||
}
|
||||
} else {
|
||||
return returnArg;
|
||||
}
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template<typename T, class Deleter>
|
||||
void getSizeType(const %1%<T,Deleter> &s_ptr, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T,Deleter>));
|
||||
|
||||
if constexpr (!std::is_void<T>::value) {
|
||||
SAVE_DATA((uintptr_t)(s_ptr.get()));
|
||||
|
||||
if (s_ptr && pointers.add((uintptr_t)(s_ptr.get()))) {
|
||||
getSizeType(*(s_ptr.get()), returnArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -10,26 +10,36 @@ allocatorIndex = 3
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template <typename Key, typename Hasher, typename KeyEqual, typename Alloc>
|
||||
void getSizeType(const %1%<Key, Hasher, KeyEqual, Alloc> &container, size_t& returnArg);
|
||||
template <typename DB, typename T0, typename T1, typename T2, typename T3>
|
||||
struct TypeHandler<DB, %1%<T0, T1, T2, T3>> {
|
||||
using type = StaticTypes::Pair<
|
||||
DB, StaticTypes::VarInt<DB>,
|
||||
StaticTypes::Pair<
|
||||
DB, StaticTypes::VarInt<DB>,
|
||||
StaticTypes::List<DB, typename TypeHandler<DB, T0>::type>>>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0, T1, T2, T3>& container,
|
||||
typename TypeHandler<DB, %1%<T0, T1, T2, T3>>::type returnArg) {
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<T0, T1, T2, T3>::node_type);
|
||||
|
||||
auto tail = returnArg.write(nodeSize)
|
||||
.write(container.bucket_count())
|
||||
.write(container.size());
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with
|
||||
// vector<bool>
|
||||
for (auto&& it : container) {
|
||||
tail = tail.delegate([&it](auto ret) {
|
||||
return OIInternal::getSizeType<DB>(it, ret);
|
||||
});
|
||||
}
|
||||
|
||||
return tail.finish();
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
func = """
|
||||
template <typename Key, typename Hasher, typename KeyEqual, typename Alloc>
|
||||
void getSizeType(const %1%<Key, Hasher, KeyEqual, Alloc> &container, size_t& returnArg)
|
||||
{
|
||||
constexpr size_t nodeSize = sizeof(typename %1%<Key, Hasher, KeyEqual, Alloc>::node_type);
|
||||
size_t bucketCount = container.bucket_count();
|
||||
size_t numElems = container.size();
|
||||
SAVE_SIZE(sizeof(%1%<Key, Hasher, KeyEqual, Alloc>) + (numElems * nodeSize) + (bucketCount * sizeof(uintptr_t)));
|
||||
|
||||
SAVE_DATA((uintptr_t)nodeSize);
|
||||
SAVE_DATA((uintptr_t)bucketCount);
|
||||
SAVE_DATA((uintptr_t)numElems);
|
||||
|
||||
// The double ampersand is needed otherwise this loop doesn't work with vector<bool>
|
||||
for (auto&& it: container) {
|
||||
getSizeType(it, returnArg);
|
||||
}
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
@ -8,15 +8,19 @@ replaceTemplateParamIndex = []
|
||||
|
||||
[codegen]
|
||||
decl = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg);
|
||||
template <typename DB, typename T0>
|
||||
struct TypeHandler<DB, %1%<T0>> {
|
||||
using type = StaticTypes::Unit<DB>;
|
||||
|
||||
static StaticTypes::Unit<DB> getSizeType(
|
||||
const %1%<T0>& container,
|
||||
typename TypeHandler<DB, %1%<T0>>::type returnArg) {
|
||||
return returnArg;
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
||||
# Weak pointers do not have ownership, so let's not follow them (for now)
|
||||
func = """
|
||||
template<typename T>
|
||||
void getSizeType(const %1%<T> &s_ptr, size_t& returnArg)
|
||||
{
|
||||
SAVE_SIZE(sizeof(%1%<T>));
|
||||
}
|
||||
// DummyFunc %1%
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user