forked from OSchip/llvm-project
bpf: fix a strict-aliasing issue
Davide Italiano reported the following issue if llvm is compiled with gcc -Wstrict-aliasing -Werror: ..... lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BPFISelDAGToDAG.cpp.o ../lib/Target/BPF/BPFISelDAGToDAG.cpp: In member function ‘virtual void {anonymous}::BPFDAGToDAGISel::PreprocessISelDAG()’: ../lib/Target/BPF/BPFISelDAGToDAG.cpp:264:26: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] val = *(uint16_t *)new_val; ..... The error is caused by my previous commit (revision 305560). This patch fixed the issue by introducing an union to avoid type casting. Signed-off-by: Yonghong Song <yhs@fb.com> llvm-svn: 305608
This commit is contained in:
parent
61e684adcc
commit
a63178f756
|
@ -214,7 +214,12 @@ void BPFDAGToDAGISel::PreprocessISelDAG() {
|
|||
if (Opcode != ISD::LOAD)
|
||||
continue;
|
||||
|
||||
unsigned char new_val[8]; // hold up the constant values replacing loads.
|
||||
union {
|
||||
uint8_t c[8];
|
||||
uint16_t s;
|
||||
uint32_t i;
|
||||
uint64_t d;
|
||||
} new_val; // hold up the constant values replacing loads.
|
||||
bool to_replace = false;
|
||||
SDLoc DL(Node);
|
||||
const LoadSDNode *LD = cast<LoadSDNode>(Node);
|
||||
|
@ -242,7 +247,7 @@ void BPFDAGToDAGISel::PreprocessISelDAG() {
|
|||
const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
|
||||
if (GADN && CDN)
|
||||
to_replace =
|
||||
getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val);
|
||||
getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val.c);
|
||||
} else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
|
||||
LDAddrNode->getNumOperands() > 0) {
|
||||
DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
|
||||
|
@ -250,7 +255,7 @@ void BPFDAGToDAGISel::PreprocessISelDAG() {
|
|||
SDValue OP1 = LDAddrNode->getOperand(0);
|
||||
if (const GlobalAddressSDNode *GADN =
|
||||
dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
|
||||
to_replace = getConstantFieldValue(GADN, 0, size, new_val);
|
||||
to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
|
||||
}
|
||||
|
||||
if (!to_replace)
|
||||
|
@ -259,13 +264,13 @@ void BPFDAGToDAGISel::PreprocessISelDAG() {
|
|||
// replacing the old with a new value
|
||||
uint64_t val;
|
||||
if (size == 1)
|
||||
val = *(uint8_t *)new_val;
|
||||
val = new_val.c[0];
|
||||
else if (size == 2)
|
||||
val = *(uint16_t *)new_val;
|
||||
val = new_val.s;
|
||||
else if (size == 4)
|
||||
val = *(uint32_t *)new_val;
|
||||
val = new_val.i;
|
||||
else {
|
||||
val = *(uint64_t *)new_val;
|
||||
val = new_val.d;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "Replacing load of size " << size << " with constant "
|
||||
|
@ -318,14 +323,17 @@ bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
|
|||
}
|
||||
|
||||
// test whether host endianness matches target
|
||||
uint8_t test_buf[2];
|
||||
union {
|
||||
uint8_t c[2];
|
||||
uint16_t s;
|
||||
} test_buf;
|
||||
uint16_t test_val = 0x2345;
|
||||
if (DL.isLittleEndian())
|
||||
support::endian::write16le(test_buf, test_val);
|
||||
support::endian::write16le(test_buf.c, test_val);
|
||||
else
|
||||
support::endian::write16be(test_buf, test_val);
|
||||
support::endian::write16be(test_buf.c, test_val);
|
||||
|
||||
bool endian_match = *(uint16_t *)test_buf == test_val;
|
||||
bool endian_match = test_buf.s == test_val;
|
||||
for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++)
|
||||
ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
|
||||
|
||||
|
|
Loading…
Reference in New Issue