Bug Summary

File:lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
Warning:line 179, column 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'

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 WebAssemblyFrameLowering.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/WebAssembly -I /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly -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/WebAssembly -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/WebAssembly/WebAssemblyFrameLowering.cpp -faddrsig
1//===-- WebAssemblyFrameLowering.cpp - WebAssembly Frame Lowering ----------==//
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/// \file
11/// This file contains the WebAssembly implementation of
12/// TargetFrameLowering class.
13///
14/// On WebAssembly, there aren't a lot of things to do here. There are no
15/// callee-saved registers to save, and no spill slots.
16///
17/// The stack grows downward.
18///
19//===----------------------------------------------------------------------===//
20
21#include "WebAssemblyFrameLowering.h"
22#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
23#include "WebAssemblyInstrInfo.h"
24#include "WebAssemblyMachineFunctionInfo.h"
25#include "WebAssemblySubtarget.h"
26#include "WebAssemblyTargetMachine.h"
27#include "WebAssemblyUtilities.h"
28#include "llvm/CodeGen/MachineFrameInfo.h"
29#include "llvm/CodeGen/MachineFunction.h"
30#include "llvm/CodeGen/MachineInstrBuilder.h"
31#include "llvm/CodeGen/MachineModuleInfoImpls.h"
32#include "llvm/CodeGen/MachineRegisterInfo.h"
33#include "llvm/Support/Debug.h"
34using namespace llvm;
35
36#define DEBUG_TYPE"wasm-frame-info" "wasm-frame-info"
37
38// TODO: wasm64
39// TODO: Emit TargetOpcode::CFI_INSTRUCTION instructions
40
41/// We need a base pointer in the case of having items on the stack that
42/// require stricter alignment than the stack pointer itself. Because we need
43/// to shift the stack pointer by some unknown amount to force the alignment,
44/// we need to record the value of the stack pointer on entry to the function.
45bool WebAssemblyFrameLowering::hasBP(
46 const MachineFunction &MF) const {
47 const auto *RegInfo =
48 MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
49 return RegInfo->needsStackRealignment(MF);
50}
51
52/// Return true if the specified function should have a dedicated frame pointer
53/// register.
54bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const {
55 const MachineFrameInfo &MFI = MF.getFrameInfo();
56
57 // When we have var-sized objects, we move the stack pointer by an unknown
58 // amount, and need to emit a frame pointer to restore the stack to where we
59 // were on function entry.
60 // If we already need a base pointer, we use that to fix up the stack pointer.
61 // If there are no fixed-size objects, we would have no use of a frame
62 // pointer, and thus should not emit one.
63 bool HasFixedSizedObjects = MFI.getStackSize() > 0;
64 bool NeedsFixedReference = !hasBP(MF) || HasFixedSizedObjects;
65
66 return MFI.isFrameAddressTaken() ||
67 (MFI.hasVarSizedObjects() && NeedsFixedReference) ||
68 MFI.hasStackMap() || MFI.hasPatchPoint();
69}
70
71/// Under normal circumstances, when a frame pointer is not required, we reserve
72/// argument space for call sites in the function immediately on entry to the
73/// current function. This eliminates the need for add/sub sp brackets around
74/// call sites. Returns true if the call frame is included as part of the stack
75/// frame.
76bool WebAssemblyFrameLowering::hasReservedCallFrame(
77 const MachineFunction &MF) const {
78 return !MF.getFrameInfo().hasVarSizedObjects();
79}
80
81
82/// Returns true if this function needs a local user-space stack pointer.
83/// Unlike a machine stack pointer, the wasm user stack pointer is a global
84/// variable, so it is loaded into a register in the prolog.
85bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF,
86 const MachineFrameInfo &MFI) const {
87 return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF);
88}
89
90/// Returns true if the local user-space stack pointer needs to be written back
91/// to memory by this function (this is not meaningful if needsSP is false). If
92/// false, the stack red zone can be used and only a local SP is needed.
93bool WebAssemblyFrameLowering::needsSPWriteback(
94 const MachineFunction &MF, const MachineFrameInfo &MFI) const {
95 assert(needsSP(MF, MFI))(static_cast <bool> (needsSP(MF, MFI)) ? void (0) : __assert_fail
("needsSP(MF, MFI)", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 95, __extension__ __PRETTY_FUNCTION__))
;
96 return MFI.getStackSize() > RedZoneSize || MFI.hasCalls() ||
97 MF.getFunction().hasFnAttribute(Attribute::NoRedZone);
98}
99
100static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
101 MachineBasicBlock &MBB,
102 MachineBasicBlock::iterator &InsertAddr,
103 MachineBasicBlock::iterator &InsertStore,
104 const DebugLoc &DL) {
105 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
106
107 const char *ES = "__stack_pointer";
108 auto *SPSymbol = MF.createExternalSymbolName(ES);
109 BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::SET_GLOBAL_I32))
110 .addExternalSymbol(SPSymbol)
111 .addReg(SrcReg);
112}
113
114MachineBasicBlock::iterator
115WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
116 MachineFunction &MF, MachineBasicBlock &MBB,
117 MachineBasicBlock::iterator I) const {
118 assert(!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) &&(static_cast <bool> (!I->getOperand(0).getImm() &&
(hasFP(MF) || hasBP(MF)) && "Call frame pseudos should only be used for dynamic stack adjustment"
) ? void (0) : __assert_fail ("!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) && \"Call frame pseudos should only be used for dynamic stack adjustment\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 119, __extension__ __PRETTY_FUNCTION__))
119 "Call frame pseudos should only be used for dynamic stack adjustment")(static_cast <bool> (!I->getOperand(0).getImm() &&
(hasFP(MF) || hasBP(MF)) && "Call frame pseudos should only be used for dynamic stack adjustment"
) ? void (0) : __assert_fail ("!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) && \"Call frame pseudos should only be used for dynamic stack adjustment\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 119, __extension__ __PRETTY_FUNCTION__))
;
120 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
121 if (I->getOpcode() == TII->getCallFrameDestroyOpcode() &&
122 needsSPWriteback(MF, MF.getFrameInfo())) {
123 DebugLoc DL = I->getDebugLoc();
124 writeSPToMemory(WebAssembly::SP32, MF, MBB, I, I, DL);
125 }
126 return MBB.erase(I);
127}
128
129void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
130 MachineBasicBlock &MBB) const {
131 // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions
132 auto &MFI = MF.getFrameInfo();
133 assert(MFI.getCalleeSavedInfo().empty() &&(static_cast <bool> (MFI.getCalleeSavedInfo().empty() &&
"WebAssembly should not have callee-saved registers") ? void
(0) : __assert_fail ("MFI.getCalleeSavedInfo().empty() && \"WebAssembly should not have callee-saved registers\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 134, __extension__ __PRETTY_FUNCTION__))
134 "WebAssembly should not have callee-saved registers")(static_cast <bool> (MFI.getCalleeSavedInfo().empty() &&
"WebAssembly should not have callee-saved registers") ? void
(0) : __assert_fail ("MFI.getCalleeSavedInfo().empty() && \"WebAssembly should not have callee-saved registers\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 134, __extension__ __PRETTY_FUNCTION__))
;
135
136 if (!needsSP(MF, MFI)) return;
1
Taking false branch
137 uint64_t StackSize = MFI.getStackSize();
138
139 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
140 auto &MRI = MF.getRegInfo();
141
142 auto InsertPt = MBB.begin();
143 while (InsertPt != MBB.end() && WebAssembly::isArgument(*InsertPt))
2
Loop condition is false. Execution continues on line 145
144 ++InsertPt;
145 DebugLoc DL;
146
147 const TargetRegisterClass *PtrRC =
148 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
149 unsigned SPReg = WebAssembly::SP32;
150 if (StackSize)
3
Taking false branch
151 SPReg = MRI.createVirtualRegister(PtrRC);
152
153 const char *ES = "__stack_pointer";
154 auto *SPSymbol = MF.createExternalSymbolName(ES);
155 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GET_GLOBAL_I32), SPReg)
156 .addExternalSymbol(SPSymbol);
157
158 bool HasBP = hasBP(MF);
159 if (HasBP) {
4
Assuming 'HasBP' is not equal to 0
5
Taking true branch
160 auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
161 unsigned BasePtr = MRI.createVirtualRegister(PtrRC);
162 FI->setBasePointerVreg(BasePtr);
163 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BasePtr)
164 .addReg(SPReg);
165 }
166 if (StackSize) {
6
Taking false branch
167 // Subtract the frame size
168 unsigned OffsetReg = MRI.createVirtualRegister(PtrRC);
169 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
170 .addImm(StackSize);
171 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32),
172 WebAssembly::SP32)
173 .addReg(SPReg)
174 .addReg(OffsetReg);
175 }
176 if (HasBP) {
7
Taking true branch
177 unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC);
178 unsigned Alignment = MFI.getMaxAlignment();
179 assert((1u << countTrailingZeros(Alignment)) == Alignment &&(static_cast <bool> ((1u << countTrailingZeros(Alignment
)) == Alignment && "Alignment must be a power of 2") ?
void (0) : __assert_fail ("(1u << countTrailingZeros(Alignment)) == Alignment && \"Alignment must be a power of 2\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 180, __extension__ __PRETTY_FUNCTION__))
8
Within the expansion of the macro 'assert':
a
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'
180 "Alignment must be a power of 2")(static_cast <bool> ((1u << countTrailingZeros(Alignment
)) == Alignment && "Alignment must be a power of 2") ?
void (0) : __assert_fail ("(1u << countTrailingZeros(Alignment)) == Alignment && \"Alignment must be a power of 2\""
, "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp"
, 180, __extension__ __PRETTY_FUNCTION__))
;
181 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg)
182 .addImm((int)~(Alignment - 1));
183 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32),
184 WebAssembly::SP32)
185 .addReg(WebAssembly::SP32)
186 .addReg(BitmaskReg);
187 }
188 if (hasFP(MF)) {
189 // Unlike most conventional targets (where FP points to the saved FP),
190 // FP points to the bottom of the fixed-size locals, so we can use positive
191 // offsets in load/store instructions.
192 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY),
193 WebAssembly::FP32)
194 .addReg(WebAssembly::SP32);
195 }
196 if (StackSize && needsSPWriteback(MF, MFI)) {
197 writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, InsertPt, DL);
198 }
199}
200
201void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
202 MachineBasicBlock &MBB) const {
203 auto &MFI = MF.getFrameInfo();
204 uint64_t StackSize = MFI.getStackSize();
205 if (!needsSP(MF, MFI) || !needsSPWriteback(MF, MFI)) return;
206 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
207 auto &MRI = MF.getRegInfo();
208 auto InsertPt = MBB.getFirstTerminator();
209 DebugLoc DL;
210
211 if (InsertPt != MBB.end())
212 DL = InsertPt->getDebugLoc();
213
214 // Restore the stack pointer. If we had fixed-size locals, add the offset
215 // subtracted in the prolog.
216 unsigned SPReg = 0;
217 MachineBasicBlock::iterator InsertAddr = InsertPt;
218 if (hasBP(MF)) {
219 auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
220 SPReg = FI->getBasePointerVreg();
221 } else if (StackSize) {
222 const TargetRegisterClass *PtrRC =
223 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
224 unsigned OffsetReg = MRI.createVirtualRegister(PtrRC);
225 InsertAddr =
226 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
227 .addImm(StackSize);
228 // In the epilog we don't need to write the result back to the SP32 physreg
229 // because it won't be used again. We can use a stackified register instead.
230 SPReg = MRI.createVirtualRegister(PtrRC);
231 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), SPReg)
232 .addReg(hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32)
233 .addReg(OffsetReg);
234 } else {
235 SPReg = hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32;
236 }
237
238 writeSPToMemory(SPReg, MF, MBB, InsertAddr, InsertPt, DL);
239}