[SelectionDAG] Fix two issues with SDNode::getRawSubclassData().

1) On some platforms, sizeof(SDNodeBits) == 1, so we were only copying
one byte out of the bitfield when we wanted to copy two, and we were
leaving half of the return value of getRawSubclassData() undefined.

2) Something something bitfields, not sure exactly what the issue or fix
is, yet.  (TODO)

Summary:
Previously we were assuming that SDNodeBits covered all of SDNode's
anonymous subclass data bitfield union.  But that's not right; it might
have size 1, in which it clearly doesn't.

This patch adds a field that does cover the whole union and adds
static_asserts to ensure it stays correct.

Reviewers: ahatanak, chandlerc

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D24223

llvm-svn: 281051
This commit is contained in:
Justin Lebar 2016-09-09 16:07:06 +00:00
parent 1eeb11bfd4
commit 8b1460250e
1 changed files with 18 additions and 4 deletions

View File

@ -463,6 +463,7 @@ protected:
};
union {
char RawSDNodeBits[sizeof(uint16_t)];
SDNodeBitfields SDNodeBits;
ConstantSDNodeBitfields ConstantSDNodeBits;
MemSDNodeBitfields MemSDNodeBits;
@ -471,6 +472,21 @@ protected:
StoreSDNodeBitfields StoreSDNodeBits;
};
// RawSDNodeBits must cover the entirety of the union. This means that all
// of the union's members must have size <= RawSDNodeBits.
static_assert(sizeof(SDNodeBits) <= sizeof(RawSDNodeBits),
"SDNodeBits too wide");
static_assert(sizeof(ConstantSDNodeBits) <= sizeof(RawSDNodeBits),
"ConstantSDNodeBits too wide");
static_assert(sizeof(MemSDNodeBits) <= sizeof(RawSDNodeBits),
"MemSDNodeBits too wide");
static_assert(sizeof(LSBaseSDNodeBits) <= sizeof(RawSDNodeBits),
"LSBaseSDNodeBits too wide");
static_assert(sizeof(LoadSDNodeBits) <= sizeof(RawSDNodeBits),
"LoadSDNodeBits too wide");
static_assert(sizeof(StoreSDNodeBits) <= sizeof(RawSDNodeBits),
"StoreSDNodeBits too wide");
private:
/// Unique id per SDNode in the DAG.
int NodeId;
@ -876,7 +892,7 @@ protected:
: NodeType(Opc), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
debugLoc(std::move(dl)) {
memset(&SDNodeBits, 0, sizeof(SDNodeBits));
memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits));
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
@ -1095,9 +1111,7 @@ public:
/// function should only be used to compute a FoldingSetNodeID value.
unsigned getRawSubclassData() const {
uint16_t Data;
memcpy(&Data, &SDNodeBits, sizeof(SDNodeBits));
static_assert(sizeof(SDNodeBits) <= sizeof(uint16_t),
"SDNodeBits field too large?");
memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits));
return Data;
}