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