1//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
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/MCStreamer.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/BinaryFormat/COFF.h"
14#include "llvm/BinaryFormat/MachO.h"
15#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
16#include "llvm/MC/MCAsmBackend.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/MC/MCCodeView.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCDwarf.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstPrinter.h"
24#include "llvm/MC/MCObjectFileInfo.h"
25#include "llvm/MC/MCPseudoProbe.h"
26#include "llvm/MC/MCRegister.h"
27#include "llvm/MC/MCRegisterInfo.h"
28#include "llvm/MC/MCSection.h"
29#include "llvm/MC/MCSectionCOFF.h"
30#include "llvm/MC/MCSymbol.h"
31#include "llvm/MC/MCWin64EH.h"
32#include "llvm/MC/MCWinEH.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/LEB128.h"
36#include "llvm/Support/MathExtras.h"
37#include "llvm/Support/raw_ostream.h"
38#include <cassert>
39#include <cstdint>
40#include <cstdlib>
41#include <optional>
42#include <utility>
43
44using namespace llvm;
45
46MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) {
47 S.setTargetStreamer(this);
48}
49
50// Pin the vtables to this file.
51MCTargetStreamer::~MCTargetStreamer() = default;
52
53void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {}
54
55void MCTargetStreamer::finish() {}
56
57void MCTargetStreamer::emitConstantPools() {}
58
59void MCTargetStreamer::changeSection(const MCSection *CurSection,
60 MCSection *Section, uint32_t Subsection,
61 raw_ostream &OS) {
62 Section->printSwitchToSection(MAI: *Streamer.getContext().getAsmInfo(),
63 T: Streamer.getContext().getTargetTriple(), OS,
64 Subsection);
65}
66
67void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) {
68 Streamer.emitRawText(String: Directive);
69}
70
71void MCTargetStreamer::emitValue(const MCExpr *Value) {
72 SmallString<128> Str;
73 raw_svector_ostream OS(Str);
74
75 Streamer.getContext().getAsmInfo()->printExpr(OS, *Value);
76 Streamer.emitRawText(String: OS.str());
77}
78
79void MCTargetStreamer::emitRawBytes(StringRef Data) {
80 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
81 const char *Directive = MAI->getData8bitsDirective();
82 for (const unsigned char C : Data.bytes()) {
83 SmallString<128> Str;
84 raw_svector_ostream OS(Str);
85
86 OS << Directive << (unsigned)C;
87 Streamer.emitRawText(String: OS.str());
88 }
89}
90
91void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
92
93MCStreamer::MCStreamer(MCContext &Ctx)
94 : Context(Ctx), CurrentWinFrameInfo(nullptr),
95 CurrentProcWinFrameInfoStartIndex(0) {
96 SectionStack.push_back(Elt: std::pair<MCSectionSubPair, MCSectionSubPair>());
97}
98
99MCStreamer::~MCStreamer() = default;
100
101void MCStreamer::reset() {
102 DwarfFrameInfos.clear();
103 CurrentWinFrameInfo = nullptr;
104 WinFrameInfos.clear();
105 SectionStack.clear();
106 SectionStack.push_back(Elt: std::pair<MCSectionSubPair, MCSectionSubPair>());
107 CurFrag = nullptr;
108}
109
110raw_ostream &MCStreamer::getCommentOS() {
111 // By default, discard comments.
112 return nulls();
113}
114
115unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); }
116ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const {
117 return DwarfFrameInfos;
118}
119
120void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {}
121
122void MCStreamer::addExplicitComment(const Twine &T) {}
123void MCStreamer::emitExplicitComments() {}
124
125void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
126 for (auto &FI : DwarfFrameInfos)
127 FI.CompactUnwindEncoding =
128 (MAB ? MAB->generateCompactUnwindEncoding(FI: &FI, Ctxt: &Context) : 0);
129}
130
131/// EmitIntValue - Special case of EmitValue that avoids the client having to
132/// pass in a MCExpr for constant integers.
133void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) {
134 assert(1 <= Size && Size <= 8 && "Invalid size");
135 assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
136 "Invalid size");
137 const bool IsLittleEndian = Context.getAsmInfo()->isLittleEndian();
138 uint64_t Swapped = support::endian::byte_swap(
139 value: Value, endian: IsLittleEndian ? llvm::endianness::little : llvm::endianness::big);
140 unsigned Index = IsLittleEndian ? 0 : 8 - Size;
141 emitBytes(Data: StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size));
142}
143void MCStreamer::emitIntValue(const APInt &Value) {
144 if (Value.getNumWords() == 1) {
145 emitIntValue(Value: Value.getLimitedValue(), Size: Value.getBitWidth() / 8);
146 return;
147 }
148
149 const bool IsLittleEndianTarget = Context.getAsmInfo()->isLittleEndian();
150 const bool ShouldSwap = sys::IsLittleEndianHost != IsLittleEndianTarget;
151 const APInt Swapped = ShouldSwap ? Value.byteSwap() : Value;
152 const unsigned Size = Value.getBitWidth() / 8;
153 SmallString<10> Tmp;
154 Tmp.resize(N: Size);
155 StoreIntToMemory(IntVal: Swapped, Dst: reinterpret_cast<uint8_t *>(Tmp.data()), StoreBytes: Size);
156 emitBytes(Data: Tmp.str());
157}
158
159/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
160/// client having to pass in a MCExpr for constant integers.
161unsigned MCStreamer::emitULEB128IntValue(uint64_t Value, unsigned PadTo) {
162 SmallString<128> Tmp;
163 raw_svector_ostream OSE(Tmp);
164 encodeULEB128(Value, OS&: OSE, PadTo);
165 emitBytes(Data: OSE.str());
166 return Tmp.size();
167}
168
169/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
170/// client having to pass in a MCExpr for constant integers.
171unsigned MCStreamer::emitSLEB128IntValue(int64_t Value) {
172 SmallString<128> Tmp;
173 raw_svector_ostream OSE(Tmp);
174 encodeSLEB128(Value, OS&: OSE);
175 emitBytes(Data: OSE.str());
176 return Tmp.size();
177}
178
179void MCStreamer::emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
180 emitValueImpl(Value, Size, Loc);
181}
182
183void MCStreamer::emitSymbolValue(const MCSymbol *Sym, unsigned Size,
184 bool IsSectionRelative) {
185 assert((!IsSectionRelative || Size == 4) &&
186 "SectionRelative value requires 4-bytes");
187
188 if (!IsSectionRelative)
189 emitValueImpl(Value: MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext()), Size);
190 else
191 emitCOFFSecRel32(Symbol: Sym, /*Offset=*/0);
192}
193
194/// Emit NumBytes bytes worth of the value specified by FillValue.
195/// This implements directives such as '.space'.
196void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
197 if (NumBytes)
198 emitFill(NumBytes: *MCConstantExpr::create(Value: NumBytes, Ctx&: getContext()), FillValue);
199}
200
201void llvm::MCStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLen,
202 llvm::SMLoc, const MCSubtargetInfo& STI) {}
203
204/// The implementation in this class just redirects to emitFill.
205void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, FillValue: 0); }
206
207Expected<unsigned> MCStreamer::tryEmitDwarfFileDirective(
208 unsigned FileNo, StringRef Directory, StringRef Filename,
209 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
210 unsigned CUID) {
211 return getContext().getDwarfFile(Directory, FileName: Filename, FileNumber: FileNo, Checksum,
212 Source, CUID);
213}
214
215void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
216 StringRef Filename,
217 std::optional<MD5::MD5Result> Checksum,
218 std::optional<StringRef> Source,
219 unsigned CUID) {
220 getContext().setMCLineTableRootFile(CUID, CompilationDir: Directory, Filename, Checksum,
221 Source);
222}
223
224void MCStreamer::emitCFIBKeyFrame() {
225 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
226 if (!CurFrame)
227 return;
228 CurFrame->IsBKeyFrame = true;
229}
230
231void MCStreamer::emitCFIMTETaggedFrame() {
232 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
233 if (!CurFrame)
234 return;
235 CurFrame->IsMTETaggedFrame = true;
236}
237
238void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
239 unsigned Column, unsigned Flags,
240 unsigned Isa, unsigned Discriminator,
241 StringRef FileName, StringRef Comment) {
242 getContext().setCurrentDwarfLoc(FileNum: FileNo, Line, Column, Flags, Isa,
243 Discriminator);
244}
245
246void MCStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) {
247 getContext()
248 .getMCDwarfLineTable(CUID: getContext().getDwarfCompileUnitID())
249 .endCurrentSeqAndEmitLineStreamLabel(MCOS: this, DefLoc: Loc, Name);
250}
251
252MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
253 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
254 if (!Table.getLabel()) {
255 StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix();
256 Table.setLabel(
257 Context.getOrCreateSymbol(Name: Prefix + "line_table_start" + Twine(CUID)));
258 }
259 return Table.getLabel();
260}
261
262bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
263 return !FrameInfoStack.empty();
264}
265
266MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
267 if (!hasUnfinishedDwarfFrameInfo()) {
268 getContext().reportError(L: getStartTokLoc(),
269 Msg: "this directive must appear between "
270 ".cfi_startproc and .cfi_endproc directives");
271 return nullptr;
272 }
273 return &DwarfFrameInfos[FrameInfoStack.back().first];
274}
275
276bool MCStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
277 ArrayRef<uint8_t> Checksum,
278 unsigned ChecksumKind) {
279 return getContext().getCVContext().addFile(OS&: *this, FileNumber: FileNo, Filename, ChecksumBytes: Checksum,
280 ChecksumKind);
281}
282
283bool MCStreamer::emitCVFuncIdDirective(unsigned FunctionId) {
284 return getContext().getCVContext().recordFunctionId(FuncId: FunctionId);
285}
286
287bool MCStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,
288 unsigned IAFunc, unsigned IAFile,
289 unsigned IALine, unsigned IACol,
290 SMLoc Loc) {
291 if (getContext().getCVContext().getCVFunctionInfo(FuncId: IAFunc) == nullptr) {
292 getContext().reportError(L: Loc, Msg: "parent function id not introduced by "
293 ".cv_func_id or .cv_inline_site_id");
294 return true;
295 }
296
297 return getContext().getCVContext().recordInlinedCallSiteId(
298 FuncId: FunctionId, IAFunc, IAFile, IALine, IACol);
299}
300
301void MCStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
302 unsigned Line, unsigned Column,
303 bool PrologueEnd, bool IsStmt,
304 StringRef FileName, SMLoc Loc) {}
305
306bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
307 SMLoc Loc) {
308 CodeViewContext &CVC = getContext().getCVContext();
309 MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId);
310 if (!FI) {
311 getContext().reportError(
312 L: Loc, Msg: "function id not introduced by .cv_func_id or .cv_inline_site_id");
313 return false;
314 }
315
316 // Track the section
317 if (FI->Section == nullptr)
318 FI->Section = getCurrentSectionOnly();
319 else if (FI->Section != getCurrentSectionOnly()) {
320 getContext().reportError(
321 L: Loc,
322 Msg: "all .cv_loc directives for a function must be in the same section");
323 return false;
324 }
325 return true;
326}
327
328void MCStreamer::emitCVLinetableDirective(unsigned FunctionId,
329 const MCSymbol *Begin,
330 const MCSymbol *End) {}
331
332void MCStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
333 unsigned SourceFileId,
334 unsigned SourceLineNum,
335 const MCSymbol *FnStartSym,
336 const MCSymbol *FnEndSym) {}
337
338/// Only call this on endian-specific types like ulittle16_t and little32_t, or
339/// structs composed of them.
340template <typename T>
341static void copyBytesForDefRange(SmallString<20> &BytePrefix,
342 codeview::SymbolKind SymKind,
343 const T &DefRangeHeader) {
344 BytePrefix.resize(N: 2 + sizeof(T));
345 codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind);
346 memcpy(dest: &BytePrefix[0], src: &SymKindLE, n: 2);
347 memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
348}
349
350void MCStreamer::emitCVDefRangeDirective(
351 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
352 StringRef FixedSizePortion) {}
353
354void MCStreamer::emitCVDefRangeDirective(
355 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
356 codeview::DefRangeRegisterRelHeader DRHdr) {
357 SmallString<20> BytePrefix;
358 copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_REGISTER_REL, DefRangeHeader: DRHdr);
359 emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix);
360}
361
362void MCStreamer::emitCVDefRangeDirective(
363 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
364 codeview::DefRangeSubfieldRegisterHeader DRHdr) {
365 SmallString<20> BytePrefix;
366 copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_SUBFIELD_REGISTER,
367 DefRangeHeader: DRHdr);
368 emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix);
369}
370
371void MCStreamer::emitCVDefRangeDirective(
372 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
373 codeview::DefRangeRegisterHeader DRHdr) {
374 SmallString<20> BytePrefix;
375 copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_REGISTER, DefRangeHeader: DRHdr);
376 emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix);
377}
378
379void MCStreamer::emitCVDefRangeDirective(
380 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
381 codeview::DefRangeFramePointerRelHeader DRHdr) {
382 SmallString<20> BytePrefix;
383 copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_FRAMEPOINTER_REL,
384 DefRangeHeader: DRHdr);
385 emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix);
386}
387
388void MCStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
389 MCSymbol *EHSymbol) {
390}
391
392void MCStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
393 switchSectionNoPrint(Section: getContext().getObjectFileInfo()->getTextSection());
394}
395
396void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
397 Symbol->redefineIfPossible();
398
399 if (!Symbol->isUndefined() || Symbol->isVariable())
400 return getContext().reportError(L: Loc, Msg: "symbol '" + Twine(Symbol->getName()) +
401 "' is already defined");
402
403 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
404 assert(getCurrentSectionOnly() && "Cannot emit before setting section!");
405 assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
406 assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
407
408 Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());
409
410 MCTargetStreamer *TS = getTargetStreamer();
411 if (TS)
412 TS->emitLabel(Symbol);
413}
414
415void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol,
416 const MCExpr *Value) {}
417
418void MCStreamer::emitCFISections(bool EH, bool Debug) {}
419
420void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
421 if (!FrameInfoStack.empty() &&
422 getCurrentSectionOnly() == FrameInfoStack.back().second)
423 return getContext().reportError(
424 L: Loc, Msg: "starting new .cfi frame before finishing the previous one");
425
426 MCDwarfFrameInfo Frame;
427 Frame.IsSimple = IsSimple;
428 emitCFIStartProcImpl(Frame);
429
430 const MCAsmInfo* MAI = Context.getAsmInfo();
431 if (MAI) {
432 for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) {
433 if (Inst.getOperation() == MCCFIInstruction::OpDefCfa ||
434 Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister ||
435 Inst.getOperation() == MCCFIInstruction::OpLLVMDefAspaceCfa) {
436 Frame.CurrentCfaRegister = Inst.getRegister();
437 }
438 }
439 }
440
441 FrameInfoStack.emplace_back(Args: DwarfFrameInfos.size(), Args: getCurrentSectionOnly());
442 DwarfFrameInfos.push_back(x: std::move(Frame));
443}
444
445void MCStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
446}
447
448void MCStreamer::emitCFIEndProc() {
449 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
450 if (!CurFrame)
451 return;
452 emitCFIEndProcImpl(CurFrame&: *CurFrame);
453 FrameInfoStack.pop_back();
454}
455
456void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
457 // Put a dummy non-null value in Frame.End to mark that this frame has been
458 // closed.
459 Frame.End = (MCSymbol *)1;
460}
461
462MCSymbol *MCStreamer::emitLineTableLabel() {
463 // Create a label and insert it into the line table and return this label
464 const MCDwarfLoc &DwarfLoc = getContext().getCurrentDwarfLoc();
465
466 MCSymbol *LineStreamLabel = getContext().createTempSymbol();
467 MCDwarfLineEntry LabelLineEntry(nullptr, DwarfLoc, LineStreamLabel);
468 getContext()
469 .getMCDwarfLineTable(CUID: getContext().getDwarfCompileUnitID())
470 .getMCLineSections()
471 .addLineEntry(LineEntry: LabelLineEntry, Sec: getCurrentSectionOnly() /*Section*/);
472
473 return LineStreamLabel;
474}
475
476MCSymbol *MCStreamer::emitCFILabel() {
477 // Return a dummy non-null value so that label fields appear filled in when
478 // generating textual assembly.
479 return (MCSymbol *)1;
480}
481
482void MCStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) {
483 MCSymbol *Label = emitCFILabel();
484 MCCFIInstruction Instruction =
485 MCCFIInstruction::cfiDefCfa(L: Label, Register, Offset, Loc);
486 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
487 if (!CurFrame)
488 return;
489 CurFrame->Instructions.push_back(x: std::move(Instruction));
490 CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
491}
492
493void MCStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) {
494 MCSymbol *Label = emitCFILabel();
495 MCCFIInstruction Instruction =
496 MCCFIInstruction::cfiDefCfaOffset(L: Label, Offset);
497 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
498 if (!CurFrame)
499 return;
500 CurFrame->Instructions.push_back(x: std::move(Instruction));
501}
502
503void MCStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) {
504 MCSymbol *Label = emitCFILabel();
505 MCCFIInstruction Instruction =
506 MCCFIInstruction::createAdjustCfaOffset(L: Label, Adjustment, Loc);
507 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
508 if (!CurFrame)
509 return;
510 CurFrame->Instructions.push_back(x: std::move(Instruction));
511}
512
513void MCStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) {
514 MCSymbol *Label = emitCFILabel();
515 MCCFIInstruction Instruction =
516 MCCFIInstruction::createDefCfaRegister(L: Label, Register, Loc);
517 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
518 if (!CurFrame)
519 return;
520 CurFrame->Instructions.push_back(x: std::move(Instruction));
521 CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
522}
523
524void MCStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
525 int64_t AddressSpace, SMLoc Loc) {
526 MCSymbol *Label = emitCFILabel();
527 MCCFIInstruction Instruction = MCCFIInstruction::createLLVMDefAspaceCfa(
528 L: Label, Register, Offset, AddressSpace, Loc);
529 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
530 if (!CurFrame)
531 return;
532 CurFrame->Instructions.push_back(x: std::move(Instruction));
533 CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
534}
535
536void MCStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
537 MCSymbol *Label = emitCFILabel();
538 MCCFIInstruction Instruction =
539 MCCFIInstruction::createOffset(L: Label, Register, Offset, Loc);
540 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
541 if (!CurFrame)
542 return;
543 CurFrame->Instructions.push_back(x: std::move(Instruction));
544}
545
546void MCStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
547 MCSymbol *Label = emitCFILabel();
548 MCCFIInstruction Instruction =
549 MCCFIInstruction::createRelOffset(L: Label, Register, Offset, Loc);
550 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
551 if (!CurFrame)
552 return;
553 CurFrame->Instructions.push_back(x: std::move(Instruction));
554}
555
556void MCStreamer::emitCFIPersonality(const MCSymbol *Sym,
557 unsigned Encoding) {
558 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
559 if (!CurFrame)
560 return;
561 CurFrame->Personality = Sym;
562 CurFrame->PersonalityEncoding = Encoding;
563}
564
565void MCStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
566 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
567 if (!CurFrame)
568 return;
569 CurFrame->Lsda = Sym;
570 CurFrame->LsdaEncoding = Encoding;
571}
572
573void MCStreamer::emitCFIRememberState(SMLoc Loc) {
574 MCSymbol *Label = emitCFILabel();
575 MCCFIInstruction Instruction =
576 MCCFIInstruction::createRememberState(L: Label, Loc);
577 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
578 if (!CurFrame)
579 return;
580 CurFrame->Instructions.push_back(x: std::move(Instruction));
581}
582
583void MCStreamer::emitCFIRestoreState(SMLoc Loc) {
584 // FIXME: Error if there is no matching cfi_remember_state.
585 MCSymbol *Label = emitCFILabel();
586 MCCFIInstruction Instruction =
587 MCCFIInstruction::createRestoreState(L: Label, Loc);
588 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
589 if (!CurFrame)
590 return;
591 CurFrame->Instructions.push_back(x: std::move(Instruction));
592}
593
594void MCStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) {
595 MCSymbol *Label = emitCFILabel();
596 MCCFIInstruction Instruction =
597 MCCFIInstruction::createSameValue(L: Label, Register, Loc);
598 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
599 if (!CurFrame)
600 return;
601 CurFrame->Instructions.push_back(x: std::move(Instruction));
602}
603
604void MCStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) {
605 MCSymbol *Label = emitCFILabel();
606 MCCFIInstruction Instruction =
607 MCCFIInstruction::createRestore(L: Label, Register, Loc);
608 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
609 if (!CurFrame)
610 return;
611 CurFrame->Instructions.push_back(x: std::move(Instruction));
612}
613
614void MCStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) {
615 MCSymbol *Label = emitCFILabel();
616 MCCFIInstruction Instruction =
617 MCCFIInstruction::createEscape(L: Label, Vals: Values, Loc, Comment: "");
618 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
619 if (!CurFrame)
620 return;
621 CurFrame->Instructions.push_back(x: std::move(Instruction));
622}
623
624void MCStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) {
625 MCSymbol *Label = emitCFILabel();
626 MCCFIInstruction Instruction =
627 MCCFIInstruction::createGnuArgsSize(L: Label, Size, Loc);
628 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
629 if (!CurFrame)
630 return;
631 CurFrame->Instructions.push_back(x: std::move(Instruction));
632}
633
634void MCStreamer::emitCFISignalFrame() {
635 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
636 if (!CurFrame)
637 return;
638 CurFrame->IsSignalFrame = true;
639}
640
641void MCStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) {
642 MCSymbol *Label = emitCFILabel();
643 MCCFIInstruction Instruction =
644 MCCFIInstruction::createUndefined(L: Label, Register, Loc);
645 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
646 if (!CurFrame)
647 return;
648 CurFrame->Instructions.push_back(x: std::move(Instruction));
649}
650
651void MCStreamer::emitCFIRegister(int64_t Register1, int64_t Register2,
652 SMLoc Loc) {
653 MCSymbol *Label = emitCFILabel();
654 MCCFIInstruction Instruction =
655 MCCFIInstruction::createRegister(L: Label, Register1, Register2, Loc);
656 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
657 if (!CurFrame)
658 return;
659 CurFrame->Instructions.push_back(x: std::move(Instruction));
660}
661
662void MCStreamer::emitCFIWindowSave(SMLoc Loc) {
663 MCSymbol *Label = emitCFILabel();
664 MCCFIInstruction Instruction = MCCFIInstruction::createWindowSave(L: Label, Loc);
665 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
666 if (!CurFrame)
667 return;
668 CurFrame->Instructions.push_back(x: std::move(Instruction));
669}
670
671void MCStreamer::emitCFINegateRAState(SMLoc Loc) {
672 MCSymbol *Label = emitCFILabel();
673 MCCFIInstruction Instruction =
674 MCCFIInstruction::createNegateRAState(L: Label, Loc);
675 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
676 if (!CurFrame)
677 return;
678 CurFrame->Instructions.push_back(x: std::move(Instruction));
679}
680
681void MCStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) {
682 MCSymbol *Label = emitCFILabel();
683 MCCFIInstruction Instruction =
684 MCCFIInstruction::createNegateRAStateWithPC(L: Label, Loc);
685 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
686 if (!CurFrame)
687 return;
688 CurFrame->Instructions.push_back(x: std::move(Instruction));
689}
690
691void MCStreamer::emitCFIReturnColumn(int64_t Register) {
692 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
693 if (!CurFrame)
694 return;
695 CurFrame->RAReg = Register;
696}
697
698void MCStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
699 MCSymbol *Label = emitCFILabel();
700 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
701 if (MCDwarfFrameInfo *F = getCurrentDwarfFrameInfo())
702 F->Instructions.push_back(x: MCCFIInstruction::createLabel(L: Label, CfiLabel: Sym, Loc));
703}
704
705void MCStreamer::emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
706 MCSymbol *Label = emitCFILabel();
707 MCCFIInstruction Instruction =
708 MCCFIInstruction::createValOffset(L: Label, Register, Offset, Loc);
709 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
710 if (!CurFrame)
711 return;
712 CurFrame->Instructions.push_back(x: std::move(Instruction));
713}
714
715WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
716 const MCAsmInfo *MAI = Context.getAsmInfo();
717 if (!MAI->usesWindowsCFI()) {
718 getContext().reportError(
719 L: Loc, Msg: ".seh_* directives are not supported on this target");
720 return nullptr;
721 }
722 if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
723 getContext().reportError(
724 L: Loc, Msg: ".seh_ directive must appear within an active frame");
725 return nullptr;
726 }
727 return CurrentWinFrameInfo;
728}
729
730void MCStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
731 const MCAsmInfo *MAI = Context.getAsmInfo();
732 if (!MAI->usesWindowsCFI())
733 return getContext().reportError(
734 L: Loc, Msg: ".seh_* directives are not supported on this target");
735 if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
736 getContext().reportError(
737 L: Loc, Msg: "Starting a function before ending the previous one!");
738
739 MCSymbol *StartProc = emitCFILabel();
740
741 CurrentProcWinFrameInfoStartIndex = WinFrameInfos.size();
742 WinFrameInfos.emplace_back(
743 args: std::make_unique<WinEH::FrameInfo>(args&: Symbol, args&: StartProc));
744 CurrentWinFrameInfo = WinFrameInfos.back().get();
745 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
746 CurrentWinFrameInfo->FunctionLoc = Loc;
747}
748
749void MCStreamer::emitWinCFIEndProc(SMLoc Loc) {
750 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
751 if (!CurFrame)
752 return;
753 if (CurFrame->ChainedParent)
754 getContext().reportError(L: Loc, Msg: "Not all chained regions terminated!");
755
756 MCSymbol *Label = emitCFILabel();
757 CurFrame->End = Label;
758 if (!CurFrame->FuncletOrFuncEnd)
759 CurFrame->FuncletOrFuncEnd = CurFrame->End;
760
761 for (size_t I = CurrentProcWinFrameInfoStartIndex, E = WinFrameInfos.size();
762 I != E; ++I)
763 emitWindowsUnwindTables(Frame: WinFrameInfos[I].get());
764 switchSection(Section: CurFrame->TextSection);
765}
766
767void MCStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
768 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
769 if (!CurFrame)
770 return;
771 if (CurFrame->ChainedParent)
772 getContext().reportError(L: Loc, Msg: "Not all chained regions terminated!");
773
774 MCSymbol *Label = emitCFILabel();
775 CurFrame->FuncletOrFuncEnd = Label;
776}
777
778void MCStreamer::emitWinCFIStartChained(SMLoc Loc) {
779 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
780 if (!CurFrame)
781 return;
782
783 MCSymbol *StartProc = emitCFILabel();
784
785 WinFrameInfos.emplace_back(args: std::make_unique<WinEH::FrameInfo>(
786 args&: CurFrame->Function, args&: StartProc, args&: CurFrame));
787 CurrentWinFrameInfo = WinFrameInfos.back().get();
788 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
789}
790
791void MCStreamer::emitWinCFIEndChained(SMLoc Loc) {
792 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
793 if (!CurFrame)
794 return;
795 if (!CurFrame->ChainedParent)
796 return getContext().reportError(
797 L: Loc, Msg: "End of a chained region outside a chained region!");
798
799 MCSymbol *Label = emitCFILabel();
800
801 CurFrame->End = Label;
802 CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
803}
804
805void MCStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
806 SMLoc Loc) {
807 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
808 if (!CurFrame)
809 return;
810 if (CurFrame->ChainedParent)
811 return getContext().reportError(
812 L: Loc, Msg: "Chained unwind areas can't have handlers!");
813 CurFrame->ExceptionHandler = Sym;
814 if (!Except && !Unwind)
815 getContext().reportError(L: Loc, Msg: "Don't know what kind of handler this is!");
816 if (Unwind)
817 CurFrame->HandlesUnwind = true;
818 if (Except)
819 CurFrame->HandlesExceptions = true;
820}
821
822void MCStreamer::emitWinEHHandlerData(SMLoc Loc) {
823 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
824 if (!CurFrame)
825 return;
826 if (CurFrame->ChainedParent)
827 getContext().reportError(L: Loc, Msg: "Chained unwind areas can't have handlers!");
828}
829
830void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
831 const MCSymbolRefExpr *To, uint64_t Count) {
832}
833
834static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
835 MCSection *MainCFISec,
836 const MCSection *TextSec) {
837 // If this is the main .text section, use the main unwind info section.
838 if (TextSec == Context.getObjectFileInfo()->getTextSection())
839 return MainCFISec;
840
841 const auto *TextSecCOFF = cast<MCSectionCOFF>(Val: TextSec);
842 auto *MainCFISecCOFF = cast<MCSectionCOFF>(Val: MainCFISec);
843 unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextID: NextWinCFIID);
844
845 // If this section is COMDAT, this unwind section should be COMDAT associative
846 // with its group.
847 const MCSymbol *KeySym = nullptr;
848 if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
849 KeySym = TextSecCOFF->getCOMDATSymbol();
850
851 // In a GNU environment, we can't use associative comdats. Instead, do what
852 // GCC does, which is to make plain comdat selectany section named like
853 // ".[px]data$_Z3foov".
854 if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
855 std::string SectionName = (MainCFISecCOFF->getName() + "$" +
856 TextSecCOFF->getName().split(Separator: '$').second)
857 .str();
858 return Context.getCOFFSection(Section: SectionName,
859 Characteristics: MainCFISecCOFF->getCharacteristics() |
860 COFF::IMAGE_SCN_LNK_COMDAT,
861 COMDATSymName: "", Selection: COFF::IMAGE_COMDAT_SELECT_ANY);
862 }
863 }
864
865 return Context.getAssociativeCOFFSection(Sec: MainCFISecCOFF, KeySym, UniqueID);
866}
867
868MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
869 return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID,
870 MainCFISec: getContext().getObjectFileInfo()->getPDataSection(),
871 TextSec);
872}
873
874MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
875 return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID,
876 MainCFISec: getContext().getObjectFileInfo()->getXDataSection(),
877 TextSec);
878}
879
880void MCStreamer::emitSyntaxDirective() {}
881
882static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
883 return Ctx.getRegisterInfo()->getSEHRegNum(RegNum: Reg);
884}
885
886void MCStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
887 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
888 if (!CurFrame)
889 return;
890
891 MCSymbol *Label = emitCFILabel();
892
893 WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(
894 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register));
895 CurFrame->Instructions.push_back(x: Inst);
896}
897
898void MCStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
899 SMLoc Loc) {
900 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
901 if (!CurFrame)
902 return;
903 if (CurFrame->LastFrameInst >= 0)
904 return getContext().reportError(
905 L: Loc, Msg: "frame register and offset can be set at most once");
906 if (Offset & 0x0F)
907 return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16");
908 if (Offset > 240)
909 return getContext().reportError(
910 L: Loc, Msg: "frame offset must be less than or equal to 240");
911
912 MCSymbol *Label = emitCFILabel();
913
914 WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(
915 L: Label, Reg: encodeSEHRegNum(Ctx&: getContext(), Reg: Register), Off: Offset);
916 CurFrame->LastFrameInst = CurFrame->Instructions.size();
917 CurFrame->Instructions.push_back(x: Inst);
918}
919
920void MCStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
921 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
922 if (!CurFrame)
923 return;
924 if (Size == 0)
925 return getContext().reportError(L: Loc,
926 Msg: "stack allocation size must be non-zero");
927 if (Size & 7)
928 return getContext().reportError(
929 L: Loc, Msg: "stack allocation size is not a multiple of 8");
930
931 MCSymbol *Label = emitCFILabel();
932
933 WinEH::Instruction Inst = Win64EH::Instruction::Alloc(L: Label, Size);
934 CurFrame->Instructions.push_back(x: Inst);
935}
936
937void MCStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
938 SMLoc Loc) {
939 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
940 if (!CurFrame)
941 return;
942
943 if (Offset & 7)
944 return getContext().reportError(
945 L: Loc, Msg: "register save offset is not 8 byte aligned");
946
947 MCSymbol *Label = emitCFILabel();
948
949 WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(
950 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset);
951 CurFrame->Instructions.push_back(x: Inst);
952}
953
954void MCStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
955 SMLoc Loc) {
956 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
957 if (!CurFrame)
958 return;
959 if (Offset & 0x0F)
960 return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16");
961
962 MCSymbol *Label = emitCFILabel();
963
964 WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(
965 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset);
966 CurFrame->Instructions.push_back(x: Inst);
967}
968
969void MCStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
970 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
971 if (!CurFrame)
972 return;
973 if (!CurFrame->Instructions.empty())
974 return getContext().reportError(
975 L: Loc, Msg: "If present, PushMachFrame must be the first UOP");
976
977 MCSymbol *Label = emitCFILabel();
978
979 WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(L: Label, Code);
980 CurFrame->Instructions.push_back(x: Inst);
981}
982
983void MCStreamer::emitWinCFIEndProlog(SMLoc Loc) {
984 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
985 if (!CurFrame)
986 return;
987
988 MCSymbol *Label = emitCFILabel();
989
990 CurFrame->PrologEnd = Label;
991}
992
993void MCStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) {
994 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
995 if (!CurFrame)
996 return;
997
998 if (!CurFrame->PrologEnd)
999 return getContext().reportError(
1000 L: Loc, Msg: "starting epilogue (.seh_startepilogue) before prologue has ended "
1001 "(.seh_endprologue) in " +
1002 CurFrame->Function->getName());
1003
1004 MCSymbol *Label = emitCFILabel();
1005 CurrentWinEpilog =
1006 &CurFrame->EpilogMap.insert_or_assign(Key: Label, Val: WinEH::FrameInfo::Epilog())
1007 .first->second;
1008 CurrentWinEpilog->Start = Label;
1009 CurrentWinEpilog->Loc = Loc;
1010}
1011
1012void MCStreamer::emitWinCFIEndEpilogue(SMLoc Loc) {
1013 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1014 if (!CurFrame)
1015 return;
1016
1017 if (!CurrentWinEpilog)
1018 return getContext().reportError(L: Loc, Msg: "Stray .seh_endepilogue in " +
1019 CurFrame->Function->getName());
1020
1021 if ((CurFrame->Version >= 2) && !CurrentWinEpilog->UnwindV2Start)
1022 return getContext().reportError(L: Loc, Msg: "Missing .seh_unwindv2start in " +
1023 CurFrame->Function->getName());
1024
1025 CurrentWinEpilog->End = emitCFILabel();
1026 CurrentWinEpilog = nullptr;
1027}
1028
1029void MCStreamer::emitWinCFIUnwindV2Start(SMLoc Loc) {
1030 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1031 if (!CurFrame)
1032 return;
1033
1034 if (!CurrentWinEpilog)
1035 return getContext().reportError(L: Loc, Msg: "Stray .seh_unwindv2start in " +
1036 CurFrame->Function->getName());
1037
1038 if (CurrentWinEpilog->UnwindV2Start)
1039 return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindv2start in " +
1040 CurFrame->Function->getName());
1041
1042 MCSymbol *Label = emitCFILabel();
1043 CurrentWinEpilog->UnwindV2Start = Label;
1044}
1045
1046void MCStreamer::emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc) {
1047 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1048 if (!CurFrame)
1049 return;
1050
1051 if (CurFrame->Version != WinEH::FrameInfo::DefaultVersion)
1052 return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindversion in " +
1053 CurFrame->Function->getName());
1054
1055 if (Version != 2)
1056 return getContext().reportError(
1057 L: Loc, Msg: "Unsupported version specified in .seh_unwindversion in " +
1058 CurFrame->Function->getName());
1059
1060 CurFrame->Version = Version;
1061}
1062
1063void MCStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {}
1064
1065void MCStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {}
1066
1067void MCStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {}
1068
1069void MCStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
1070
1071void MCStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
1072
1073void MCStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {}
1074
1075void MCStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {}
1076
1077/// EmitRawText - If this file is backed by an assembly streamer, this dumps
1078/// the specified string in the output .s file. This capability is
1079/// indicated by the hasRawTextSupport() predicate.
1080void MCStreamer::emitRawTextImpl(StringRef String) {
1081 // This is not llvm_unreachable for the sake of out of tree backend
1082 // developers who may not have assembly streamers and should serve as a
1083 // reminder to not accidentally call EmitRawText in the absence of such.
1084 report_fatal_error(reason: "EmitRawText called on an MCStreamer that doesn't support "
1085 "it (target backend is likely missing an AsmStreamer "
1086 "implementation)");
1087}
1088
1089void MCStreamer::emitRawText(const Twine &T) {
1090 SmallString<128> Str;
1091 emitRawTextImpl(String: T.toStringRef(Out&: Str));
1092}
1093
1094void MCStreamer::emitWindowsUnwindTables() {}
1095
1096void MCStreamer::emitWindowsUnwindTables(WinEH::FrameInfo *Frame) {}
1097
1098void MCStreamer::finish(SMLoc EndLoc) {
1099 if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
1100 (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
1101 getContext().reportError(L: EndLoc, Msg: "Unfinished frame!");
1102 return;
1103 }
1104
1105 MCTargetStreamer *TS = getTargetStreamer();
1106 if (TS)
1107 TS->finish();
1108
1109 finishImpl();
1110}
1111
1112void MCStreamer::maybeEmitDwarf64Mark() {
1113 if (Context.getDwarfFormat() != dwarf::DWARF64)
1114 return;
1115 AddComment(T: "DWARF64 Mark");
1116 emitInt32(Value: dwarf::DW_LENGTH_DWARF64);
1117}
1118
1119void MCStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
1120 assert(Context.getDwarfFormat() == dwarf::DWARF64 ||
1121 Length <= dwarf::DW_LENGTH_lo_reserved);
1122 maybeEmitDwarf64Mark();
1123 AddComment(T: Comment);
1124 emitIntValue(Value: Length, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat()));
1125}
1126
1127MCSymbol *MCStreamer::emitDwarfUnitLength(const Twine &Prefix,
1128 const Twine &Comment) {
1129 maybeEmitDwarf64Mark();
1130 AddComment(T: Comment);
1131 MCSymbol *Lo = Context.createTempSymbol(Name: Prefix + "_start");
1132 MCSymbol *Hi = Context.createTempSymbol(Name: Prefix + "_end");
1133
1134 emitAbsoluteSymbolDiff(
1135 Hi, Lo, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat()));
1136 // emit the begin symbol after we generate the length field.
1137 emitLabel(Symbol: Lo);
1138 // Return the Hi symbol to the caller.
1139 return Hi;
1140}
1141
1142void MCStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
1143 // Set the value of the symbol, as we are at the start of the line table.
1144 emitLabel(Symbol: StartSym);
1145}
1146
1147void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
1148 visitUsedExpr(Expr: *Value);
1149 Symbol->setVariableValue(Value);
1150
1151 MCTargetStreamer *TS = getTargetStreamer();
1152 if (TS)
1153 TS->emitAssignment(Symbol, Value);
1154}
1155
1156void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
1157 uint64_t Address, const MCInst &Inst,
1158 const MCSubtargetInfo &STI,
1159 raw_ostream &OS) {
1160 InstPrinter.printInst(MI: &Inst, Address, Annot: "", STI, OS);
1161}
1162
1163void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
1164}
1165
1166void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
1167 switch (Expr.getKind()) {
1168 case MCExpr::Target:
1169 cast<MCTargetExpr>(Val: Expr).visitUsedExpr(Streamer&: *this);
1170 break;
1171
1172 case MCExpr::Constant:
1173 break;
1174
1175 case MCExpr::Binary: {
1176 const MCBinaryExpr &BE = cast<MCBinaryExpr>(Val: Expr);
1177 visitUsedExpr(Expr: *BE.getLHS());
1178 visitUsedExpr(Expr: *BE.getRHS());
1179 break;
1180 }
1181
1182 case MCExpr::SymbolRef:
1183 visitUsedSymbol(Sym: cast<MCSymbolRefExpr>(Val: Expr).getSymbol());
1184 break;
1185
1186 case MCExpr::Unary:
1187 visitUsedExpr(Expr: *cast<MCUnaryExpr>(Val: Expr).getSubExpr());
1188 break;
1189
1190 case MCExpr::Specifier:
1191 visitUsedExpr(Expr: *cast<MCSpecifierExpr>(Val: Expr).getSubExpr());
1192 break;
1193 }
1194}
1195
1196void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
1197 // Scan for values.
1198 for (unsigned i = Inst.getNumOperands(); i--;)
1199 if (Inst.getOperand(i).isExpr())
1200 visitUsedExpr(Expr: *Inst.getOperand(i).getExpr());
1201}
1202
1203void MCStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
1204 uint64_t Attr, uint64_t Discriminator,
1205 const MCPseudoProbeInlineStack &InlineStack,
1206 MCSymbol *FnSym) {
1207 auto &Context = getContext();
1208
1209 // Create a symbol at in the current section for use in the probe.
1210 MCSymbol *ProbeSym = Context.createTempSymbol();
1211
1212 // Set the value of the symbol to use for the MCPseudoProbe.
1213 emitLabel(Symbol: ProbeSym);
1214
1215 // Create a (local) probe entry with the symbol.
1216 MCPseudoProbe Probe(ProbeSym, Guid, Index, Type, Attr, Discriminator);
1217
1218 // Add the probe entry to this section's entries.
1219 Context.getMCPseudoProbeTable().getProbeSections().addPseudoProbe(
1220 FuncSym: FnSym, Probe, InlineStack);
1221}
1222
1223void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
1224 unsigned Size) {
1225 // Get the Hi-Lo expression.
1226 const MCExpr *Diff =
1227 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context),
1228 RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context);
1229
1230 const MCAsmInfo *MAI = Context.getAsmInfo();
1231 if (!MAI->doesSetDirectiveSuppressReloc()) {
1232 emitValue(Value: Diff, Size);
1233 return;
1234 }
1235
1236 // Otherwise, emit with .set (aka assignment).
1237 MCSymbol *SetLabel = Context.createTempSymbol(Name: "set");
1238 emitAssignment(Symbol: SetLabel, Value: Diff);
1239 emitSymbolValue(Sym: SetLabel, Size);
1240}
1241
1242void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
1243 const MCSymbol *Lo) {
1244 // Get the Hi-Lo expression.
1245 const MCExpr *Diff =
1246 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context),
1247 RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context);
1248
1249 emitULEB128Value(Value: Diff);
1250}
1251
1252void MCStreamer::emitSubsectionsViaSymbols() {
1253 llvm_unreachable(
1254 "emitSubsectionsViaSymbols only supported on Mach-O targets");
1255}
1256void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
1257void MCStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
1258 llvm_unreachable("this directive only supported on COFF targets");
1259}
1260void MCStreamer::endCOFFSymbolDef() {
1261 llvm_unreachable("this directive only supported on COFF targets");
1262}
1263void MCStreamer::emitFileDirective(StringRef Filename) {}
1264void MCStreamer::emitFileDirective(StringRef Filename,
1265 StringRef CompilerVersion,
1266 StringRef TimeStamp, StringRef Description) {
1267}
1268void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
1269 llvm_unreachable("this directive only supported on COFF targets");
1270}
1271void MCStreamer::emitCOFFSymbolType(int Type) {
1272 llvm_unreachable("this directive only supported on COFF targets");
1273}
1274void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
1275 MCSymbol *CsectSym,
1276 Align Alignment) {
1277 llvm_unreachable("this directive only supported on XCOFF targets");
1278}
1279
1280void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
1281 MCSymbolAttr Linkage,
1282 MCSymbolAttr Visibility) {
1283 llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on "
1284 "XCOFF targets");
1285}
1286
1287void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
1288 StringRef Rename) {}
1289
1290void MCStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
1291 llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
1292}
1293
1294void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
1295 const MCSymbol *Trap,
1296 unsigned Lang, unsigned Reason,
1297 unsigned FunctionSize,
1298 bool hasDebug) {
1299 report_fatal_error(reason: "emitXCOFFExceptDirective is only supported on "
1300 "XCOFF targets");
1301}
1302
1303void MCStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
1304 llvm_unreachable("emitXCOFFCInfoSym is only supported on"
1305 "XCOFF targets");
1306}
1307
1308void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
1309void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
1310 StringRef Name, bool KeepOriginalSym) {}
1311void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1312 Align ByteAlignment) {}
1313void MCStreamer::emitZerofill(MCSection *, MCSymbol *, uint64_t, Align, SMLoc) {
1314}
1315void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1316 uint64_t Size, Align ByteAlignment) {}
1317void MCStreamer::changeSection(MCSection *Section, uint32_t) {
1318 CurFrag = &Section->getDummyFragment();
1319}
1320void MCStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
1321void MCStreamer::emitBytes(StringRef Data) {}
1322void MCStreamer::emitBinaryData(StringRef Data) { emitBytes(Data); }
1323void MCStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
1324 visitUsedExpr(Expr: *Value);
1325}
1326void MCStreamer::emitULEB128Value(const MCExpr *Value) {}
1327void MCStreamer::emitSLEB128Value(const MCExpr *Value) {}
1328void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
1329void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
1330 SMLoc Loc) {}
1331void MCStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
1332 unsigned ValueSize,
1333 unsigned MaxBytesToEmit) {}
1334void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,
1335 unsigned MaxBytesToEmit) {}
1336void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
1337 SMLoc Loc) {}
1338void MCStreamer::emitBundleAlignMode(Align Alignment) {}
1339void MCStreamer::emitBundleLock(bool AlignToEnd) {}
1340void MCStreamer::finishImpl() {}
1341void MCStreamer::emitBundleUnlock() {}
1342
1343bool MCStreamer::popSection() {
1344 if (SectionStack.size() <= 1)
1345 return false;
1346 auto I = SectionStack.end();
1347 --I;
1348 MCSectionSubPair OldSec = I->first;
1349 --I;
1350 MCSectionSubPair NewSec = I->first;
1351
1352 if (NewSec.first && OldSec != NewSec)
1353 changeSection(Section: NewSec.first, NewSec.second);
1354 SectionStack.pop_back();
1355 return true;
1356}
1357
1358void MCStreamer::switchSection(MCSection *Section, uint32_t Subsection) {
1359 assert(Section && "Cannot switch to a null section!");
1360 MCSectionSubPair curSection = SectionStack.back().first;
1361 SectionStack.back().second = curSection;
1362 if (MCSectionSubPair(Section, Subsection) != curSection) {
1363 changeSection(Section, Subsection);
1364 SectionStack.back().first = MCSectionSubPair(Section, Subsection);
1365 assert(!Section->hasEnded() && "Section already ended");
1366 MCSymbol *Sym = Section->getBeginSymbol();
1367 if (Sym && !Sym->isInSection())
1368 emitLabel(Symbol: Sym);
1369 }
1370}
1371
1372bool MCStreamer::switchSection(MCSection *Section, const MCExpr *SubsecExpr) {
1373 int64_t Subsec = 0;
1374 if (SubsecExpr) {
1375 if (!SubsecExpr->evaluateAsAbsolute(Res&: Subsec, Asm: getAssemblerPtr())) {
1376 getContext().reportError(L: SubsecExpr->getLoc(),
1377 Msg: "cannot evaluate subsection number");
1378 return true;
1379 }
1380 if (!isUInt<31>(x: Subsec)) {
1381 getContext().reportError(L: SubsecExpr->getLoc(),
1382 Msg: "subsection number " + Twine(Subsec) +
1383 " is not within [0,2147483647]");
1384 return true;
1385 }
1386 }
1387 switchSection(Section, Subsection: Subsec);
1388 return false;
1389}
1390
1391void MCStreamer::switchSectionNoPrint(MCSection *Section) {
1392 SectionStack.back().second = SectionStack.back().first;
1393 SectionStack.back().first = MCSectionSubPair(Section, 0);
1394 changeSection(Section, 0);
1395 MCSymbol *Sym = Section->getBeginSymbol();
1396 if (Sym && !Sym->isInSection())
1397 emitLabel(Symbol: Sym);
1398}
1399
1400MCSymbol *MCStreamer::endSection(MCSection *Section) {
1401 // TODO: keep track of the last subsection so that this symbol appears in the
1402 // correct place.
1403 MCSymbol *Sym = Section->getEndSymbol(Ctx&: Context);
1404 if (Sym->isInSection())
1405 return Sym;
1406
1407 switchSection(Section);
1408 emitLabel(Symbol: Sym);
1409 return Sym;
1410}
1411
1412static VersionTuple
1413targetVersionOrMinimumSupportedOSVersion(const Triple &Target,
1414 VersionTuple TargetVersion) {
1415 VersionTuple Min = Target.getMinimumSupportedOSVersion();
1416 return !Min.empty() && Min > TargetVersion ? Min : TargetVersion;
1417}
1418
1419static MCVersionMinType
1420getMachoVersionMinLoadCommandType(const Triple &Target) {
1421 assert(Target.isOSDarwin() && "expected a darwin OS");
1422 switch (Target.getOS()) {
1423 case Triple::MacOSX:
1424 case Triple::Darwin:
1425 return MCVM_OSXVersionMin;
1426 case Triple::IOS:
1427 assert(!Target.isMacCatalystEnvironment() &&
1428 "mac Catalyst should use LC_BUILD_VERSION");
1429 return MCVM_IOSVersionMin;
1430 case Triple::TvOS:
1431 return MCVM_TvOSVersionMin;
1432 case Triple::WatchOS:
1433 return MCVM_WatchOSVersionMin;
1434 default:
1435 break;
1436 }
1437 llvm_unreachable("unexpected OS type");
1438}
1439
1440static VersionTuple getMachoBuildVersionSupportedOS(const Triple &Target) {
1441 assert(Target.isOSDarwin() && "expected a darwin OS");
1442 switch (Target.getOS()) {
1443 case Triple::MacOSX:
1444 case Triple::Darwin:
1445 return VersionTuple(10, 14);
1446 case Triple::IOS:
1447 // Mac Catalyst always uses the build version load command.
1448 if (Target.isMacCatalystEnvironment())
1449 return VersionTuple();
1450 [[fallthrough]];
1451 case Triple::TvOS:
1452 return VersionTuple(12);
1453 case Triple::WatchOS:
1454 return VersionTuple(5);
1455 case Triple::DriverKit:
1456 case Triple::BridgeOS:
1457 case Triple::XROS:
1458 // DriverKit/BridgeOS/XROS always use the build version load command.
1459 return VersionTuple();
1460 default:
1461 break;
1462 }
1463 llvm_unreachable("unexpected OS type");
1464}
1465
1466static MachO::PlatformType
1467getMachoBuildVersionPlatformType(const Triple &Target) {
1468 assert(Target.isOSDarwin() && "expected a darwin OS");
1469 switch (Target.getOS()) {
1470 case Triple::MacOSX:
1471 case Triple::Darwin:
1472 return MachO::PLATFORM_MACOS;
1473 case Triple::IOS:
1474 if (Target.isMacCatalystEnvironment())
1475 return MachO::PLATFORM_MACCATALYST;
1476 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
1477 : MachO::PLATFORM_IOS;
1478 case Triple::TvOS:
1479 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
1480 : MachO::PLATFORM_TVOS;
1481 case Triple::WatchOS:
1482 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
1483 : MachO::PLATFORM_WATCHOS;
1484 case Triple::DriverKit:
1485 return MachO::PLATFORM_DRIVERKIT;
1486 case Triple::XROS:
1487 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR
1488 : MachO::PLATFORM_XROS;
1489 case Triple::BridgeOS:
1490 return MachO::PLATFORM_BRIDGEOS;
1491 default:
1492 break;
1493 }
1494 llvm_unreachable("unexpected OS type");
1495}
1496
1497void MCStreamer::emitVersionForTarget(
1498 const Triple &Target, const VersionTuple &SDKVersion,
1499 const Triple *DarwinTargetVariantTriple,
1500 const VersionTuple &DarwinTargetVariantSDKVersion) {
1501 if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
1502 return;
1503 // Do we even know the version?
1504 if (Target.getOSMajorVersion() == 0)
1505 return;
1506
1507 VersionTuple Version;
1508 switch (Target.getOS()) {
1509 case Triple::MacOSX:
1510 case Triple::Darwin:
1511 Target.getMacOSXVersion(Version);
1512 break;
1513 case Triple::IOS:
1514 case Triple::TvOS:
1515 Version = Target.getiOSVersion();
1516 break;
1517 case Triple::WatchOS:
1518 Version = Target.getWatchOSVersion();
1519 break;
1520 case Triple::DriverKit:
1521 Version = Target.getDriverKitVersion();
1522 break;
1523 case Triple::XROS:
1524 case Triple::BridgeOS:
1525 Version = Target.getOSVersion();
1526 break;
1527 default:
1528 llvm_unreachable("unexpected OS type");
1529 }
1530 assert(Version.getMajor() != 0 && "A non-zero major version is expected");
1531 auto LinkedTargetVersion =
1532 targetVersionOrMinimumSupportedOSVersion(Target, TargetVersion: Version);
1533 auto BuildVersionOSVersion = getMachoBuildVersionSupportedOS(Target);
1534 bool ShouldEmitBuildVersion = false;
1535 if (BuildVersionOSVersion.empty() ||
1536 LinkedTargetVersion >= BuildVersionOSVersion) {
1537 if (Target.isMacCatalystEnvironment() && DarwinTargetVariantTriple &&
1538 DarwinTargetVariantTriple->isMacOSX()) {
1539 emitVersionForTarget(Target: *DarwinTargetVariantTriple,
1540 SDKVersion: DarwinTargetVariantSDKVersion,
1541 /*DarwinTargetVariantTriple=*/nullptr,
1542 /*DarwinTargetVariantSDKVersion=*/VersionTuple());
1543 emitDarwinTargetVariantBuildVersion(
1544 Platform: getMachoBuildVersionPlatformType(Target),
1545 Major: LinkedTargetVersion.getMajor(),
1546 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1547 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1548 return;
1549 }
1550 emitBuildVersion(Platform: getMachoBuildVersionPlatformType(Target),
1551 Major: LinkedTargetVersion.getMajor(),
1552 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1553 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1554 ShouldEmitBuildVersion = true;
1555 }
1556
1557 if (const Triple *TVT = DarwinTargetVariantTriple) {
1558 if (Target.isMacOSX() && TVT->isMacCatalystEnvironment()) {
1559 auto TVLinkedTargetVersion =
1560 targetVersionOrMinimumSupportedOSVersion(Target: *TVT, TargetVersion: TVT->getiOSVersion());
1561 emitDarwinTargetVariantBuildVersion(
1562 Platform: getMachoBuildVersionPlatformType(Target: *TVT),
1563 Major: TVLinkedTargetVersion.getMajor(),
1564 Minor: TVLinkedTargetVersion.getMinor().value_or(u: 0),
1565 Update: TVLinkedTargetVersion.getSubminor().value_or(u: 0),
1566 SDKVersion: DarwinTargetVariantSDKVersion);
1567 }
1568 }
1569
1570 if (ShouldEmitBuildVersion)
1571 return;
1572
1573 emitVersionMin(Type: getMachoVersionMinLoadCommandType(Target),
1574 Major: LinkedTargetVersion.getMajor(),
1575 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1576 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1577}
1578