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