diff --git a/finalize/accumulation.cpp b/finalize/accumulation.cpp index 4e263b6..38dab43 100644 --- a/finalize/accumulation.cpp +++ b/finalize/accumulation.cpp @@ -11,11 +11,28 @@ static std::size_t next_global_target_uid = 0; std::unordered_map targets; std::unordered_map units; -// NOTE -> Field comparison for this matter can literally just compare field attributes // Two different types with exactly same field structure will not cause problems if simply randomized together - static bool global_target_field_cmp(const TARGET& a, const TARGET& b) { - // TODO + if (a.fields.size() != b.fields.size()) + return false; + + auto ita = a.fields.begin(); + auto itb = b.fields.begin(); + + for (; ita != a.fields.end() && itb != b.fields.end(); ++ita, ++itb) { + const FIELD& fa = ita->second; + const FIELD& fb = itb->second; + + if (fa.offset != fb.offset) + return false; + if (fa.size != fb.size) + return false; + if (fa.alignment != fb.alignment) + return false; + if (fa.flags != fb.flags) + return false; + } + return true; } diff --git a/pinpoint/final/on_finish_unit.cpp b/pinpoint/final/on_finish_unit.cpp index d04c05b..6d632a7 100644 --- a/pinpoint/final/on_finish_unit.cpp +++ b/pinpoint/final/on_finish_unit.cpp @@ -165,8 +165,7 @@ void on_finish_unit(void* plugin_data, void* user_data) { for (const auto& [off, field] : target.fields()) { // f - std::size_t field_alignment = field.size; // TODO - out << "f " << field.offset << " " << field.size << " " << field_alignment << " " << field.flags << std::endl; + out << "f " << field.offset << " " << field.size << " " << field.alignment << " " << field.flags << std::endl; } } diff --git a/pinpoint/stage0/on_finish_decl.cpp b/pinpoint/stage0/on_finish_decl.cpp index 69eb3eb..d880b61 100644 --- a/pinpoint/stage0/on_finish_decl.cpp +++ b/pinpoint/stage0/on_finish_decl.cpp @@ -46,7 +46,7 @@ static bool compile_datapin(tree type, DataPin& pin, std::size_t offset = 0, std std::size_t field_offset; bool field_bitfield; - if (!field_info(field, &field_offset, nullptr, &field_bitfield)) + if (!field_info(field, &field_offset, nullptr, nullptr, &field_bitfield)) pinpoint_fatal("compile_datapin failed to get field info"); if (field_bitfield) diff --git a/pinpoint/stage0/separate_offset_pass.cpp b/pinpoint/stage0/separate_offset_pass.cpp index 2f8e805..00c0861 100644 --- a/pinpoint/stage0/separate_offset_pass.cpp +++ b/pinpoint/stage0/separate_offset_pass.cpp @@ -107,7 +107,7 @@ static tree separate_offset_chain_maybe(tree ref, gimple_stmt_iterator* gsi) { std::size_t field_offset; bool field_bitfield; - if (!field_info(field_decl, &field_offset, nullptr, &field_bitfield)) + if (!field_info(field_decl, &field_offset, nullptr, nullptr, &field_bitfield)) pinpoint_fatal("separate_offset_chain_maybe failed to get field info of non-target access"); if (field_bitfield) diff --git a/pinpoint/stage0/stage0.h b/pinpoint/stage0/stage0.h index fab8cbf..67faae5 100644 --- a/pinpoint/stage0/stage0.h +++ b/pinpoint/stage0/stage0.h @@ -19,6 +19,7 @@ public: std::size_t offset; std::size_t size; + std::size_t alignment; std::size_t flags; }; private: @@ -62,7 +63,7 @@ private: static TargetType* find_mutable(tree t); }; -bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* bitfield); +bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, std::size_t* alignment, bool* bitfield); /* Stage 0 offsetof separators are function calls, such as: SPSLR_PINPOINT_STAGE0_SEPARATOR(target, member offset) */ diff --git a/pinpoint/stage0/target.cpp b/pinpoint/stage0/target.cpp index 8538b2d..3e23492 100644 --- a/pinpoint/stage0/target.cpp +++ b/pinpoint/stage0/target.cpp @@ -135,7 +135,7 @@ const TargetType* TargetType::find(UID uid) { return &it->second; } -bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* bitfield) { +bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, std::size_t* alignment, bool* bitfield) { if (!field_decl || TREE_CODE(field_decl) != FIELD_DECL) return false; @@ -172,6 +172,19 @@ bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* b if (tmp_bit_overhang != 0) tmp_bit_size += (8 - tmp_bit_overhang); + // Alignment in bytes + + HOST_WIDE_INT tmp_align_bits = DECL_ALIGN(field_decl); + if (tmp_align_bits <= 0 && TREE_TYPE(field_decl)) + tmp_align_bits = TYPE_ALIGN(TREE_TYPE(field_decl)); + if (tmp_align_bits <= 0) + tmp_align_bits = BITS_PER_UNIT; + + std::size_t tmp_alignment = + static_cast((tmp_align_bits + BITS_PER_UNIT - 1) / BITS_PER_UNIT); + if (tmp_alignment == 0) + tmp_alignment = 1; + // Set all outputs if (offset) @@ -180,6 +193,9 @@ bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* b if (size) *size = static_cast(tmp_bit_size / 8); + if (alignment) + *alignment = tmp_alignment; + if (bitfield) *bitfield = tmp_bitfield; @@ -206,7 +222,7 @@ bool TargetType::reference(tree ref, UID& target, std::size_t& offset) { tree field_decl = TREE_OPERAND(ref, 1); - if (!field_info(field_decl, &offset, nullptr, nullptr)) + if (!field_info(field_decl, &offset, nullptr, nullptr, nullptr)) return false; const Field* f = base_target->field(offset, false); @@ -239,7 +255,7 @@ static bool foreach_record_field(tree t, std::function