Proper field alignment recognition
This commit is contained in:
parent
1422c0b143
commit
84b1bc9b4e
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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) */
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
3
plan.txt
3
plan.txt
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user