1 //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/MC/MCObjectStreamer.h"
10 #include "llvm/MC/MCAsmBackend.h"
11 #include "llvm/MC/MCAsmInfo.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCCodeEmitter.h"
14 #include "llvm/MC/MCCodeView.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCDwarf.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCObjectFileInfo.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSection.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/SourceMgr.h"
25 using namespace llvm;
26
MCObjectStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> TAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)27 MCObjectStreamer::MCObjectStreamer(MCContext &Context,
28 std::unique_ptr<MCAsmBackend> TAB,
29 std::unique_ptr<MCObjectWriter> OW,
30 std::unique_ptr<MCCodeEmitter> Emitter)
31 : MCStreamer(Context),
32 Assembler(std::make_unique<MCAssembler>(
33 Context, std::move(TAB), std::move(Emitter), std::move(OW))),
34 EmitEHFrame(true), EmitDebugFrame(false) {
35 assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());
36 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
37 if (Context.getTargetOptions() && Context.getTargetOptions()->MCRelaxAll)
38 Assembler->setRelaxAll(true);
39 }
40
41 MCObjectStreamer::~MCObjectStreamer() = default;
42
getAssemblerPtr()43 MCAssembler *MCObjectStreamer::getAssemblerPtr() {
44 if (getUseAssemblerInfoForParsing())
45 return Assembler.get();
46 return nullptr;
47 }
48
49 // When fixup's offset is a forward declared label, e.g.:
50 //
51 // .reloc 1f, R_MIPS_JALR, foo
52 // 1: nop
53 //
54 // postpone adding it to Fixups vector until the label is defined and its offset
55 // is known.
resolvePendingFixups()56 void MCObjectStreamer::resolvePendingFixups() {
57 for (PendingMCFixup &PendingFixup : PendingFixups) {
58 if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
59 getContext().reportError(PendingFixup.Fixup.getLoc(),
60 "unresolved relocation offset");
61 continue;
62 }
63 PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
64 PendingFixup.Fixup.getOffset());
65
66 // If the location symbol to relocate is in MCEncodedFragment,
67 // put the Fixup into location symbol's fragment. Otherwise
68 // put into PendingFixup.DF
69 MCFragment *SymFragment = PendingFixup.Sym->getFragment();
70 if (auto *F = dyn_cast<MCEncodedFragment>(SymFragment))
71 F->addFixup(PendingFixup.Fixup);
72 else
73 PendingFixup.DF->addFixup(PendingFixup.Fixup);
74 }
75 PendingFixups.clear();
76 }
77
78 // As a compile-time optimization, avoid allocating and evaluating an MCExpr
79 // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
absoluteSymbolDiff(const MCSymbol * Hi,const MCSymbol * Lo)80 static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
81 const MCSymbol *Lo) {
82 assert(Hi && Lo);
83 if (Lo == Hi)
84 return 0;
85 if (Hi->isVariable() || Lo->isVariable())
86 return std::nullopt;
87 auto *LoF = Lo->getFragment();
88 if (!LoF || LoF->getKind() != MCFragment::FT_Data ||
89 Hi->getFragment() != LoF || LoF->isLinkerRelaxable())
90 return std::nullopt;
91
92 return Hi->getOffset() - Lo->getOffset();
93 }
94
emitAbsoluteSymbolDiff(const MCSymbol * Hi,const MCSymbol * Lo,unsigned Size)95 void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
96 const MCSymbol *Lo,
97 unsigned Size) {
98 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
99 emitIntValue(*Diff, Size);
100 else
101 MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
102 }
103
emitAbsoluteSymbolDiffAsULEB128(const MCSymbol * Hi,const MCSymbol * Lo)104 void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
105 const MCSymbol *Lo) {
106 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
107 emitULEB128IntValue(*Diff);
108 else
109 MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
110 }
111
reset()112 void MCObjectStreamer::reset() {
113 if (Assembler) {
114 Assembler->reset();
115 if (getContext().getTargetOptions())
116 Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);
117 }
118 EmitEHFrame = true;
119 EmitDebugFrame = false;
120 MCStreamer::reset();
121 }
122
emitFrames(MCAsmBackend * MAB)123 void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
124 if (!getNumFrameInfos())
125 return;
126
127 if (EmitEHFrame)
128 MCDwarfFrameEmitter::Emit(*this, MAB, true);
129
130 if (EmitDebugFrame)
131 MCDwarfFrameEmitter::Emit(*this, MAB, false);
132 }
133
canReuseDataFragment(const MCDataFragment & F,const MCAssembler & Assembler,const MCSubtargetInfo * STI)134 static bool canReuseDataFragment(const MCDataFragment &F,
135 const MCAssembler &Assembler,
136 const MCSubtargetInfo *STI) {
137 if (!F.hasInstructions())
138 return true;
139 // Do not add data after a linker-relaxable instruction. The difference
140 // between a new label and a label at or before the linker-relaxable
141 // instruction cannot be resolved at assemble-time.
142 if (F.isLinkerRelaxable())
143 return false;
144 // When bundling is enabled, we don't want to add data to a fragment that
145 // already has instructions (see MCELFStreamer::emitInstToData for details)
146 if (Assembler.isBundlingEnabled())
147 return false;
148 // If the subtarget is changed mid fragment we start a new fragment to record
149 // the new STI.
150 return !STI || F.getSubtargetInfo() == STI;
151 }
152
153 MCDataFragment *
getOrCreateDataFragment(const MCSubtargetInfo * STI)154 MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
155 auto *F = dyn_cast<MCDataFragment>(getCurrentFragment());
156 if (!F || !canReuseDataFragment(*F, *Assembler, STI)) {
157 F = getContext().allocFragment<MCDataFragment>();
158 insert(F);
159 }
160 return F;
161 }
162
visitUsedSymbol(const MCSymbol & Sym)163 void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
164 Assembler->registerSymbol(Sym);
165 }
166
emitCFISections(bool EH,bool Debug)167 void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
168 MCStreamer::emitCFISections(EH, Debug);
169 EmitEHFrame = EH;
170 EmitDebugFrame = Debug;
171 }
172
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)173 void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
174 SMLoc Loc) {
175 MCStreamer::emitValueImpl(Value, Size, Loc);
176 MCDataFragment *DF = getOrCreateDataFragment();
177
178 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
179
180 // Avoid fixups when possible.
181 int64_t AbsValue;
182 if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
183 if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
184 getContext().reportError(
185 Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
186 return;
187 }
188 emitIntValue(AbsValue, Size);
189 return;
190 }
191 DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
192 MCFixup::getDataKindForSize(Size)));
193 DF->appendContents(Size, 0);
194 }
195
emitCFILabel()196 MCSymbol *MCObjectStreamer::emitCFILabel() {
197 MCSymbol *Label = getContext().createTempSymbol("cfi");
198 emitLabel(Label);
199 return Label;
200 }
201
emitCFIStartProcImpl(MCDwarfFrameInfo & Frame)202 void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
203 // We need to create a local symbol to avoid relocations.
204 Frame.Begin = getContext().createTempSymbol();
205 emitLabel(Frame.Begin);
206 }
207
emitCFIEndProcImpl(MCDwarfFrameInfo & Frame)208 void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
209 Frame.End = getContext().createTempSymbol();
210 emitLabel(Frame.End);
211 }
212
emitLabel(MCSymbol * Symbol,SMLoc Loc)213 void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
214 MCStreamer::emitLabel(Symbol, Loc);
215 // If Symbol is a non-redefiniable variable, emitLabel has reported an error.
216 // Bail out.
217 if (Symbol->isVariable())
218 return;
219
220 getAssembler().registerSymbol(*Symbol);
221
222 // If there is a current fragment, mark the symbol as pointing into it.
223 // Otherwise queue the label and set its fragment pointer when we emit the
224 // next fragment.
225 MCDataFragment *F = getOrCreateDataFragment();
226 Symbol->setFragment(F);
227 Symbol->setOffset(F->getContents().size());
228
229 emitPendingAssignments(Symbol);
230 }
231
emitPendingAssignments(MCSymbol * Symbol)232 void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
233 auto Assignments = pendingAssignments.find(Symbol);
234 if (Assignments != pendingAssignments.end()) {
235 for (const PendingAssignment &A : Assignments->second)
236 emitAssignment(A.Symbol, A.Value);
237
238 pendingAssignments.erase(Assignments);
239 }
240 }
241
242 // Emit a label at a previously emitted fragment/offset position. This must be
243 // within the currently-active section.
emitLabelAtPos(MCSymbol * Symbol,SMLoc Loc,MCDataFragment & F,uint64_t Offset)244 void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
245 MCDataFragment &F, uint64_t Offset) {
246 assert(F.getParent() == getCurrentSectionOnly());
247 MCStreamer::emitLabel(Symbol, Loc);
248 getAssembler().registerSymbol(*Symbol);
249 Symbol->setFragment(&F);
250 Symbol->setOffset(Offset);
251 }
252
emitULEB128Value(const MCExpr * Value)253 void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
254 int64_t IntValue;
255 if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
256 emitULEB128IntValue(IntValue);
257 return;
258 }
259 insert(getContext().allocFragment<MCLEBFragment>(*Value, false));
260 }
261
emitSLEB128Value(const MCExpr * Value)262 void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
263 int64_t IntValue;
264 if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
265 emitSLEB128IntValue(IntValue);
266 return;
267 }
268 insert(getContext().allocFragment<MCLEBFragment>(*Value, true));
269 }
270
emitWeakReference(MCSymbol * Alias,const MCSymbol * Target)271 void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
272 const MCSymbol *Target) {
273 reportFatalUsageError("this file format doesn't support weak aliases");
274 }
275
changeSection(MCSection * Section,uint32_t Subsection)276 void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
277 changeSectionImpl(Section, Subsection);
278 }
279
changeSectionImpl(MCSection * Section,uint32_t Subsection)280 bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
281 uint32_t Subsection) {
282 assert(Section && "Cannot switch to a null section!");
283 getContext().clearDwarfLocSeen();
284
285 auto &Subsections = Section->Subsections;
286 size_t I = 0, E = Subsections.size();
287 while (I != E && Subsections[I].first < Subsection)
288 ++I;
289 // If the subsection number is not in the sorted Subsections list, create a
290 // new fragment list.
291 if (I == E || Subsections[I].first != Subsection) {
292 auto *F = getContext().allocFragment<MCDataFragment>();
293 F->setParent(Section);
294 Subsections.insert(Subsections.begin() + I,
295 {Subsection, MCSection::FragList{F, F}});
296 }
297 Section->CurFragList = &Subsections[I].second;
298 CurFrag = Section->CurFragList->Tail;
299
300 return getAssembler().registerSection(*Section);
301 }
302
switchSectionNoPrint(MCSection * Section)303 void MCObjectStreamer::switchSectionNoPrint(MCSection *Section) {
304 MCStreamer::switchSectionNoPrint(Section);
305 changeSection(Section, 0);
306 }
307
emitAssignment(MCSymbol * Symbol,const MCExpr * Value)308 void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
309 getAssembler().registerSymbol(*Symbol);
310 MCStreamer::emitAssignment(Symbol, Value);
311 emitPendingAssignments(Symbol);
312 }
313
emitConditionalAssignment(MCSymbol * Symbol,const MCExpr * Value)314 void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,
315 const MCExpr *Value) {
316 const MCSymbol *Target = &cast<MCSymbolRefExpr>(*Value).getSymbol();
317
318 // If the symbol already exists, emit the assignment. Otherwise, emit it
319 // later only if the symbol is also emitted.
320 if (Target->isRegistered())
321 emitAssignment(Symbol, Value);
322 else
323 pendingAssignments[Target].push_back({Symbol, Value});
324 }
325
mayHaveInstructions(MCSection & Sec) const326 bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
327 return Sec.hasInstructions();
328 }
329
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)330 void MCObjectStreamer::emitInstruction(const MCInst &Inst,
331 const MCSubtargetInfo &STI) {
332 const MCSection &Sec = *getCurrentSectionOnly();
333 if (Sec.isVirtualSection()) {
334 getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +
335 " section '" + Sec.getName() +
336 "' cannot have instructions");
337 return;
338 }
339 emitInstructionImpl(Inst, STI);
340 }
341
emitInstructionImpl(const MCInst & Inst,const MCSubtargetInfo & STI)342 void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
343 const MCSubtargetInfo &STI) {
344 MCStreamer::emitInstruction(Inst, STI);
345
346 MCSection *Sec = getCurrentSectionOnly();
347 Sec->setHasInstructions(true);
348
349 // Now that a machine instruction has been assembled into this section, make
350 // a line entry for any .loc directive that has been seen.
351 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
352
353 // If this instruction doesn't need relaxation, just emit it as data.
354 MCAssembler &Assembler = getAssembler();
355 MCAsmBackend &Backend = Assembler.getBackend();
356 if (!(Backend.mayNeedRelaxation(Inst.getOpcode(), Inst.getOperands(), STI) ||
357 Backend.allowEnhancedRelaxation())) {
358 emitInstToData(Inst, STI);
359 return;
360 }
361
362 // Otherwise, relax and emit it as data if either:
363 // - The RelaxAll flag was passed
364 // - Bundling is enabled and this instruction is inside a bundle-locked
365 // group. We want to emit all such instructions into the same data
366 // fragment.
367 if (Assembler.getRelaxAll() ||
368 (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
369 MCInst Relaxed = Inst;
370 while (Backend.mayNeedRelaxation(Relaxed.getOpcode(), Relaxed.getOperands(),
371 STI))
372 Backend.relaxInstruction(Relaxed, STI);
373 emitInstToData(Relaxed, STI);
374 return;
375 }
376
377 // Otherwise emit to a separate fragment.
378 emitInstToFragment(Inst, STI);
379 }
380
emitInstToData(const MCInst & Inst,const MCSubtargetInfo & STI)381 void MCObjectStreamer::emitInstToData(const MCInst &Inst,
382 const MCSubtargetInfo &STI) {
383 MCDataFragment *DF = getOrCreateDataFragment();
384 SmallVector<MCFixup, 1> Fixups;
385 SmallString<256> Code;
386 getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
387
388 auto CodeOffset = DF->getContents().size();
389 for (MCFixup &Fixup : Fixups)
390 Fixup.setOffset(Fixup.getOffset() + CodeOffset);
391 if (!Fixups.empty())
392 DF->appendFixups(Fixups);
393 DF->setHasInstructions(STI);
394 DF->appendContents(Code);
395 }
396
emitInstToFragment(const MCInst & Inst,const MCSubtargetInfo & STI)397 void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
398 const MCSubtargetInfo &STI) {
399 // Always create a new, separate fragment here, because its size can change
400 // during relaxation.
401 MCRelaxableFragment *IF =
402 getContext().allocFragment<MCRelaxableFragment>(STI);
403 insert(IF);
404 IF->setInst(Inst);
405
406 SmallVector<MCFixup, 1> Fixups;
407 getAssembler().getEmitter().encodeInstruction(
408 Inst, IF->getContentsForAppending(), Fixups, STI);
409 IF->doneAppending();
410 IF->appendFixups(Fixups);
411
412 for (auto &Fixup : Fixups) {
413 if (Fixup.isLinkerRelaxable()) {
414 IF->setLinkerRelaxable();
415 getCurrentSectionOnly()->setLinkerRelaxable();
416 }
417 }
418 }
419
420 #ifndef NDEBUG
421 static const char *const BundlingNotImplementedMsg =
422 "Aligned bundling is not implemented for this object format";
423 #endif
424
emitBundleAlignMode(Align Alignment)425 void MCObjectStreamer::emitBundleAlignMode(Align Alignment) {
426 llvm_unreachable(BundlingNotImplementedMsg);
427 }
428
emitBundleLock(bool AlignToEnd)429 void MCObjectStreamer::emitBundleLock(bool AlignToEnd) {
430 llvm_unreachable(BundlingNotImplementedMsg);
431 }
432
emitBundleUnlock()433 void MCObjectStreamer::emitBundleUnlock() {
434 llvm_unreachable(BundlingNotImplementedMsg);
435 }
436
emitDwarfLocDirective(unsigned FileNo,unsigned Line,unsigned Column,unsigned Flags,unsigned Isa,unsigned Discriminator,StringRef FileName,StringRef Comment)437 void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
438 unsigned Column, unsigned Flags,
439 unsigned Isa,
440 unsigned Discriminator,
441 StringRef FileName,
442 StringRef Comment) {
443 // In case we see two .loc directives in a row, make sure the
444 // first one gets a line entry.
445 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
446
447 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
448 Discriminator, FileName, Comment);
449 }
450
buildSymbolDiff(MCObjectStreamer & OS,const MCSymbol * A,const MCSymbol * B,SMLoc Loc)451 static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
452 const MCSymbol *B, SMLoc Loc) {
453 MCContext &Context = OS.getContext();
454 const MCExpr *ARef = MCSymbolRefExpr::create(A, Context);
455 const MCExpr *BRef = MCSymbolRefExpr::create(B, Context);
456 const MCExpr *AddrDelta =
457 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context, Loc);
458 return AddrDelta;
459 }
460
emitDwarfSetLineAddr(MCObjectStreamer & OS,MCDwarfLineTableParams Params,int64_t LineDelta,const MCSymbol * Label,int PointerSize)461 static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
462 MCDwarfLineTableParams Params,
463 int64_t LineDelta, const MCSymbol *Label,
464 int PointerSize) {
465 // emit the sequence to set the address
466 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
467 OS.emitULEB128IntValue(PointerSize + 1);
468 OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
469 OS.emitSymbolValue(Label, PointerSize);
470
471 // emit the sequence for the LineDelta (from 1) and a zero address delta.
472 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
473 }
474
emitDwarfAdvanceLineAddr(int64_t LineDelta,const MCSymbol * LastLabel,const MCSymbol * Label,unsigned PointerSize)475 void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
476 const MCSymbol *LastLabel,
477 const MCSymbol *Label,
478 unsigned PointerSize) {
479 if (!LastLabel) {
480 emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
481 Label, PointerSize);
482 return;
483 }
484
485 // If the two labels are within the same fragment, then the address-offset is
486 // already a fixed constant and is not relaxable. Emit the advance-line-addr
487 // data immediately to save time and memory.
488 if (auto OptAddrDelta = absoluteSymbolDiff(Label, LastLabel)) {
489 SmallString<16> Tmp;
490 MCDwarfLineAddr::encode(getContext(), Assembler->getDWARFLinetableParams(),
491 LineDelta, *OptAddrDelta, Tmp);
492 emitBytes(Tmp);
493 return;
494 }
495
496 const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc());
497 insert(getContext().allocFragment<MCDwarfLineAddrFragment>(LineDelta,
498 *AddrDelta));
499 }
500
emitDwarfLineEndEntry(MCSection * Section,MCSymbol * LastLabel,MCSymbol * EndLabel)501 void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
502 MCSymbol *LastLabel,
503 MCSymbol *EndLabel) {
504 // Emit a DW_LNE_end_sequence into the line table. When EndLabel is null, it
505 // means we should emit the entry for the end of the section and therefore we
506 // use the section end label for the reference label. After having the
507 // appropriate reference label, we emit the address delta and use INT64_MAX as
508 // the line delta which is the signal that this is actually a
509 // DW_LNE_end_sequence.
510 if (!EndLabel)
511 EndLabel = endSection(Section);
512
513 // Switch back the dwarf line section, in case endSection had to switch the
514 // section.
515 MCContext &Ctx = getContext();
516 switchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());
517
518 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
519 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, EndLabel,
520 AsmInfo->getCodePointerSize());
521 }
522
emitDwarfAdvanceFrameAddr(const MCSymbol * LastLabel,const MCSymbol * Label,SMLoc Loc)523 void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
524 const MCSymbol *Label,
525 SMLoc Loc) {
526 const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc);
527 insert(getContext().allocFragment<MCDwarfCallFrameFragment>(*AddrDelta));
528 }
529
emitCVLocDirective(unsigned FunctionId,unsigned FileNo,unsigned Line,unsigned Column,bool PrologueEnd,bool IsStmt,StringRef FileName,SMLoc Loc)530 void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
531 unsigned Line, unsigned Column,
532 bool PrologueEnd, bool IsStmt,
533 StringRef FileName, SMLoc Loc) {
534 // Validate the directive.
535 if (!checkCVLocSection(FunctionId, FileNo, Loc))
536 return;
537
538 // Emit a label at the current position and record it in the CodeViewContext.
539 MCSymbol *LineSym = getContext().createTempSymbol();
540 emitLabel(LineSym);
541 getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
542 FileNo, Line, Column, PrologueEnd,
543 IsStmt);
544 }
545
emitCVLinetableDirective(unsigned FunctionId,const MCSymbol * Begin,const MCSymbol * End)546 void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
547 const MCSymbol *Begin,
548 const MCSymbol *End) {
549 getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
550 End);
551 this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);
552 }
553
emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,unsigned SourceFileId,unsigned SourceLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym)554 void MCObjectStreamer::emitCVInlineLinetableDirective(
555 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
556 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
557 getContext().getCVContext().emitInlineLineTableForFunction(
558 *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
559 FnEndSym);
560 this->MCStreamer::emitCVInlineLinetableDirective(
561 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
562 }
563
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,StringRef FixedSizePortion)564 void MCObjectStreamer::emitCVDefRangeDirective(
565 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
566 StringRef FixedSizePortion) {
567 getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
568 // Attach labels that were pending before we created the defrange fragment to
569 // the beginning of the new fragment.
570 this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
571 }
572
emitCVStringTableDirective()573 void MCObjectStreamer::emitCVStringTableDirective() {
574 getContext().getCVContext().emitStringTable(*this);
575 }
emitCVFileChecksumsDirective()576 void MCObjectStreamer::emitCVFileChecksumsDirective() {
577 getContext().getCVContext().emitFileChecksums(*this);
578 }
579
emitCVFileChecksumOffsetDirective(unsigned FileNo)580 void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
581 getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
582 }
583
emitBytes(StringRef Data)584 void MCObjectStreamer::emitBytes(StringRef Data) {
585 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
586 MCDataFragment *DF = getOrCreateDataFragment();
587 DF->appendContents(ArrayRef(Data.data(), Data.size()));
588 }
589
emitValueToAlignment(Align Alignment,int64_t Fill,uint8_t FillLen,unsigned MaxBytesToEmit)590 void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
591 uint8_t FillLen,
592 unsigned MaxBytesToEmit) {
593 if (MaxBytesToEmit == 0)
594 MaxBytesToEmit = Alignment.value();
595 insert(getContext().allocFragment<MCAlignFragment>(Alignment, Fill, FillLen,
596 MaxBytesToEmit));
597
598 // Update the maximum alignment on the current section if necessary.
599 MCSection *CurSec = getCurrentSectionOnly();
600 CurSec->ensureMinAlignment(Alignment);
601 }
602
emitCodeAlignment(Align Alignment,const MCSubtargetInfo * STI,unsigned MaxBytesToEmit)603 void MCObjectStreamer::emitCodeAlignment(Align Alignment,
604 const MCSubtargetInfo *STI,
605 unsigned MaxBytesToEmit) {
606 emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
607 auto *F = cast<MCAlignFragment>(getCurrentFragment());
608 F->setEmitNops(true, STI);
609 // With RISC-V style linker relaxation, mark the section as linker-relaxable
610 // if the alignment is larger than the minimum NOP size.
611 unsigned Size;
612 if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F,
613 Size))
614 getCurrentSectionOnly()->setLinkerRelaxable();
615 }
616
emitValueToOffset(const MCExpr * Offset,unsigned char Value,SMLoc Loc)617 void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
618 unsigned char Value,
619 SMLoc Loc) {
620 insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));
621 }
622
623 static std::optional<std::pair<bool, std::string>>
getOffsetAndDataFragment(const MCSymbol & Symbol,uint32_t & RelocOffset,MCDataFragment * & DF)624 getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
625 MCDataFragment *&DF) {
626 if (Symbol.isVariable()) {
627 const MCExpr *SymbolExpr = Symbol.getVariableValue();
628 MCValue OffsetVal;
629 if (!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr))
630 return std::make_pair(false,
631 std::string("symbol in .reloc offset is not "
632 "relocatable"));
633 if (OffsetVal.isAbsolute()) {
634 RelocOffset = OffsetVal.getConstant();
635 MCFragment *Fragment = Symbol.getFragment();
636 // FIXME Support symbols with no DF. For example:
637 // .reloc .data, ENUM_VALUE, <some expr>
638 if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
639 return std::make_pair(false,
640 std::string("symbol in offset has no data "
641 "fragment"));
642 DF = cast<MCDataFragment>(Fragment);
643 return std::nullopt;
644 }
645
646 if (OffsetVal.getSubSym())
647 return std::make_pair(false,
648 std::string(".reloc symbol offset is not "
649 "representable"));
650
651 const MCSymbol &SA = *OffsetVal.getAddSym();
652 if (!SA.isDefined())
653 return std::make_pair(false,
654 std::string("symbol used in the .reloc offset is "
655 "not defined"));
656
657 if (SA.isVariable())
658 return std::make_pair(false,
659 std::string("symbol used in the .reloc offset is "
660 "variable"));
661
662 MCFragment *Fragment = SA.getFragment();
663 // FIXME Support symbols with no DF. For example:
664 // .reloc .data, ENUM_VALUE, <some expr>
665 if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
666 return std::make_pair(false,
667 std::string("symbol in offset has no data "
668 "fragment"));
669 RelocOffset = SA.getOffset() + OffsetVal.getConstant();
670 DF = cast<MCDataFragment>(Fragment);
671 } else {
672 RelocOffset = Symbol.getOffset();
673 MCFragment *Fragment = Symbol.getFragment();
674 // FIXME Support symbols with no DF. For example:
675 // .reloc .data, ENUM_VALUE, <some expr>
676 if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
677 return std::make_pair(false,
678 std::string("symbol in offset has no data "
679 "fragment"));
680 DF = cast<MCDataFragment>(Fragment);
681 }
682 return std::nullopt;
683 }
684
685 std::optional<std::pair<bool, std::string>>
emitRelocDirective(const MCExpr & Offset,StringRef Name,const MCExpr * Expr,SMLoc Loc,const MCSubtargetInfo & STI)686 MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
687 const MCExpr *Expr, SMLoc Loc,
688 const MCSubtargetInfo &STI) {
689 std::optional<MCFixupKind> MaybeKind =
690 Assembler->getBackend().getFixupKind(Name);
691 if (!MaybeKind)
692 return std::make_pair(true, std::string("unknown relocation name"));
693
694 MCFixupKind Kind = *MaybeKind;
695 if (Expr)
696 visitUsedExpr(*Expr);
697 else
698 Expr =
699 MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
700
701 MCDataFragment *DF = getOrCreateDataFragment(&STI);
702 MCValue OffsetVal;
703 if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr))
704 return std::make_pair(false,
705 std::string(".reloc offset is not relocatable"));
706 if (OffsetVal.isAbsolute()) {
707 if (OffsetVal.getConstant() < 0)
708 return std::make_pair(false, std::string(".reloc offset is negative"));
709 DF->addFixup(MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
710 return std::nullopt;
711 }
712 if (OffsetVal.getSubSym())
713 return std::make_pair(false,
714 std::string(".reloc offset is not representable"));
715
716 const MCSymbol &Symbol = *OffsetVal.getAddSym();
717 if (Symbol.isDefined()) {
718 uint32_t SymbolOffset = 0;
719 std::optional<std::pair<bool, std::string>> Error =
720 getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
721
722 if (Error != std::nullopt)
723 return Error;
724
725 DF->addFixup(
726 MCFixup::create(SymbolOffset + OffsetVal.getConstant(), Expr, Kind));
727 return std::nullopt;
728 }
729
730 PendingFixups.emplace_back(
731 &Symbol, DF, MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
732 return std::nullopt;
733 }
734
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)735 void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
736 SMLoc Loc) {
737 assert(getCurrentSectionOnly() && "need a section");
738 insert(
739 getContext().allocFragment<MCFillFragment>(FillValue, 1, NumBytes, Loc));
740 }
741
emitFill(const MCExpr & NumValues,int64_t Size,int64_t Expr,SMLoc Loc)742 void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
743 int64_t Expr, SMLoc Loc) {
744 int64_t IntNumValues;
745 // Do additional checking now if we can resolve the value.
746 if (NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {
747 if (IntNumValues < 0) {
748 getContext().getSourceManager()->PrintMessage(
749 Loc, SourceMgr::DK_Warning,
750 "'.fill' directive with negative repeat count has no effect");
751 return;
752 }
753 // Emit now if we can for better errors.
754 int64_t NonZeroSize = Size > 4 ? 4 : Size;
755 Expr &= ~0ULL >> (64 - NonZeroSize * 8);
756 for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
757 emitIntValue(Expr, NonZeroSize);
758 if (NonZeroSize < Size)
759 emitIntValue(0, Size - NonZeroSize);
760 }
761 return;
762 }
763
764 // Otherwise emit as fragment.
765 assert(getCurrentSectionOnly() && "need a section");
766 insert(
767 getContext().allocFragment<MCFillFragment>(Expr, Size, NumValues, Loc));
768 }
769
emitNops(int64_t NumBytes,int64_t ControlledNopLength,SMLoc Loc,const MCSubtargetInfo & STI)770 void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
771 SMLoc Loc, const MCSubtargetInfo &STI) {
772 assert(getCurrentSectionOnly() && "need a section");
773 insert(getContext().allocFragment<MCNopsFragment>(
774 NumBytes, ControlledNopLength, Loc, STI));
775 }
776
emitFileDirective(StringRef Filename)777 void MCObjectStreamer::emitFileDirective(StringRef Filename) {
778 MCAssembler &Asm = getAssembler();
779 Asm.getWriter().addFileName(Filename);
780 }
781
emitFileDirective(StringRef Filename,StringRef CompilerVersion,StringRef TimeStamp,StringRef Description)782 void MCObjectStreamer::emitFileDirective(StringRef Filename,
783 StringRef CompilerVersion,
784 StringRef TimeStamp,
785 StringRef Description) {
786 MCObjectWriter &W = getAssembler().getWriter();
787 W.addFileName(Filename);
788 if (CompilerVersion.size())
789 W.setCompilerVersion(CompilerVersion);
790 // TODO: add TimeStamp and Description to .file symbol table entry
791 // with the integrated assembler.
792 }
793
emitAddrsig()794 void MCObjectStreamer::emitAddrsig() {
795 getAssembler().getWriter().emitAddrsigSection();
796 }
797
emitAddrsigSym(const MCSymbol * Sym)798 void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
799 getAssembler().getWriter().addAddrsigSymbol(Sym);
800 }
801
finishImpl()802 void MCObjectStreamer::finishImpl() {
803 getContext().RemapDebugPaths();
804
805 // If we are generating dwarf for assembly source files dump out the sections.
806 if (getContext().getGenDwarfForAssembly())
807 MCGenDwarfInfo::Emit(this);
808
809 // Dump out the dwarf file & directory tables and line tables.
810 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
811
812 // Emit pseudo probes for the current module.
813 MCPseudoProbeTable::emit(this);
814
815 resolvePendingFixups();
816 getAssembler().Finish();
817 }
818