From 86f1ba02a91d387ff523ca5f4653a940bdc49d87 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Fri, 16 Jun 2017 23:28:04 +0000 Subject: [PATCH] bpf: fix a strict-aliasing issue MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305608 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/BPF/BPFISelDAGToDAG.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/Target/BPF/BPFISelDAGToDAG.cpp b/lib/Target/BPF/BPFISelDAGToDAG.cpp index 7d5fb6ca17b..c6ddd6bdad5 100644 --- a/lib/Target/BPF/BPFISelDAGToDAG.cpp +++ b/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -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(Node); @@ -242,7 +247,7 @@ void BPFDAGToDAGISel::PreprocessISelDAG() { const ConstantSDNode *CDN = dyn_cast(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(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]; -- 2.40.0