summaryrefslogtreecommitdiffhomepage
path: root/ir/be
diff options
context:
space:
mode:
authorAndreas Fried <andreas.fried@kit.edu>2019-11-08 14:58:22 +0100
committerAndreas Fried <andreas.fried@kit.edu>2019-11-08 15:00:54 +0100
commitf7ec5706af08145638069aedecef94c5d2b38c33 (patch)
treeef2d2e7cc3cc3d80d2d6c5202e7202f5865c37e4 /ir/be
parenta4672cceb5a83407ba9a70a9b7b613006034073e (diff)
Fix handling of array-typed struct members in AMD64 ABI.
Arrays need to be considered for a slice even if their starting offset is outside the range in question (e.g. struct { long x[2]; };).
Diffstat (limited to 'ir/be')
-rw-r--r--ir/be/amd64/amd64_abi.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/ir/be/amd64/amd64_abi.c b/ir/be/amd64/amd64_abi.c
index 562316a..6f65823 100644
--- a/ir/be/amd64/amd64_abi.c
+++ b/ir/be/amd64/amd64_abi.c
@@ -77,14 +77,20 @@ static ir_mode *classify_compound_by_members(ir_type const *const tp, unsigned m
ir_mode *current_class = mode_BAD;
for (unsigned i = 0; i < n; i++) {
ir_entity *member = get_compound_member(tp, i);
- unsigned offset = get_entity_offset(member);
+ ir_type *member_type = get_entity_type(member);
+ unsigned member_size = get_type_size(member_type);
- if (min <= offset && offset < max) {
+ unsigned member_begin = get_entity_offset(member);
+ unsigned member_end = member_begin + member_size;
+
+ // Is the member (at least partially) between min and max?
+ if (min < member_end && max > member_begin) {
if (get_entity_aligned(member) == align_non_aligned) {
return mode_M;
}
- ir_type *member_type = get_entity_type(member);
- ir_mode *member_class = classify_slice_for_amd64(member_type, 0, max - offset);
+ unsigned min_in_member = min <= member_begin ? 0 : min - member_begin;
+ unsigned max_in_member = member_end < max ? member_size : max - member_begin;
+ ir_mode *member_class = classify_slice_for_amd64(member_type, min_in_member, max_in_member);
current_class = fold_classes(current_class, member_class);
}
}