diff --git a/dev.oid.toml b/dev.oid.toml index 77a05c5..ecfe35a 100644 --- a/dev.oid.toml +++ b/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"] diff --git a/src/ContainerInfo.cpp b/src/ContainerInfo.cpp index 673e14e..548523e 100644 --- a/src/ContainerInfo.cpp +++ b/src/ContainerInfo.cpp @@ -154,6 +154,15 @@ std::unique_ptr ContainerInfo::loadFromFile( return nullptr; } + // std::string outputType; + // if (std::optional str = + // (*codegen)["outputType"].value()) { + // func = std::move(*str); + // } else { + // LOG(ERROR) << "`codegen.outputType` is a required field"; + // return nullptr; + // } + return std::unique_ptr(new ContainerInfo{ std::move(typeName), std::move(matcher), @@ -166,8 +175,9 @@ std::unique_ptr ContainerInfo::loadFromFile( underlyingContainerIndex, { - std::move(decl), - std::move(func), + .outputType = "", + .decl = std::move(decl), + .func = std::move(func), }, }); } diff --git a/src/ContainerInfo.h b/src/ContainerInfo.h index 3294dbc..870e58d 100644 --- a/src/ContainerInfo.h +++ b/src/ContainerInfo.h @@ -28,6 +28,7 @@ const char* containerTypeEnumToStr(ContainerTypeEnum ty); struct ContainerInfo { struct Codegen { + std::string outputType; std::string decl; std::string func; }; diff --git a/src/FuncGen.cpp b/src/FuncGen.cpp index f4f7257..2a54f85 100644 --- a/src/FuncGen.cpp +++ b/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 +struct TypeHandler { + private: + static auto choose_type() { + if constexpr(std::is_pointer_v) { + return std::type_identity, + StaticTypes::Sum, + typename TypeHandler>::type + >>>(); + } else { + return std::type_identity>(); + } + } + + public: + using type = typename decltype(choose_type())::type; + + static StaticTypes::Unit getSizeType( + const T& t, + typename TypeHandler::type returnArg) { + if constexpr(std::is_pointer_v) { + 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>::value) { + return TypeHandler>::getSizeType(*t, ret); + } else { + return ret; + } + }); + } else { + return r0.template delegate<0>(std::identity()); + } + } else { + return returnArg; + } + } +}; + +template +class TypeHandler { + public: + using type = StaticTypes::Unit; +}; + )"); +} + 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(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::type; + DataBufferType db = DataBuffer::DataSegment(dataSegOffset); + + StaticTypes::Unit out = OIInternal::getSizeType(t, db); + + StaticTypes::Unit final = out.template cast, + StaticTypes::VarInt + >>() + .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(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{}(rawType); - testCode.append(fmt.str()); -} - bool FuncGen::DeclareGetSizeFuncs(std::string& testCode, const ContainerInfoRefSet& containerInfo, bool chaseRawPointers) { + testCode.append(R"(template +StaticTypes::Unit +getSizeType(const T &t, typename TypeHandler::type returnArg) { + JLOG("obj @"); + JLOGPTR(&t); + return TypeHandler::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>>>\n"); - } else { - testCode.append("template\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\n"); - } else { - testCode.append("template\n"); - } - - testCode.append(R"( - void getSizeType(const T &t, size_t& returnArg) { - JLOG("obj @"); - JLOGPTR(&t); - SAVE_SIZE(sizeof(T)); - } - )"); - return true; } diff --git a/src/FuncGen.h b/src/FuncGen.h index de77d46..ff893b2 100644 --- a/src/FuncGen.h +++ b/src/FuncGen.h @@ -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); }; diff --git a/src/OICodeGen.cpp b/src/OICodeGen.cpp index a8d7cea..bea3042 100644 --- a/src/OICodeGen.cpp +++ b/src/OICodeGen.cpp @@ -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(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(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 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::type") % + typeName % memberName) + .str(); + if (i != members.size() - 1) { + out += ", "; + } + } + out += std::string(count, '>'); + + if (!out.empty()) { + return out; + } + return "StaticTypes::Unit"; +} + 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 +struct TypeHandler { + using type = %3%; + + static StaticTypes::Unit %2%( + const %1% &t, + typename TypeHandler::type returnArg) { +)") % typeName % + funcName % typeStaticType) + .str(); std::unordered_map 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 \n"; + code += std::string("StaticTypes::Unit 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(&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 - 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); } diff --git a/src/OICodeGen.h b/src/OICodeGen.h index 1c16184..62bd524 100644 --- a/src/OICodeGen.h +++ b/src/OICodeGen.h @@ -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 getDrgnTypeSize(drgn_type* type); diff --git a/src/OITraceCode.cpp b/src/OITraceCode.cpp index 98a3fca..a82f143 100644 --- a/src/OITraceCode.cpp +++ b/src/OITraceCode.cpp @@ -14,6 +14,9 @@ R"( #include #include +#include +#include +#include #include // 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, + std::reference_wrapper>; + +} // namespace RuntimeTypes + +namespace StaticTypes { + +template +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 + T cast() { + return T(_buf); + } + + Unit + delegate(std::function(Unit)> cb) { + return cb(*this); + } + + private: + DataBuffer _buf; +}; + +template +class VarInt { + public: + VarInt(DataBuffer db) : _buf(db) {} + + static RuntimeTypes::Dynamic describe() { + static auto singleton = RuntimeTypes::VarInt(); + return RuntimeTypes::Dynamic(singleton); + } + + Unit write(uint64_t val) { + while (val >= 128) { + _buf.write_byte(0x80 | (val & 0x7f)); + val >>= 7; + } + _buf.write_byte(uint8_t(val)); + return Unit(_buf); + } + + private: + DataBuffer _buf; +}; + +template +class Pair { + public: + Pair(DataBuffer db) : _buf(db) {} + + template + T2 write(U val) { + Unit second = T1(_buf).write(val); + return second.template cast(); + } + + T2 delegate(std::function(T1)> cb) { + T1 first = T1(_buf); + Unit second = cb(first); + return second.template cast(); + } + + private: + DataBuffer _buf; +}; + +template +class Sum { + private: + template + struct Selector; + + template + struct Selector { + using type = typename std::conditional::type>::type; + }; + + template + struct Selector { + using type = int; + }; + + public: + Sum(DataBuffer db) : _buf(db) {} + + template + typename Selector::type write() { + Pair, typename Selector::type> buf(_buf); + return buf.write(I); + } + + template + Unit delegate(std::function(typename Selector::type)> cb) { + auto tail = write(); + return cb(tail); + } + + private: + DataBuffer _buf; +}; + +template +class ListContents { + public: + ListContents(DataBuffer db) : _buf(db) {} + + ListContents delegate(std::function(T)> cb) { + T head = T(_buf); + Unit tail = cb(head); + return tail.template cast>(); + } + + Unit finish() { + return { _buf }; + } + + private: + DataBuffer _buf; +}; + +template +using List = Pair, ListContents>; + +} // namespace StaticTypes +} // namespace ObjectIntrospection + +using namespace ObjectIntrospection; + )" diff --git a/src/Serialize.h b/src/Serialize.h index e2056e0..7309ff0 100644 --- a/src/Serialize.h +++ b/src/Serialize.h @@ -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) diff --git a/src/TreeBuilder.cpp b/src/TreeBuilder.cpp index 74040c4..15b639f 100644 --- a/src/TreeBuilder.cpp +++ b/src/TreeBuilder.cpp @@ -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; diff --git a/test/integration/simple.toml b/test/integration/simple.toml index 2fe4405..63c838c 100644 --- a/test/integration/simple.toml +++ b/test/integration/simple.toml @@ -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 {};" diff --git a/types/array_type.toml b/types/array_type.toml index 6d91291..4d38a90 100644 --- a/types/array_type.toml +++ b/types/array_type.toml @@ -10,21 +10,26 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::List::type>; + + static StaticTypes::Unit getSizeType( + const %1% &container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write(container.size()); + + for (auto & it: container) { + tail = tail.delegate([&it](auto ret) { + return TypeHandler::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &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% """ diff --git a/types/cxx11_list_type.toml b/types/cxx11_list_type.toml index 2de1520..e78138d 100644 --- a/types/cxx11_list_type.toml +++ b/types/cxx11_list_type.toml @@ -10,22 +10,31 @@ allocatorIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::List::type>>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::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 + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - SAVE_DATA((uintptr_t)&container); - SAVE_DATA((uintptr_t)container.size()); - - // The double ampersand is needed otherwise this loop doesn't work with vector - for (auto&& it: container) { - getSizeType(it, returnArg); - } -} +// DummyFunc %1% """ diff --git a/types/cxx11_string_type.toml b/types/cxx11_string_type.toml index 8af41de..8536dd3 100644 --- a/types/cxx11_string_type.toml +++ b/types/cxx11_string_type.toml @@ -10,26 +10,23 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &t, size_t& returnArg); +template +struct TypeHandler> { + using type = + StaticTypes::Pair, StaticTypes::VarInt>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + bool sso = ((uintptr_t)container.data() < + (uintptr_t)(&container + sizeof(%1% ))) && + ((uintptr_t)container.data() >= (uintptr_t)&container); + + return returnArg.write(container.capacity()).write(container.size()); + } +}; """ func = """ -template -void getSizeType(const %1% &t, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - 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%))) - && - ((uintptr_t)t.data() >= (uintptr_t)&t)) - ? 0 : (t.capacity() * sizeof(T)) - ); -} +// DummyFunc %1% """ diff --git a/types/deque_list_type.toml b/types/deque_list_type.toml index 7691e7f..3870b6d 100644 --- a/types/deque_list_type.toml +++ b/types/deque_list_type.toml @@ -10,22 +10,31 @@ allocatorIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::List::type>>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::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 + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return TypeHandler::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - SAVE_DATA((uintptr_t)&container); - SAVE_DATA((uintptr_t)container.size()); - - // The double ampersand is needed otherwise this loop doesn't work with vector - for (auto&& it: container) { - getSizeType(it, returnArg); - } -} +// DummyFunc %1% """ diff --git a/types/list_type.toml b/types/list_type.toml index ef7df87..792be77 100644 --- a/types/list_type.toml +++ b/types/list_type.toml @@ -10,22 +10,31 @@ allocatorIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::List::type>>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::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 + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - SAVE_DATA((uintptr_t)&container); - SAVE_DATA((uintptr_t)container.size()); - - // The double ampersand is needed otherwise this loop doesn't work with vector - for (auto&& it: container) { - getSizeType(it, returnArg); - } -} +// DummyFunc %1% """ diff --git a/types/multi_map_type.toml b/types/multi_map_type.toml index b0d7cd2..46e1a0b 100644 --- a/types/multi_map_type.toml +++ b/types/multi_map_type.toml @@ -9,22 +9,33 @@ allocatorIndex = 3 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::List::type, + typename TypeHandler::type + >>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write(container.size()); + + // The double ampersand is needed otherwise this loop doesn't work with + // vector + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.second, ret.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.first, ret); + })); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - SAVE_DATA((uintptr_t)container.size()); - - for (auto const& it : container) - { - getSizeType(it.first, returnArg); - getSizeType(it.second, returnArg); - } -} +// DummyFunc %1% """ diff --git a/types/optional_type.toml b/types/optional_type.toml index 5c3547a..ed95685 100644 --- a/types/optional_type.toml +++ b/types/optional_type.toml @@ -10,20 +10,27 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Sum, + typename TypeHandler::type + >; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + if (container) { + return returnArg.template delegate<1>([&container](auto ret) { + return OIInternal::getSizeType(*container, ret); + }); + } else { + return returnArg.template delegate<0>(std::identity()); + } + } +}; """ func = """ -template -void getSizeType(const %1%& s_ptr, size_t& returnArg) { - if (s_ptr) { - SAVE_SIZE(sizeof(%1%) - sizeof(T)); - SAVE_DATA(true); - getSizeType(*s_ptr, returnArg); - } else { - SAVE_SIZE(sizeof(%1%)); - SAVE_DATA(false); - } -} +// DummyFunc %1% """ diff --git a/types/pair_type.toml b/types/pair_type.toml index 6f106ee..c1b9357 100644 --- a/types/pair_type.toml +++ b/types/pair_type.toml @@ -10,17 +10,25 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &p, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair::type, + typename TypeHandler::type>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + return OIInternal::getSizeType( + container.second, + returnArg.delegate([&container](auto ret) { + return OIInternal::getSizeType(container.first, ret); + }) + ); + } +}; """ func = """ -template -void getSizeType(const %1% &p, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%) - sizeof(P) - sizeof(Q)); - - getSizeType(p.first, returnArg); - getSizeType(p.second, returnArg); -} +// DummyFunc %1% """ diff --git a/types/priority_queue_container_adapter_type.toml b/types/priority_queue_container_adapter_type.toml index 82520aa..7047297 100644 --- a/types/priority_queue_container_adapter_type.toml +++ b/types/priority_queue_container_adapter_type.toml @@ -10,22 +10,23 @@ underlyingContainerIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + typename TypeHandler::type>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write((uintptr_t)&container); + + const T1 &underlyingContainer = get_container(container); + return OIInternal::getSizeType(underlyingContainer, tail); + } +}; """ func = """ -template -void getSizeType(const %1% &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%) - sizeof(Container)); - - const Container &container = get_container(containerAdapter); - getSizeType(container, returnArg); -} +// DummyFunc %1% """ diff --git a/types/queue_container_adapter_type.toml b/types/queue_container_adapter_type.toml index 63e794f..951ccfa 100644 --- a/types/queue_container_adapter_type.toml +++ b/types/queue_container_adapter_type.toml @@ -10,22 +10,23 @@ underlyingContainerIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + typename TypeHandler::type>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write((uintptr_t)&container); + + const T1 &underlyingContainer = get_container(container); + return OIInternal::getSizeType(underlyingContainer, tail); + } +}; """ func = """ -template -void getSizeType(const %1% &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%) - sizeof(Container)); - - const Container &container = get_container(containerAdapter); - getSizeType(container, returnArg); -} +// DummyFunc %1% """ diff --git a/types/ref_wrapper_type.toml b/types/ref_wrapper_type.toml index 2ef6026..70321db 100644 --- a/types/ref_wrapper_type.toml +++ b/types/ref_wrapper_type.toml @@ -10,16 +10,22 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + typename TypeHandler::type + >; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + auto r0 = returnArg.write((uintptr_t)&(container.get())); + return OIInternal::getSizeType(container.get(), r0); + } +}; """ func = """ -template -void getSizeType(const %1% &ref, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - SAVE_DATA((uintptr_t)&(ref.get())); - getSizeType(ref.get(), returnArg); -} +// DummyFunc %1% """ diff --git a/types/seq_type.toml b/types/seq_type.toml index cc6646a..0bd3ee1 100644 --- a/types/seq_type.toml +++ b/types/seq_type.toml @@ -10,25 +10,34 @@ allocatorIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair< + DB, StaticTypes::VarInt, + StaticTypes::Pair< + DB, StaticTypes::VarInt, + StaticTypes::List::type>>>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::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 + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - 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 - for (auto&& it: container) { - getSizeType(it, returnArg); - } -} +// DummyDecl %1% """ diff --git a/types/set_type.toml b/types/set_type.toml index 9b8e434..dbaff93 100644 --- a/types/set_type.toml +++ b/types/set_type.toml @@ -10,8 +10,31 @@ allocatorIndex = 2 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::List::type>>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + constexpr size_t nodeSize = sizeof(typename %1%::node_type); + + auto tail = returnArg.write(nodeSize) + .write(container.size()); + + // The double ampersand is needed otherwise this loop doesn't work with + // vector + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ diff --git a/types/shrd_ptr_type.toml b/types/shrd_ptr_type.toml index 85437fa..6f00ace 100644 --- a/types/shrd_ptr_type.toml +++ b/types/shrd_ptr_type.toml @@ -10,22 +10,37 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg); +template +struct TypeHandler> { + using type = typename std::conditional< + std::is_void::value, + StaticTypes::Unit, + StaticTypes::Pair, + StaticTypes::Sum, + typename TypeHandler::type + >>>::type; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + if constexpr (!std::is_void::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(*(container.get()), ret); + }); + } else { + return r0.template delegate<0>(std::identity()); + } + } else { + return returnArg; + } + } +}; """ func = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - if constexpr (!std::is_void::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% """ diff --git a/types/sorted_vec_set_type.toml b/types/sorted_vec_set_type.toml index 2f013ac..c1e6d8b 100644 --- a/types/sorted_vec_set_type.toml +++ b/types/sorted_vec_set_type.toml @@ -8,20 +8,22 @@ underlyingContainerIndex = 4 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + typename TypeHandler::type>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write((uintptr_t)&container); + const T4 &underlyingContainer = container.get_container(); + return OIInternal::getSizeType(underlyingContainer, tail); + } +}; """ func = """ -template -void getSizeType(const %1% &containerAdapter, size_t& returnArg) -{ - SAVE_DATA((uintptr_t)&containerAdapter); - - // Underlying container is grabbed by recursion, store only the exclusive size. - SAVE_SIZE(sizeof(%1%) - sizeof(Container)); - - const Container &container = containerAdapter.get_container(); - getSizeType(container, returnArg); -} +// DummyFunc %1% """ diff --git a/types/stack_container_adapter_type.toml b/types/stack_container_adapter_type.toml index 77a8fdd..4a2fbbc 100644 --- a/types/stack_container_adapter_type.toml +++ b/types/stack_container_adapter_type.toml @@ -10,22 +10,23 @@ underlyingContainerIndex = 1 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + typename TypeHandler::type>; + + static StaticTypes::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write((uintptr_t)&container); + + const T1 &underlyingContainer = get_container(container); + return OIInternal::getSizeType(underlyingContainer, tail); + } +}; """ func = """ -template -void getSizeType(const %1% &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%) - sizeof(Container)); - - const Container &container = get_container(containerAdapter); - getSizeType(container, returnArg); -} +// DummyFunc %1% """ diff --git a/types/std_map_type.toml b/types/std_map_type.toml index 4ab538b..3afb741 100644 --- a/types/std_map_type.toml +++ b/types/std_map_type.toml @@ -10,26 +10,37 @@ allocatorIndex = 3 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::List::type, + typename TypeHandler::type + >>>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + constexpr size_t nodeSize = sizeof(typename %1%::node_type); + + auto tail = returnArg.write(nodeSize).write(container.size()); + + // The double ampersand is needed otherwise this loop doesn't work with + // vector + for (const auto& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.second, ret.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.first, ret); + })); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - constexpr size_t nodeSize = sizeof(typename %1%::node_type); - size_t numElems = container.size(); - - SAVE_SIZE(sizeof(%1%) + (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% """ diff --git a/types/std_unordered_map_type.toml b/types/std_unordered_map_type.toml index cf9cb10..7c611ce 100644 --- a/types/std_unordered_map_type.toml +++ b/types/std_unordered_map_type.toml @@ -10,28 +10,41 @@ allocatorIndex = 4 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair, + StaticTypes::Pair, + StaticTypes::List::type, + typename TypeHandler::type + >>>>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + constexpr size_t nodeSize = sizeof(typename %1%::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 + for (const auto& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.second, ret.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.first, ret); + })); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - constexpr size_t nodeSize = sizeof(typename %1%::node_type); - size_t bucketCount = container.bucket_count(); - size_t numElems = container.size(); - - SAVE_SIZE(sizeof(%1%) + (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% """ diff --git a/types/std_variant.toml b/types/std_variant.toml index df157cd..1132e44 100644 --- a/types/std_variant.toml +++ b/types/std_variant.toml @@ -6,29 +6,36 @@ ns = ["namespace std"] [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Sum::type..., StaticTypes::Unit>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + return getSizeTypeRecursive(container, returnArg); + } + + private: + template + static StaticTypes::Unit getSizeTypeRecursive( + const %1%& container, + typename TypeHandler>::type returnArg) { + if constexpr (I < sizeof...(Types)) { + if (I == container.index()) { + return returnArg.template delegate([&container](auto ret) { + return OIInternal::getSizeType(std::get(container), ret); + }); + } else { + return getSizeTypeRecursive(container, returnArg); + } + } else { + return returnArg.template delegate(std::identity()); + } + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - 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% """ diff --git a/types/string_type.toml b/types/string_type.toml index fb48c1b..24f39d5 100644 --- a/types/string_type.toml +++ b/types/string_type.toml @@ -10,18 +10,22 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &t, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::VarInt; +}; + +template +Unit getSizeType(const %1% &t, TypeHandler<%1%> returnArg); """ func = """ -template -void getSizeType(const %1% &t, size_t& returnArg) +template +Unit getSizeType(const %1% &t, TypeHandler<%1%> returnArg) { - SAVE_SIZE(sizeof(%1%)); + SAVE_SIZE(sizeof(%1%)); - 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. diff --git a/types/uniq_ptr_type.toml b/types/uniq_ptr_type.toml index 304f799..d02eeae 100644 --- a/types/uniq_ptr_type.toml +++ b/types/uniq_ptr_type.toml @@ -10,22 +10,37 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg); +template +struct TypeHandler> { + using type = typename std::conditional< + std::is_void::value, + StaticTypes::Unit, + StaticTypes::Pair, + StaticTypes::Sum, + typename TypeHandler::type + >>>::type; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + if constexpr (!std::is_void::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(*(container.get()), ret); + }); + } else { + return r0.template delegate<0>(std::identity()); + } + } else { + return returnArg; + } + } +}; """ func = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); - - if constexpr (!std::is_void::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% """ diff --git a/types/unordered_set_type.toml b/types/unordered_set_type.toml index 10f2044..4536c21 100644 --- a/types/unordered_set_type.toml +++ b/types/unordered_set_type.toml @@ -10,26 +10,36 @@ allocatorIndex = 3 [codegen] decl = """ -template -void getSizeType(const %1% &container, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Pair< + DB, StaticTypes::VarInt, + StaticTypes::Pair< + DB, StaticTypes::VarInt, + StaticTypes::List::type>>>; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + constexpr size_t nodeSize = sizeof(typename %1%::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 + for (auto&& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; """ func = """ -template -void getSizeType(const %1% &container, size_t& returnArg) -{ - constexpr size_t nodeSize = sizeof(typename %1%::node_type); - size_t bucketCount = container.bucket_count(); - size_t numElems = container.size(); - SAVE_SIZE(sizeof(%1%) + (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 - for (auto&& it: container) { - getSizeType(it, returnArg); - } -} +// DummyFunc %1% """ diff --git a/types/weak_ptr_type.toml b/types/weak_ptr_type.toml index 246f724..cb06517 100644 --- a/types/weak_ptr_type.toml +++ b/types/weak_ptr_type.toml @@ -8,15 +8,19 @@ replaceTemplateParamIndex = [] [codegen] decl = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg); +template +struct TypeHandler> { + using type = StaticTypes::Unit; + + static StaticTypes::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + return returnArg; + } +}; """ # Weak pointers do not have ownership, so let's not follow them (for now) func = """ -template -void getSizeType(const %1% &s_ptr, size_t& returnArg) -{ - SAVE_SIZE(sizeof(%1%)); -} +// DummyFunc %1% """