diff options
author | Joel Brobecker <brobecker@gnat.com> | 2010-01-29 14:39:04 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2010-01-29 14:39:04 +0000 |
commit | e4e2711a4aea4b4c12347d12ad9987432ff4b21f (patch) | |
tree | ef3cc5cd9585f1470781ee74ff6d56d681a0b885 /gdb/amd64-tdep.c | |
parent | cba6fab54a80261d8f1e6831bc5c560481cfc107 (diff) | |
download | fsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.zip fsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.tar.gz fsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.tar.bz2 |
amd64 - function returning record with field straddling 2 registers
gdb/ChangeLog:
From Paul Hilfinger <hilfinger@adacore.com>
* amd64-tdep.c (amd_classify_aggregate): Handle the case of
a record of length <= 16 in which a field straddles the two
eightbytes.
gdb/testsuite/ChangeLog:
* gdb.ada/rec_return: New testcase.
Diffstat (limited to 'gdb/amd64-tdep.c')
-rw-r--r-- | gdb/amd64-tdep.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index fc621e0..2b15141 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -347,6 +347,12 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); int pos = TYPE_FIELD_BITPOS (type, i) / 64; enum amd64_reg_class subclass[2]; + int bitsize = TYPE_FIELD_BITSIZE (type, i); + int endpos; + + if (bitsize == 0) + bitsize = TYPE_LENGTH (subtype) * 8; + endpos = (TYPE_FIELD_BITPOS (type, i) + bitsize - 1) / 64; /* Ignore static fields. */ if (field_is_static (&TYPE_FIELD (type, i))) @@ -356,6 +362,30 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) amd64_classify (subtype, subclass); class[pos] = amd64_merge_classes (class[pos], subclass[0]); + if (bitsize <= 64 && pos == 0 && endpos == 1) + /* This is a bit of an odd case: We have a field that would + normally fit in one of the two eightbytes, except that + it is placed in a way that this field straddles them. + This has been seen with a structure containing an array. + + The ABI is a bit unclear in this case, but we assume that + this field's class (stored in subclass[0]) must also be merged + into class[1]. In other words, our field has a piece stored + in the second eight-byte, and thus its class applies to + the second eight-byte as well. + + In the case where the field length exceeds 8 bytes, + it should not be necessary to merge the field class + into class[1]. As LEN > 8, subclass[1] is necessarily + different from AMD64_NO_CLASS. If subclass[1] is equal + to subclass[0], then the normal class[1]/subclass[1] + merging will take care of everything. For subclass[1] + to be different from subclass[0], I can only see the case + where we have a SSE/SSEUP or X87/X87UP pair, which both + use up all 16 bytes of the aggregate, and are already + handled just fine (because each portion sits on its own + 8-byte). */ + class[1] = amd64_merge_classes (class[1], subclass[0]); if (pos == 0) class[1] = amd64_merge_classes (class[1], subclass[1]); } |