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