#pragma once #include #include #include #include #include #include #include using UID = std::size_t; constexpr UID UID_INVALID = std::numeric_limits::max(); class TargetType { public: struct Field { static constexpr std::size_t FLAG_DANGEROUS = 1; std::size_t offset; std::size_t size; std::size_t flags; }; private: static constexpr std::size_t FLAG_MAIN_VARIANT = 1; static constexpr std::size_t FLAG_FIELDS = 2; UID m_uid; std::size_t m_flags; tree m_main_variant; // Fields are identified by their offsets std::map m_fields; public: TargetType(const TargetType& other) = default; TargetType& operator=(const TargetType& other) = default; TargetType(TargetType&& other) = default; TargetType& operator=(TargetType&& other) = default; TargetType(tree t); // Does NOT fetch fields ~TargetType(); bool valid() const; bool fields() const; std::string name() const; const Field* field(std::size_t off, bool exact = true) const; UID uid() const; static void add(tree t); static std::size_t count(); static const TargetType* find(tree t); // O(n) static const TargetType* find(UID uid); // O(1) static bool reference(tree ref, UID& target, std::size_t& offset); private: friend void on_finish_type(void*, void*); bool fetch_fields(bool redo = false); static TargetType* find_mutable(tree t); }; bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* bitfield); /* Stage 0 offsetof separators are function calls, such as: SPSLR_PINPOINT_STAGE0_SEPARATOR(target, member offset) */ tree make_stage0_ast_separator(UID target, std::size_t offset); gimple* make_stage0_gimple_separator(tree lhs, UID target, std::size_t offset); bool is_stage0_separator(gimple* stmt, UID& target, std::size_t& offset); struct DataPin { struct Component { std::size_t offset; std::size_t level; UID target; }; std::string symbol; std::list components; }; const std::list& dpins(); void on_register_attributes(void* plugin_data, void* user_data); void on_finish_type(void* plugin_data, void* user_data); void on_preserve_component_ref(void* plugin_data, void* user_data); void on_finish_decl(void* plugin_data, void* user_data); struct separate_offset_pass : gimple_opt_pass { separate_offset_pass(gcc::context* ctxt); unsigned int execute(function* fn) override; };