Proper field alignment recognition

This commit is contained in:
York Jasper Niebuhr 2026-04-04 09:49:40 +02:00
parent 1422c0b143
commit 84b1bc9b4e
7 changed files with 44 additions and 14 deletions

View File

@ -11,11 +11,28 @@ static std::size_t next_global_target_uid = 0;
std::unordered_map<std::size_t, TARGET> targets; std::unordered_map<std::size_t, TARGET> targets;
std::unordered_map<std::string, CU> units; std::unordered_map<std::string, CU> 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 // 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) { 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; return true;
} }

View File

@ -165,8 +165,7 @@ void on_finish_unit(void* plugin_data, void* user_data) {
for (const auto& [off, field] : target.fields()) { for (const auto& [off, field] : target.fields()) {
// f <offset> <size> <alignment> <flags> // f <offset> <size> <alignment> <flags>
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;
} }
} }

View File

@ -46,7 +46,7 @@ static bool compile_datapin(tree type, DataPin& pin, std::size_t offset = 0, std
std::size_t field_offset; std::size_t field_offset;
bool field_bitfield; 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"); pinpoint_fatal("compile_datapin failed to get field info");
if (field_bitfield) if (field_bitfield)

View File

@ -107,7 +107,7 @@ static tree separate_offset_chain_maybe(tree ref, gimple_stmt_iterator* gsi) {
std::size_t field_offset; std::size_t field_offset;
bool field_bitfield; 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"); pinpoint_fatal("separate_offset_chain_maybe failed to get field info of non-target access");
if (field_bitfield) if (field_bitfield)

View File

@ -19,6 +19,7 @@ public:
std::size_t offset; std::size_t offset;
std::size_t size; std::size_t size;
std::size_t alignment;
std::size_t flags; std::size_t flags;
}; };
private: private:
@ -62,7 +63,7 @@ private:
static TargetType* find_mutable(tree t); 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: /* Stage 0 offsetof separators are function calls, such as:
SPSLR_PINPOINT_STAGE0_SEPARATOR(target, member offset) */ SPSLR_PINPOINT_STAGE0_SEPARATOR(target, member offset) */

View File

@ -135,7 +135,7 @@ const TargetType* TargetType::find(UID uid) {
return &it->second; 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) if (!field_decl || TREE_CODE(field_decl) != FIELD_DECL)
return false; 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) if (tmp_bit_overhang != 0)
tmp_bit_size += (8 - tmp_bit_overhang); 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<std::size_t>((tmp_align_bits + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
if (tmp_alignment == 0)
tmp_alignment = 1;
// Set all outputs // Set all outputs
if (offset) if (offset)
@ -180,6 +193,9 @@ bool field_info(tree field_decl, std::size_t* offset, std::size_t* size, bool* b
if (size) if (size)
*size = static_cast<std::size_t>(tmp_bit_size / 8); *size = static_cast<std::size_t>(tmp_bit_size / 8);
if (alignment)
*alignment = tmp_alignment;
if (bitfield) if (bitfield)
*bitfield = tmp_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); 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; return false;
const Field* f = base_target->field(offset, false); const Field* f = base_target->field(offset, false);
@ -239,7 +255,7 @@ static bool foreach_record_field(tree t, std::function<bool(const TargetType::Fi
TargetType::Field field; TargetType::Field field;
bool is_bitfield; bool is_bitfield;
if (!field_info(field_decl, &field.offset, &field.size, &is_bitfield)) if (!field_info(field_decl, &field.offset, &field.size, &field.alignment, &is_bitfield))
return false; return false;
field.flags = (is_bitfield ? TargetType::Field::FLAG_DANGEROUS : 0); field.flags = (is_bitfield ? TargetType::Field::FLAG_DANGEROUS : 0);

View File

@ -1,6 +1,3 @@
Collect alignment data from struct members
Fix bit fields in place
Move patcher generation to pre-link stage Move patcher generation to pre-link stage
- Aggregate meta data files - Aggregate meta data files
- Generate patcher object file than links against symbols - Generate patcher object file than links against symbols