Bug Summary

File:tools/llvm-exegesis/lib/MCInstrDescView.cpp
Warning:line 235, column 44
Access to field 'RegClass' results in a dereference of a null pointer (loaded from field 'Info')

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 MCInstrDescView.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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-8/lib/clang/8.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/llvm-exegesis/lib -I /build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/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-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/llvm-exegesis/lib -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-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp -faddrsig
1//===-- MCInstrDescView.cpp -------------------------------------*- 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#include "MCInstrDescView.h"
11
12#include <iterator>
13#include <map>
14#include <tuple>
15
16#include "llvm/ADT/STLExtras.h"
17
18namespace llvm {
19namespace exegesis {
20
21unsigned Variable::getIndex() const {
22 assert(Index >= 0 && "Index must be set")((Index >= 0 && "Index must be set") ? static_cast
<void> (0) : __assert_fail ("Index >= 0 && \"Index must be set\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 22, __PRETTY_FUNCTION__))
;
23 return Index;
24}
25
26unsigned Variable::getPrimaryOperandIndex() const {
27 assert(!TiedOperands.empty())((!TiedOperands.empty()) ? static_cast<void> (0) : __assert_fail
("!TiedOperands.empty()", "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 27, __PRETTY_FUNCTION__))
;
28 return TiedOperands[0];
29}
30
31bool Variable::hasTiedOperands() const {
32 assert(TiedOperands.size() <= 2 &&((TiedOperands.size() <= 2 && "No more than two operands can be tied together"
) ? static_cast<void> (0) : __assert_fail ("TiedOperands.size() <= 2 && \"No more than two operands can be tied together\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 33, __PRETTY_FUNCTION__))
33 "No more than two operands can be tied together")((TiedOperands.size() <= 2 && "No more than two operands can be tied together"
) ? static_cast<void> (0) : __assert_fail ("TiedOperands.size() <= 2 && \"No more than two operands can be tied together\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 33, __PRETTY_FUNCTION__))
;
34 // By definition only Use and Def operands can be tied together.
35 // TiedOperands[0] is the Def operand (LLVM stores defs first).
36 // TiedOperands[1] is the Use operand.
37 return TiedOperands.size() > 1;
38}
39
40unsigned Operand::getIndex() const {
41 assert(Index >= 0 && "Index must be set")((Index >= 0 && "Index must be set") ? static_cast
<void> (0) : __assert_fail ("Index >= 0 && \"Index must be set\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 41, __PRETTY_FUNCTION__))
;
42 return Index;
43}
44
45bool Operand::isExplicit() const { return Info; }
46
47bool Operand::isImplicit() const { return !Info; }
48
49bool Operand::isImplicitReg() const { return ImplicitReg; }
50
51bool Operand::isDef() const { return IsDef; }
52
53bool Operand::isUse() const { return !IsDef; }
54
55bool Operand::isReg() const { return Tracker; }
56
57bool Operand::isTied() const { return TiedToIndex >= 0; }
58
59bool Operand::isVariable() const { return VariableIndex >= 0; }
60
61bool Operand::isMemory() const {
62 return isExplicit() &&
63 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
64}
65
66bool Operand::isImmediate() const {
67 return isExplicit() &&
68 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
69}
70
71unsigned Operand::getTiedToIndex() const {
72 assert(isTied() && "Operand must be tied to get the tied index")((isTied() && "Operand must be tied to get the tied index"
) ? static_cast<void> (0) : __assert_fail ("isTied() && \"Operand must be tied to get the tied index\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 72, __PRETTY_FUNCTION__))
;
73 assert(TiedToIndex >= 0 && "TiedToIndex must be set")((TiedToIndex >= 0 && "TiedToIndex must be set") ?
static_cast<void> (0) : __assert_fail ("TiedToIndex >= 0 && \"TiedToIndex must be set\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 73, __PRETTY_FUNCTION__))
;
74 return TiedToIndex;
75}
76
77unsigned Operand::getVariableIndex() const {
78 assert(isVariable() && "Operand must be variable to get the Variable index")((isVariable() && "Operand must be variable to get the Variable index"
) ? static_cast<void> (0) : __assert_fail ("isVariable() && \"Operand must be variable to get the Variable index\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 78, __PRETTY_FUNCTION__))
;
79 assert(VariableIndex >= 0 && "VariableIndex must be set")((VariableIndex >= 0 && "VariableIndex must be set"
) ? static_cast<void> (0) : __assert_fail ("VariableIndex >= 0 && \"VariableIndex must be set\""
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 79, __PRETTY_FUNCTION__))
;
80 return VariableIndex;
81}
82
83unsigned Operand::getImplicitReg() const {
84 assert(ImplicitReg)((ImplicitReg) ? static_cast<void> (0) : __assert_fail (
"ImplicitReg", "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 84, __PRETTY_FUNCTION__))
;
85 return *ImplicitReg;
86}
87
88const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
89 assert(Tracker)((Tracker) ? static_cast<void> (0) : __assert_fail ("Tracker"
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 89, __PRETTY_FUNCTION__))
;
90 return *Tracker;
91}
92
93const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
94 assert(Info)((Info) ? static_cast<void> (0) : __assert_fail ("Info"
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 94, __PRETTY_FUNCTION__))
;
95 return *Info;
96}
97
98Instruction::Instruction(const llvm::MCInstrInfo &InstrInfo,
99 const RegisterAliasingTrackerCache &RATC,
100 unsigned Opcode)
101 : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) {
102 unsigned OpIndex = 0;
103 for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
104 const auto &OpInfo = Description->opInfo_begin()[OpIndex];
105 Operand Operand;
106 Operand.Index = OpIndex;
107 Operand.IsDef = (OpIndex < Description->getNumDefs());
108 // TODO(gchatelet): Handle isLookupPtrRegClass.
109 if (OpInfo.RegClass >= 0)
110 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
111 Operand.TiedToIndex =
112 Description->getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
113 Operand.Info = &OpInfo;
114 Operands.push_back(Operand);
115 }
116 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitDefs();
117 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
118 Operand Operand;
119 Operand.Index = OpIndex;
120 Operand.IsDef = true;
121 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
122 Operand.ImplicitReg = MCPhysReg;
123 Operands.push_back(Operand);
124 }
125 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitUses();
126 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
127 Operand Operand;
128 Operand.Index = OpIndex;
129 Operand.IsDef = false;
130 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
131 Operand.ImplicitReg = MCPhysReg;
132 Operands.push_back(Operand);
133 }
134 // Assigning Variables to non tied explicit operands.
135 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
136 for (auto &Op : Operands)
137 if (Op.isExplicit() && !Op.isTied()) {
138 const size_t VariableIndex = Variables.size();
139 Op.VariableIndex = VariableIndex;
140 Variables.emplace_back();
141 Variables.back().Index = VariableIndex;
142 }
143 // Assigning Variables to tied operands.
144 for (auto &Op : Operands)
145 if (Op.isTied())
146 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
147 // Assigning Operands to Variables.
148 for (auto &Op : Operands)
149 if (Op.isVariable())
150 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
151 // Processing Aliasing.
152 ImplDefRegs = RATC.emptyRegisters();
153 ImplUseRegs = RATC.emptyRegisters();
154 AllDefRegs = RATC.emptyRegisters();
155 AllUseRegs = RATC.emptyRegisters();
156 for (const auto &Op : Operands) {
157 if (Op.isReg()) {
158 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
159 if (Op.isDef())
160 AllDefRegs |= AliasingBits;
161 if (Op.isUse())
162 AllUseRegs |= AliasingBits;
163 if (Op.isDef() && Op.isImplicit())
164 ImplDefRegs |= AliasingBits;
165 if (Op.isUse() && Op.isImplicit())
166 ImplUseRegs |= AliasingBits;
167 }
168 }
169}
170
171const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
172 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
173 assert(PrimaryOperandIndex < Operands.size())((PrimaryOperandIndex < Operands.size()) ? static_cast<
void> (0) : __assert_fail ("PrimaryOperandIndex < Operands.size()"
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp"
, 173, __PRETTY_FUNCTION__))
;
174 return Operands[PrimaryOperandIndex];
175}
176
177bool Instruction::hasMemoryOperands() const {
178 return any_of(Operands, [](const Operand &Op) {
179 return Op.isReg() && Op.isExplicit() && Op.isMemory();
180 });
181}
182
183bool Instruction::hasAliasingImplicitRegisters() const {
184 return ImplDefRegs.anyCommon(ImplUseRegs);
185}
186
187bool Instruction::hasAliasingImplicitRegistersThrough(
188 const Instruction &OtherInstr) const {
189 return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) &&
190 OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs);
191}
192
193bool Instruction::hasAliasingRegistersThrough(
194 const Instruction &OtherInstr) const {
195 return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) &&
196 OtherInstr.AllDefRegs.anyCommon(AllUseRegs);
197}
198
199bool Instruction::hasTiedRegisters() const {
200 return llvm::any_of(
201 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
202}
203
204bool Instruction::hasAliasingRegisters() const {
205 return AllDefRegs.anyCommon(AllUseRegs);
206}
207
208bool Instruction::hasOneUseOrOneDef() const {
209 return AllDefRegs.count() || AllUseRegs.count();
210}
211
212void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
213 llvm::raw_ostream &Stream) const {
214 Stream << "- " << Name << "\n";
215 for (const auto &Op : Operands) {
1
Assuming '__begin2' is not equal to '__end2'
216 Stream << "- Op" << Op.getIndex();
217 if (Op.isExplicit())
2
Assuming pointer value is null
3
Taking false branch
218 Stream << " Explicit";
219 if (Op.isImplicit())
4
Taking true branch
220 Stream << " Implicit";
221 if (Op.isUse())
5
Taking false branch
222 Stream << " Use";
223 if (Op.isDef())
6
Taking true branch
224 Stream << " Def";
225 if (Op.isImmediate())
7
Taking false branch
226 Stream << " Immediate";
227 if (Op.isMemory())
8
Taking false branch
228 Stream << " Memory";
229 if (Op.isReg()) {
9
Assuming the condition is true
10
Taking true branch
230 if (Op.isImplicitReg())
11
Assuming the condition is false
12
Taking false branch
231 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
232 else
233 Stream << " RegClass("
234 << RegInfo.getRegClassName(
235 &RegInfo.getRegClass(Op.Info->RegClass))
13
Access to field 'RegClass' results in a dereference of a null pointer (loaded from field 'Info')
236 << ")";
237 }
238 if (Op.isTied())
239 Stream << " TiedToOp" << Op.getTiedToIndex();
240 Stream << "\n";
241 }
242 for (const auto &Var : Variables) {
243 Stream << "- Var" << Var.getIndex();
244 Stream << " [";
245 bool IsFirst = true;
246 for (auto OperandIndex : Var.TiedOperands) {
247 if (!IsFirst)
248 Stream << ",";
249 Stream << "Op" << OperandIndex;
250 IsFirst = false;
251 }
252 Stream << "]";
253 Stream << "\n";
254 }
255 if (hasMemoryOperands())
256 Stream << "- hasMemoryOperands\n";
257 if (hasAliasingImplicitRegisters())
258 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
259 if (hasTiedRegisters())
260 Stream << "- hasTiedRegisters (execution is always serial)\n";
261 if (hasAliasingRegisters())
262 Stream << "- hasAliasingRegisters\n";
263}
264
265InstructionsCache::InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
266 const RegisterAliasingTrackerCache &RATC)
267 : InstrInfo(InstrInfo), RATC(RATC) {}
268
269const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
270 auto &Found = Instructions[Opcode];
271 if (!Found)
272 Found.reset(new Instruction(InstrInfo, RATC, Opcode));
273 return *Found;
274}
275
276bool RegisterOperandAssignment::
277operator==(const RegisterOperandAssignment &Other) const {
278 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
279}
280
281bool AliasingRegisterOperands::
282operator==(const AliasingRegisterOperands &Other) const {
283 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
284}
285
286static void addOperandIfAlias(
287 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
288 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
289 for (const auto &Op : Operands) {
290 if (Op.isReg() && Op.isDef() == SelectDef) {
291 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
292 if (SourceReg >= 0)
293 OperandValues.emplace_back(&Op, SourceReg);
294 }
295 }
296}
297
298bool AliasingRegisterOperands::hasImplicitAliasing() const {
299 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
300 return ROV.Op->isImplicit();
301 };
302 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
303}
304
305bool AliasingConfigurations::empty() const { return Configurations.empty(); }
306
307bool AliasingConfigurations::hasImplicitAliasing() const {
308 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
309 return ARO.hasImplicitAliasing();
310 });
311}
312
313AliasingConfigurations::AliasingConfigurations(
314 const Instruction &DefInstruction, const Instruction &UseInstruction) {
315 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
316 auto CommonRegisters = UseInstruction.AllUseRegs;
317 CommonRegisters &= DefInstruction.AllDefRegs;
318 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
319 AliasingRegisterOperands ARO;
320 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
321 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
322 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
323 !llvm::is_contained(Configurations, ARO))
324 Configurations.push_back(std::move(ARO));
325 }
326 }
327}
328
329void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
330 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
331 if (!Op.isValid())
332 OS << "Invalid";
333 else if (Op.isReg())
334 OS << MCRegisterInfo.getName(Op.getReg());
335 else if (Op.isImm())
336 OS << Op.getImm();
337 else if (Op.isFPImm())
338 OS << Op.getFPImm();
339 else if (Op.isExpr())
340 OS << "Expr";
341 else if (Op.isInst())
342 OS << "SubInst";
343}
344
345void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
346 const llvm::MCInstrInfo &MCInstrInfo,
347 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
348 OS << MCInstrInfo.getName(MCInst.getOpcode());
349 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
350 if (I > 0)
351 OS << ',';
352 OS << ' ';
353 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
354 }
355}
356
357} // namespace exegesis
358} // namespace llvm