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