Bug Summary

File:lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
Warning:line 80, column 27
The result of the left shift is undefined due to shifting by '32', which is greater or equal to the width of type 'unsigned int'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ARMUnwindOpAsm.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/lib/Target/ARM/MCTargetDesc -I /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc -I /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/lib/Target/ARM -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/lib/Target/ARM/MCTargetDesc -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp -faddrsig
1//===-- ARMUnwindOpAsm.cpp - ARM Unwind Opcodes Assembler -------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the unwind opcode assmebler for ARM exception handling
11// table.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ARMUnwindOpAsm.h"
16#include "llvm/Support/ARMEHABI.h"
17#include "llvm/Support/LEB128.h"
18#include "llvm/Support/MathExtras.h"
19#include <cassert>
20
21using namespace llvm;
22
23namespace {
24
25 /// UnwindOpcodeStreamer - The simple wrapper over SmallVector to emit bytes
26 /// with MSB to LSB per uint32_t ordering. For example, the first byte will
27 /// be placed in Vec[3], and the following bytes will be placed in 2, 1, 0,
28 /// 7, 6, 5, 4, 11, 10, 9, 8, and so on.
29 class UnwindOpcodeStreamer {
30 private:
31 SmallVectorImpl<uint8_t> &Vec;
32 size_t Pos = 3;
33
34 public:
35 UnwindOpcodeStreamer(SmallVectorImpl<uint8_t> &V) : Vec(V) {}
36
37 /// Emit the byte in MSB to LSB per uint32_t order.
38 void EmitByte(uint8_t elem) {
39 Vec[Pos] = elem;
40 Pos = (((Pos ^ 0x3u) + 1) ^ 0x3u);
41 }
42
43 /// Emit the size prefix.
44 void EmitSize(size_t Size) {
45 size_t SizeInWords = (Size + 3) / 4;
46 assert(SizeInWords <= 0x100u &&(static_cast <bool> (SizeInWords <= 0x100u &&
"Only 256 additional words are allowed for unwind opcodes") ?
void (0) : __assert_fail ("SizeInWords <= 0x100u && \"Only 256 additional words are allowed for unwind opcodes\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp"
, 47, __extension__ __PRETTY_FUNCTION__))
47 "Only 256 additional words are allowed for unwind opcodes")(static_cast <bool> (SizeInWords <= 0x100u &&
"Only 256 additional words are allowed for unwind opcodes") ?
void (0) : __assert_fail ("SizeInWords <= 0x100u && \"Only 256 additional words are allowed for unwind opcodes\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp"
, 47, __extension__ __PRETTY_FUNCTION__))
;
48 EmitByte(static_cast<uint8_t>(SizeInWords - 1));
49 }
50
51 /// Emit the personality index prefix.
52 void EmitPersonalityIndex(unsigned PI) {
53 assert(PI < ARM::EHABI::NUM_PERSONALITY_INDEX &&(static_cast <bool> (PI < ARM::EHABI::NUM_PERSONALITY_INDEX
&& "Invalid personality prefix") ? void (0) : __assert_fail
("PI < ARM::EHABI::NUM_PERSONALITY_INDEX && \"Invalid personality prefix\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp"
, 54, __extension__ __PRETTY_FUNCTION__))
54 "Invalid personality prefix")(static_cast <bool> (PI < ARM::EHABI::NUM_PERSONALITY_INDEX
&& "Invalid personality prefix") ? void (0) : __assert_fail
("PI < ARM::EHABI::NUM_PERSONALITY_INDEX && \"Invalid personality prefix\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp"
, 54, __extension__ __PRETTY_FUNCTION__))
;
55 EmitByte(ARM::EHABI::EHT_COMPACT | PI);
56 }
57
58 /// Fill the rest of bytes with FINISH opcode.
59 void FillFinishOpcode() {
60 while (Pos < Vec.size())
61 EmitByte(ARM::EHABI::UNWIND_OPCODE_FINISH);
62 }
63 };
64
65} // end anonymous namespace
66
67void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) {
68 if (RegSave == 0u)
1
Assuming 'RegSave' is not equal to 0
2
Taking false branch
69 return;
70
71 // One byte opcode to save register r14 and r11-r4
72 if (RegSave & (1u << 4)) {
3
Assuming the condition is true
4
Taking true branch
73 // The one byte opcode will always save r4, thus we can't use the one byte
74 // opcode when r4 is not in .save directive.
75
76 // Compute the consecutive registers from r4 to r11.
77 uint32_t Mask = RegSave & 0xff0u;
78 uint32_t Range = countTrailingOnes(Mask >> 5); // Exclude r4.
79 // Mask off non-consecutive registers. Keep r4.
80 Mask &= ~(0xffffffe0u << Range);
5
The result of the left shift is undefined due to shifting by '32', which is greater or equal to the width of type 'unsigned int'
81
82 // Emit this opcode when the mask covers every registers.
83 uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);
84 if (UnmaskedReg == 0u) {
85 // Pop r[4 : (4 + n)]
86 EmitInt8(ARM::EHABI::UNWIND_OPCODE_POP_REG_RANGE_R4 | Range);
87 RegSave &= 0x000fu;
88 } else if (UnmaskedReg == (1u << 14)) {
89 // Pop r[14] + r[4 : (4 + n)]
90 EmitInt8(ARM::EHABI::UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range);
91 RegSave &= 0x000fu;
92 }
93 }
94
95 // Two bytes opcode to save register r15-r4
96 if ((RegSave & 0xfff0u) != 0)
97 EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_REG_MASK_R4 | (RegSave >> 4));
98
99 // Opcode to save register r3-r0
100 if ((RegSave & 0x000fu) != 0)
101 EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_REG_MASK | (RegSave & 0x000fu));
102}
103
104/// Emit unwind opcodes for .vsave directives
105void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) {
106 // We only have 4 bits to save the offset in the opcode so look at the lower
107 // and upper 16 bits separately.
108 for (uint32_t Regs : {VFPRegSave & 0xffff0000u, VFPRegSave & 0x0000ffffu}) {
109 while (Regs) {
110 // Now look for a run of set bits. Remember the MSB and LSB of the run.
111 auto RangeMSB = 32 - countLeadingZeros(Regs);
112 auto RangeLen = countLeadingOnes(Regs << (32 - RangeMSB));
113 auto RangeLSB = RangeMSB - RangeLen;
114
115 int Opcode = RangeLSB >= 16
116 ? ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16
117 : ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD;
118
119 EmitInt16(Opcode | ((RangeLSB % 16) << 4) | (RangeLen - 1));
120
121 // Zero out bits we're done with.
122 Regs &= ~(-1u << RangeLSB);
123 }
124 }
125}
126
127/// Emit unwind opcodes to copy address from source register to $sp.
128void UnwindOpcodeAssembler::EmitSetSP(uint16_t Reg) {
129 EmitInt8(ARM::EHABI::UNWIND_OPCODE_SET_VSP | Reg);
130}
131
132/// Emit unwind opcodes to add $sp with an offset.
133void UnwindOpcodeAssembler::EmitSPOffset(int64_t Offset) {
134 if (Offset > 0x200) {
135 uint8_t Buff[16];
136 Buff[0] = ARM::EHABI::UNWIND_OPCODE_INC_VSP_ULEB128;
137 size_t ULEBSize = encodeULEB128((Offset - 0x204) >> 2, Buff + 1);
138 EmitBytes(Buff, ULEBSize + 1);
139 } else if (Offset > 0) {
140 if (Offset > 0x100) {
141 EmitInt8(ARM::EHABI::UNWIND_OPCODE_INC_VSP | 0x3fu);
142 Offset -= 0x100;
143 }
144 EmitInt8(ARM::EHABI::UNWIND_OPCODE_INC_VSP |
145 static_cast<uint8_t>((Offset - 4) >> 2));
146 } else if (Offset < 0) {
147 while (Offset < -0x100) {
148 EmitInt8(ARM::EHABI::UNWIND_OPCODE_DEC_VSP | 0x3fu);
149 Offset += 0x100;
150 }
151 EmitInt8(ARM::EHABI::UNWIND_OPCODE_DEC_VSP |
152 static_cast<uint8_t>(((-Offset) - 4) >> 2));
153 }
154}
155
156void UnwindOpcodeAssembler::Finalize(unsigned &PersonalityIndex,
157 SmallVectorImpl<uint8_t> &Result) {
158 UnwindOpcodeStreamer OpStreamer(Result);
159
160 if (HasPersonality) {
161 // User-specifed personality routine: [ SIZE , OP1 , OP2 , ... ]
162 PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX;
163 size_t TotalSize = Ops.size() + 1;
164 size_t RoundUpSize = (TotalSize + 3) / 4 * 4;
165 Result.resize(RoundUpSize);
166 OpStreamer.EmitSize(RoundUpSize);
167 } else {
168 // If no personalityindex is specified, select ane
169 if (PersonalityIndex == ARM::EHABI::NUM_PERSONALITY_INDEX)
170 PersonalityIndex = (Ops.size() <= 3) ? ARM::EHABI::AEABI_UNWIND_CPP_PR0
171 : ARM::EHABI::AEABI_UNWIND_CPP_PR1;
172 if (PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0) {
173 // __aeabi_unwind_cpp_pr0: [ 0x80 , OP1 , OP2 , OP3 ]
174 assert(Ops.size() <= 3 && "too many opcodes for __aeabi_unwind_cpp_pr0")(static_cast <bool> (Ops.size() <= 3 && "too many opcodes for __aeabi_unwind_cpp_pr0"
) ? void (0) : __assert_fail ("Ops.size() <= 3 && \"too many opcodes for __aeabi_unwind_cpp_pr0\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp"
, 174, __extension__ __PRETTY_FUNCTION__))
;
175 Result.resize(4);
176 OpStreamer.EmitPersonalityIndex(PersonalityIndex);
177 } else {
178 // __aeabi_unwind_cpp_pr{1,2}: [ {0x81,0x82} , SIZE , OP1 , OP2 , ... ]
179 size_t TotalSize = Ops.size() + 2;
180 size_t RoundUpSize = (TotalSize + 3) / 4 * 4;
181 Result.resize(RoundUpSize);
182 OpStreamer.EmitPersonalityIndex(PersonalityIndex);
183 OpStreamer.EmitSize(RoundUpSize);
184 }
185 }
186
187 // Copy the unwind opcodes
188 for (size_t i = OpBegins.size() - 1; i > 0; --i)
189 for (size_t j = OpBegins[i - 1], end = OpBegins[i]; j < end; ++j)
190 OpStreamer.EmitByte(Ops[j]);
191
192 // Emit the padding finish opcodes if the size is not multiple of 4.
193 OpStreamer.FillFinishOpcode();
194
195 // Reset the assembler state
196 Reset();
197}