File: | lib/MC/MCObjectStreamer.cpp |
Location: | line 408, column 23 |
Description: | Called C++ object pointer is null |
1 | //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===// |
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 "llvm/MC/MCObjectStreamer.h" |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/MC/MCAsmBackend.h" |
13 | #include "llvm/MC/MCAsmInfo.h" |
14 | #include "llvm/MC/MCAssembler.h" |
15 | #include "llvm/MC/MCCodeEmitter.h" |
16 | #include "llvm/MC/MCContext.h" |
17 | #include "llvm/MC/MCDwarf.h" |
18 | #include "llvm/MC/MCExpr.h" |
19 | #include "llvm/MC/MCObjectWriter.h" |
20 | #include "llvm/MC/MCSection.h" |
21 | #include "llvm/MC/MCSymbol.h" |
22 | #include "llvm/Support/ErrorHandling.h" |
23 | using namespace llvm; |
24 | |
25 | MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, |
26 | raw_ostream &OS, MCCodeEmitter *Emitter_) |
27 | : MCStreamer(Context), |
28 | Assembler(new MCAssembler(Context, TAB, *Emitter_, |
29 | *TAB.createObjectWriter(OS), OS)), |
30 | CurSectionData(nullptr), EmitEHFrame(true), EmitDebugFrame(false) {} |
31 | |
32 | MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, |
33 | raw_ostream &OS, MCCodeEmitter *Emitter_, |
34 | MCAssembler *_Assembler) |
35 | : MCStreamer(Context), Assembler(_Assembler), CurSectionData(nullptr), |
36 | EmitEHFrame(true), EmitDebugFrame(false) {} |
37 | |
38 | MCObjectStreamer::~MCObjectStreamer() { |
39 | delete &Assembler->getBackend(); |
40 | delete &Assembler->getEmitter(); |
41 | delete &Assembler->getWriter(); |
42 | delete Assembler; |
43 | } |
44 | |
45 | void MCObjectStreamer::flushPendingLabels(MCFragment *F) { |
46 | if (PendingLabels.size()) { |
47 | if (!F) { |
48 | F = new MCDataFragment(); |
49 | CurSectionData->getFragmentList().insert(CurInsertionPoint, F); |
50 | F->setParent(CurSectionData); |
51 | } |
52 | for (MCSymbolData *SD : PendingLabels) { |
53 | SD->setFragment(F); |
54 | SD->setOffset(0); |
55 | } |
56 | PendingLabels.clear(); |
57 | } |
58 | } |
59 | |
60 | void MCObjectStreamer::reset() { |
61 | if (Assembler) |
62 | Assembler->reset(); |
63 | CurSectionData = nullptr; |
64 | CurInsertionPoint = MCSectionData::iterator(); |
65 | EmitEHFrame = true; |
66 | EmitDebugFrame = false; |
67 | PendingLabels.clear(); |
68 | MCStreamer::reset(); |
69 | } |
70 | |
71 | void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) { |
72 | if (!getNumFrameInfos()) |
73 | return; |
74 | |
75 | if (EmitEHFrame) |
76 | MCDwarfFrameEmitter::Emit(*this, MAB, true); |
77 | |
78 | if (EmitDebugFrame) |
79 | MCDwarfFrameEmitter::Emit(*this, MAB, false); |
80 | } |
81 | |
82 | MCFragment *MCObjectStreamer::getCurrentFragment() const { |
83 | assert(getCurrentSectionData() && "No current section!")((getCurrentSectionData() && "No current section!") ? static_cast<void> (0) : __assert_fail ("getCurrentSectionData() && \"No current section!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 83, __PRETTY_FUNCTION__)); |
84 | |
85 | if (CurInsertionPoint != getCurrentSectionData()->getFragmentList().begin()) |
86 | return std::prev(CurInsertionPoint); |
87 | |
88 | return nullptr; |
89 | } |
90 | |
91 | MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() { |
92 | MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); |
93 | // When bundling is enabled, we don't want to add data to a fragment that |
94 | // already has instructions (see MCELFStreamer::EmitInstToData for details) |
95 | if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) { |
96 | F = new MCDataFragment(); |
97 | insert(F); |
98 | } |
99 | return F; |
100 | } |
101 | |
102 | void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) { |
103 | Assembler->getOrCreateSymbolData(Sym); |
104 | } |
105 | |
106 | void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { |
107 | MCStreamer::EmitCFISections(EH, Debug); |
108 | EmitEHFrame = EH; |
109 | EmitDebugFrame = Debug; |
110 | } |
111 | |
112 | void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, |
113 | const SMLoc &Loc) { |
114 | MCStreamer::EmitValueImpl(Value, Size, Loc); |
115 | MCDataFragment *DF = getOrCreateDataFragment(); |
116 | |
117 | MCLineEntry::Make(this, getCurrentSection().first); |
118 | |
119 | // Avoid fixups when possible. |
120 | int64_t AbsValue; |
121 | if (Value->EvaluateAsAbsolute(AbsValue, getAssembler())) { |
122 | EmitIntValue(AbsValue, Size); |
123 | return; |
124 | } |
125 | DF->getFixups().push_back( |
126 | MCFixup::Create(DF->getContents().size(), Value, |
127 | MCFixup::getKindForSize(Size, false), Loc)); |
128 | DF->getContents().resize(DF->getContents().size() + Size, 0); |
129 | } |
130 | |
131 | void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { |
132 | // We need to create a local symbol to avoid relocations. |
133 | Frame.Begin = getContext().CreateTempSymbol(); |
134 | EmitLabel(Frame.Begin); |
135 | } |
136 | |
137 | void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { |
138 | Frame.End = getContext().CreateTempSymbol(); |
139 | EmitLabel(Frame.End); |
140 | } |
141 | |
142 | void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { |
143 | MCStreamer::EmitLabel(Symbol); |
144 | |
145 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); |
146 | assert(!SD.getFragment() && "Unexpected fragment on symbol data!")((!SD.getFragment() && "Unexpected fragment on symbol data!" ) ? static_cast<void> (0) : __assert_fail ("!SD.getFragment() && \"Unexpected fragment on symbol data!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 146, __PRETTY_FUNCTION__)); |
147 | |
148 | // If there is a current fragment, mark the symbol as pointing into it. |
149 | // Otherwise queue the label and set its fragment pointer when we emit the |
150 | // next fragment. |
151 | if (auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment())) { |
152 | SD.setFragment(F); |
153 | SD.setOffset(F->getContents().size()); |
154 | } else { |
155 | PendingLabels.push_back(&SD); |
156 | } |
157 | } |
158 | |
159 | void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { |
160 | int64_t IntValue; |
161 | if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { |
162 | EmitULEB128IntValue(IntValue); |
163 | return; |
164 | } |
165 | insert(new MCLEBFragment(*Value, false)); |
166 | } |
167 | |
168 | void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { |
169 | int64_t IntValue; |
170 | if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { |
171 | EmitSLEB128IntValue(IntValue); |
172 | return; |
173 | } |
174 | insert(new MCLEBFragment(*Value, true)); |
175 | } |
176 | |
177 | void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, |
178 | const MCSymbol *Symbol) { |
179 | report_fatal_error("This file format doesn't support weak aliases."); |
180 | } |
181 | |
182 | void MCObjectStreamer::ChangeSection(const MCSection *Section, |
183 | const MCExpr *Subsection) { |
184 | assert(Section && "Cannot switch to a null section!")((Section && "Cannot switch to a null section!") ? static_cast <void> (0) : __assert_fail ("Section && \"Cannot switch to a null section!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 184, __PRETTY_FUNCTION__)); |
185 | flushPendingLabels(nullptr); |
186 | |
187 | CurSectionData = &getAssembler().getOrCreateSectionData(*Section); |
188 | |
189 | int64_t IntSubsection = 0; |
190 | if (Subsection && |
191 | !Subsection->EvaluateAsAbsolute(IntSubsection, getAssembler())) |
192 | report_fatal_error("Cannot evaluate subsection number"); |
193 | if (IntSubsection < 0 || IntSubsection > 8192) |
194 | report_fatal_error("Subsection number out of range"); |
195 | CurInsertionPoint = |
196 | CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection)); |
197 | } |
198 | |
199 | void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { |
200 | getAssembler().getOrCreateSymbolData(*Symbol); |
201 | MCStreamer::EmitAssignment(Symbol, Value); |
202 | } |
203 | |
204 | void MCObjectStreamer::EmitInstruction(const MCInst &Inst, |
205 | const MCSubtargetInfo &STI) { |
206 | MCStreamer::EmitInstruction(Inst, STI); |
207 | |
208 | MCSectionData *SD = getCurrentSectionData(); |
209 | SD->setHasInstructions(true); |
210 | |
211 | // Now that a machine instruction has been assembled into this section, make |
212 | // a line entry for any .loc directive that has been seen. |
213 | MCLineEntry::Make(this, getCurrentSection().first); |
214 | |
215 | // If this instruction doesn't need relaxation, just emit it as data. |
216 | MCAssembler &Assembler = getAssembler(); |
217 | if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { |
218 | EmitInstToData(Inst, STI); |
219 | return; |
220 | } |
221 | |
222 | // Otherwise, relax and emit it as data if either: |
223 | // - The RelaxAll flag was passed |
224 | // - Bundling is enabled and this instruction is inside a bundle-locked |
225 | // group. We want to emit all such instructions into the same data |
226 | // fragment. |
227 | if (Assembler.getRelaxAll() || |
228 | (Assembler.isBundlingEnabled() && SD->isBundleLocked())) { |
229 | MCInst Relaxed; |
230 | getAssembler().getBackend().relaxInstruction(Inst, Relaxed); |
231 | while (getAssembler().getBackend().mayNeedRelaxation(Relaxed)) |
232 | getAssembler().getBackend().relaxInstruction(Relaxed, Relaxed); |
233 | EmitInstToData(Relaxed, STI); |
234 | return; |
235 | } |
236 | |
237 | // Otherwise emit to a separate fragment. |
238 | EmitInstToFragment(Inst, STI); |
239 | } |
240 | |
241 | void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst, |
242 | const MCSubtargetInfo &STI) { |
243 | // Always create a new, separate fragment here, because its size can change |
244 | // during relaxation. |
245 | MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI); |
246 | insert(IF); |
247 | |
248 | SmallString<128> Code; |
249 | raw_svector_ostream VecOS(Code); |
250 | getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups(), |
251 | STI); |
252 | VecOS.flush(); |
253 | IF->getContents().append(Code.begin(), Code.end()); |
254 | } |
255 | |
256 | #ifndef NDEBUG |
257 | static const char *const BundlingNotImplementedMsg = |
258 | "Aligned bundling is not implemented for this object format"; |
259 | #endif |
260 | |
261 | void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) { |
262 | llvm_unreachable(BundlingNotImplementedMsg)::llvm::llvm_unreachable_internal(BundlingNotImplementedMsg, "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 262); |
263 | } |
264 | |
265 | void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) { |
266 | llvm_unreachable(BundlingNotImplementedMsg)::llvm::llvm_unreachable_internal(BundlingNotImplementedMsg, "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 266); |
267 | } |
268 | |
269 | void MCObjectStreamer::EmitBundleUnlock() { |
270 | llvm_unreachable(BundlingNotImplementedMsg)::llvm::llvm_unreachable_internal(BundlingNotImplementedMsg, "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224007/lib/MC/MCObjectStreamer.cpp" , 270); |
271 | } |
272 | |
273 | void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, |
274 | unsigned Column, unsigned Flags, |
275 | unsigned Isa, |
276 | unsigned Discriminator, |
277 | StringRef FileName) { |
278 | // In case we see two .loc directives in a row, make sure the |
279 | // first one gets a line entry. |
280 | MCLineEntry::Make(this, getCurrentSection().first); |
281 | |
282 | this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, |
283 | Isa, Discriminator, FileName); |
284 | } |
285 | |
286 | static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, |
287 | const MCSymbol *B) { |
288 | MCContext &Context = OS.getContext(); |
289 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; |
290 | const MCExpr *ARef = MCSymbolRefExpr::Create(A, Variant, Context); |
291 | const MCExpr *BRef = MCSymbolRefExpr::Create(B, Variant, Context); |
292 | const MCExpr *AddrDelta = |
293 | MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); |
294 | return AddrDelta; |
295 | } |
296 | |
297 | static void emitDwarfSetLineAddr(MCObjectStreamer &OS, int64_t LineDelta, |
298 | const MCSymbol *Label, int PointerSize) { |
299 | // emit the sequence to set the address |
300 | OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1); |
301 | OS.EmitULEB128IntValue(PointerSize + 1); |
302 | OS.EmitIntValue(dwarf::DW_LNE_set_address, 1); |
303 | OS.EmitSymbolValue(Label, PointerSize); |
304 | |
305 | // emit the sequence for the LineDelta (from 1) and a zero address delta. |
306 | MCDwarfLineAddr::Emit(&OS, LineDelta, 0); |
307 | } |
308 | |
309 | void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, |
310 | const MCSymbol *LastLabel, |
311 | const MCSymbol *Label, |
312 | unsigned PointerSize) { |
313 | if (!LastLabel) { |
314 | emitDwarfSetLineAddr(*this, LineDelta, Label, PointerSize); |
315 | return; |
316 | } |
317 | const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); |
318 | int64_t Res; |
319 | if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { |
320 | MCDwarfLineAddr::Emit(this, LineDelta, Res); |
321 | return; |
322 | } |
323 | insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); |
324 | } |
325 | |
326 | void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, |
327 | const MCSymbol *Label) { |
328 | const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); |
329 | int64_t Res; |
330 | if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { |
331 | MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res); |
332 | return; |
333 | } |
334 | insert(new MCDwarfCallFrameFragment(*AddrDelta)); |
335 | } |
336 | |
337 | void MCObjectStreamer::EmitBytes(StringRef Data) { |
338 | MCLineEntry::Make(this, getCurrentSection().first); |
339 | getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); |
340 | } |
341 | |
342 | void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment, |
343 | int64_t Value, |
344 | unsigned ValueSize, |
345 | unsigned MaxBytesToEmit) { |
346 | if (MaxBytesToEmit == 0) |
347 | MaxBytesToEmit = ByteAlignment; |
348 | insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); |
349 | |
350 | // Update the maximum alignment on the current section if necessary. |
351 | if (ByteAlignment > getCurrentSectionData()->getAlignment()) |
352 | getCurrentSectionData()->setAlignment(ByteAlignment); |
353 | } |
354 | |
355 | void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment, |
356 | unsigned MaxBytesToEmit) { |
357 | EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit); |
358 | cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true); |
359 | } |
360 | |
361 | bool MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, |
362 | unsigned char Value) { |
363 | int64_t Res; |
364 | if (Offset->EvaluateAsAbsolute(Res, getAssembler())) { |
365 | insert(new MCOrgFragment(*Offset, Value)); |
366 | return false; |
367 | } |
368 | |
369 | MCSymbol *CurrentPos = getContext().CreateTempSymbol(); |
370 | EmitLabel(CurrentPos); |
371 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; |
372 | const MCExpr *Ref = |
373 | MCSymbolRefExpr::Create(CurrentPos, Variant, getContext()); |
374 | const MCExpr *Delta = |
375 | MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext()); |
376 | |
377 | if (!Delta->EvaluateAsAbsolute(Res, getAssembler())) |
378 | return true; |
379 | EmitFill(Res, Value); |
380 | return false; |
381 | } |
382 | |
383 | // Associate GPRel32 fixup with data and resize data area |
384 | void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) { |
385 | MCDataFragment *DF = getOrCreateDataFragment(); |
386 | |
387 | DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(), |
388 | Value, FK_GPRel_4)); |
389 | DF->getContents().resize(DF->getContents().size() + 4, 0); |
390 | } |
391 | |
392 | // Associate GPRel32 fixup with data and resize data area |
393 | void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { |
394 | MCDataFragment *DF = getOrCreateDataFragment(); |
395 | |
396 | DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(), |
397 | Value, FK_GPRel_4)); |
398 | DF->getContents().resize(DF->getContents().size() + 8, 0); |
399 | } |
400 | |
401 | void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { |
402 | // FIXME: A MCFillFragment would be more memory efficient but MCExpr has |
403 | // problems evaluating expressions across multiple fragments. |
404 | getOrCreateDataFragment()->getContents().append(NumBytes, FillValue); |
405 | } |
406 | |
407 | void MCObjectStreamer::EmitZeros(uint64_t NumBytes) { |
408 | unsigned ItemSize = getCurrentSection().first->isVirtualSection() ? 0 : 1; |
Called C++ object pointer is null | |
409 | insert(new MCFillFragment(0, ItemSize, NumBytes)); |
410 | } |
411 | |
412 | void MCObjectStreamer::FinishImpl() { |
413 | // If we are generating dwarf for assembly source files dump out the sections. |
414 | if (getContext().getGenDwarfForAssembly()) |
415 | MCGenDwarfInfo::Emit(this); |
416 | |
417 | // Dump out the dwarf file & directory tables and line tables. |
418 | MCDwarfLineTable::Emit(this); |
419 | |
420 | flushPendingLabels(nullptr); |
421 | getAssembler().Finish(); |
422 | } |