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, Out&: *this);
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::emitCFILLVMSetRAState(unsigned State, MCSymbol *PACSym,
752 SMLoc Loc) {
753 MCSymbol *Label = emitCFILabel();
754 MCCFIInstruction Instruction =
755 MCCFIInstruction::createSetRAState(L: Label, State, PACSym, Loc);
756 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
757 if (!CurFrame)
758 return;
759 CurFrame->Instructions.push_back(x: std::move(Instruction));
760}
761
762void MCStreamer::emitCFILLVMSetRAState(unsigned State, int64_t Offset,
763 SMLoc Loc) {
764 MCSymbol *Label = emitCFILabel();
765 MCCFIInstruction Instruction =
766 MCCFIInstruction::createSetRAState(L: Label, State, Offset, Loc);
767 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
768 if (!CurFrame)
769 return;
770 CurFrame->Instructions.push_back(x: std::move(Instruction));
771}
772
773void MCStreamer::emitCFIReturnColumn(int64_t Register) {
774 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
775 if (!CurFrame)
776 return;
777 CurFrame->RAReg = Register;
778}
779
780void MCStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
781 MCSymbol *Label = emitCFILabel();
782 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
783 if (MCDwarfFrameInfo *F = getCurrentDwarfFrameInfo())
784 F->Instructions.push_back(x: MCCFIInstruction::createLabel(L: Label, CfiLabel: Sym, Loc));
785}
786
787void MCStreamer::emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
788 MCSymbol *Label = emitCFILabel();
789 MCCFIInstruction Instruction =
790 MCCFIInstruction::createValOffset(L: Label, Register, Offset, Loc);
791 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
792 if (!CurFrame)
793 return;
794 CurFrame->Instructions.push_back(x: std::move(Instruction));
795}
796
797WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
798 const MCAsmInfo &MAI = Context.getAsmInfo();
799 if (!MAI.usesWindowsCFI()) {
800 getContext().reportError(
801 L: Loc, Msg: ".seh_* directives are not supported on this target");
802 return nullptr;
803 }
804 if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
805 getContext().reportError(
806 L: Loc, Msg: ".seh_ directive must appear within an active frame");
807 return nullptr;
808 }
809 return CurrentWinFrameInfo;
810}
811
812void MCStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
813 const MCAsmInfo &MAI = Context.getAsmInfo();
814 if (!MAI.usesWindowsCFI())
815 return getContext().reportError(
816 L: Loc, Msg: ".seh_* directives are not supported on this target");
817 if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
818 getContext().reportError(
819 L: Loc, Msg: "Starting a function before ending the previous one!");
820
821 MCSymbol *StartProc = emitCFILabel();
822
823 CurrentProcWinFrameInfoStartIndex = WinFrameInfos.size();
824 WinFrameInfos.emplace_back(
825 args: std::make_unique<WinEH::FrameInfo>(args&: Symbol, args&: StartProc));
826 CurrentWinFrameInfo = WinFrameInfos.back().get();
827 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
828 CurrentWinFrameInfo->FunctionLoc = Loc;
829 // Inherit the module-wide default unwind version.
830 CurrentWinFrameInfo->Version = DefaultWinCFIUnwindVersion;
831}
832
833void MCStreamer::emitWinCFIEndProc(SMLoc Loc) {
834 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
835 if (!CurFrame)
836 return;
837 CurrentWinFrameInfo = nullptr;
838
839 MCSymbol *Label = emitCFILabel();
840 CurFrame->End = Label;
841 const MCSymbol **FuncletOrFuncEndPtr =
842 CurFrame->ChainedParent ? &CurFrame->ChainedParent->FuncletOrFuncEnd
843 : &CurFrame->FuncletOrFuncEnd;
844 if (!*FuncletOrFuncEndPtr)
845 *FuncletOrFuncEndPtr = CurFrame->End;
846
847 if (CurrentWinEpilog) {
848 // Set End to... something... to prevent crashes later.
849 CurrentWinEpilog->End = emitCFILabel();
850 CurrentWinEpilog = nullptr;
851 getContext().reportError(L: Loc, Msg: "Missing .seh_endepilogue in " +
852 CurFrame->Function->getName());
853 }
854
855 for (size_t I = CurrentProcWinFrameInfoStartIndex, E = WinFrameInfos.size();
856 I != E; ++I)
857 emitWindowsUnwindTables(Frame: WinFrameInfos[I].get());
858 switchSection(Section: CurFrame->TextSection);
859}
860
861void MCStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
862 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
863 if (!CurFrame)
864 return;
865
866 MCSymbol *Label = emitCFILabel();
867 const MCSymbol **FuncletOrFuncEndPtr =
868 CurFrame->ChainedParent ? &CurFrame->ChainedParent->FuncletOrFuncEnd
869 : &CurFrame->FuncletOrFuncEnd;
870 *FuncletOrFuncEndPtr = Label;
871}
872
873void MCStreamer::emitWinCFISplitChained(SMLoc Loc) {
874 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
875 if (!CurFrame)
876 return;
877
878 if (!CurFrame->PrologEnd)
879 return getContext().reportError(
880 L: Loc, Msg: "can't split into a new chained region (.seh_splitchained) in the "
881 "middle of a prolog in " +
882 CurFrame->Function->getName());
883
884 MCSymbol *Label = emitCFILabel();
885
886 // Complete the current frame before starting a new, chained one.
887 CurFrame->End = Label;
888
889 // All chained frames point to the same parent.
890 WinEH::FrameInfo *ChainedParent =
891 CurFrame->ChainedParent ? CurFrame->ChainedParent : CurFrame;
892
893 WinFrameInfos.emplace_back(args: std::make_unique<WinEH::FrameInfo>(
894 args&: CurFrame->Function, args&: Label, args&: ChainedParent));
895 CurrentWinFrameInfo = WinFrameInfos.back().get();
896 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
897}
898
899void MCStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
900 SMLoc Loc) {
901 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
902 if (!CurFrame)
903 return;
904
905 // Handlers are always associated with the parent frame.
906 CurFrame = CurFrame->ChainedParent ? CurFrame->ChainedParent : CurFrame;
907
908 CurFrame->ExceptionHandler = Sym;
909 if (!Except && !Unwind)
910 getContext().reportError(L: Loc, Msg: "Don't know what kind of handler this is!");
911 if (Unwind)
912 CurFrame->HandlesUnwind = true;
913 if (Except)
914 CurFrame->HandlesExceptions = true;
915}
916
917void MCStreamer::emitWinEHHandlerData(SMLoc Loc) {
918 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
919 if (!CurFrame)
920 return;
921}
922
923void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
924 const MCSymbolRefExpr *To, uint64_t Count) {
925}
926
927static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
928 MCSection *MainCFISec,
929 const MCSection *TextSec) {
930 // If this is the main .text section, use the main unwind info section.
931 if (TextSec == Context.getObjectFileInfo()->getTextSection())
932 return MainCFISec;
933
934 const auto *TextSecCOFF = static_cast<const MCSectionCOFF *>(TextSec);
935 auto *MainCFISecCOFF = static_cast<MCSectionCOFF *>(MainCFISec);
936 unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextID: NextWinCFIID);
937
938 // If this section is COMDAT, this unwind section should be COMDAT associative
939 // with its group.
940 const MCSymbol *KeySym = nullptr;
941 if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
942 KeySym = TextSecCOFF->getCOMDATSymbol();
943
944 // In a GNU environment, we can't use associative comdats. Instead, do what
945 // GCC does, which is to make plain comdat selectany section named like
946 // ".[px]data$_Z3foov".
947 if (!Context.getAsmInfo().hasCOFFAssociativeComdats()) {
948 std::string SectionName = (MainCFISecCOFF->getName() + "$" +
949 TextSecCOFF->getName().split(Separator: '$').second)
950 .str();
951 return Context.getCOFFSection(Section: SectionName,
952 Characteristics: MainCFISecCOFF->getCharacteristics() |
953 COFF::IMAGE_SCN_LNK_COMDAT,
954 COMDATSymName: "", Selection: COFF::IMAGE_COMDAT_SELECT_ANY);
955 }
956 }
957
958 return Context.getAssociativeCOFFSection(Sec: MainCFISecCOFF, KeySym, UniqueID);
959}
960
961MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
962 return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID,
963 MainCFISec: getContext().getObjectFileInfo()->getPDataSection(),
964 TextSec);
965}
966
967MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
968 return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID,
969 MainCFISec: getContext().getObjectFileInfo()->getXDataSection(),
970 TextSec);
971}
972
973void MCStreamer::emitSyntaxDirective(StringRef Syntax, StringRef Options) {}
974
975static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
976 return Ctx.getRegisterInfo()->getSEHRegNum(Reg);
977}
978
979// Unwind formats before v3 store the register operand of an unwind code in a
980// 4-bit field, so extended registers (r16-r31 / xmm16-xmm31, i.e. SEH register
981// numbers greater than 15) cannot be represented. Report an error rather than
982// silently truncating the register number to a different register. Returns true
983// if an error was reported.
984static bool checkUnwindV3ExtendedReg(MCContext &Ctx,
985 const WinEH::Instruction &Inst,
986 uint8_t Version, SMLoc Loc,
987 StringRef Directive) {
988 if (Version < 3 && Inst.Register > 15) {
989 Ctx.reportError(L: Loc, Msg: Directive +
990 " with an extended register requires unwind v3");
991 return true;
992 }
993 return false;
994}
995
996void MCStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
997 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
998 if (!CurFrame)
999 return;
1000
1001 MCSymbol *Label = emitCFILabel();
1002
1003 WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(
1004 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register));
1005 if (CurrentWinEpilog) {
1006 if (CurFrame->Version < 3)
1007 return getContext().reportError(
1008 L: Loc, Msg: ".seh_pushreg inside epilog requires unwind v3");
1009 CurrentWinEpilog->Instructions.push_back(x: Inst);
1010 } else {
1011 if (checkUnwindV3ExtendedReg(Ctx&: getContext(), Inst, Version: CurFrame->Version, Loc,
1012 Directive: ".seh_pushreg"))
1013 return;
1014 CurFrame->Instructions.push_back(x: Inst);
1015 }
1016}
1017
1018void MCStreamer::emitWinCFIPush2Regs(MCRegister Reg1, MCRegister Reg2,
1019 SMLoc Loc) {
1020 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1021 if (!CurFrame)
1022 return;
1023
1024 // UOP_Push2 is V3-only - reject for V1/V2.
1025 if (CurFrame->Version < 3)
1026 return getContext().reportError(
1027 L: Loc, Msg: ".seh_push2regs is only supported for unwind v3");
1028
1029 MCSymbol *Label = emitCFILabel();
1030
1031 WinEH::Instruction Inst = Win64EH::Instruction::Push2(
1032 L: Label, Reg1: encodeSEHRegNum(Ctx&: Context, Reg: Reg1), Reg2: encodeSEHRegNum(Ctx&: Context, Reg: Reg2));
1033 if (CurrentWinEpilog)
1034 CurrentWinEpilog->Instructions.push_back(x: Inst);
1035 else
1036 CurFrame->Instructions.push_back(x: Inst);
1037}
1038
1039void MCStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
1040 SMLoc Loc) {
1041 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1042 if (!CurFrame)
1043 return;
1044 if (!CurrentWinEpilog && CurFrame->LastFrameInst >= 0)
1045 return getContext().reportError(
1046 L: Loc, Msg: "frame register and offset can be set at most once");
1047 if (Offset & 0x0F)
1048 return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16");
1049 if (Offset > 240)
1050 return getContext().reportError(
1051 L: Loc, Msg: "frame offset must be less than or equal to 240");
1052
1053 MCSymbol *Label = emitCFILabel();
1054
1055 WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(
1056 L: Label, Reg: encodeSEHRegNum(Ctx&: getContext(), Reg: Register), Off: Offset);
1057 if (CurrentWinEpilog) {
1058 if (CurFrame->Version < 3)
1059 return getContext().reportError(
1060 L: Loc, Msg: ".seh_setframe inside epilog requires unwind v3");
1061 CurrentWinEpilog->Instructions.push_back(x: Inst);
1062 } else {
1063 if (checkUnwindV3ExtendedReg(Ctx&: getContext(), Inst, Version: CurFrame->Version, Loc,
1064 Directive: ".seh_setframe"))
1065 return;
1066 CurFrame->LastFrameInst = CurFrame->Instructions.size();
1067 CurFrame->Instructions.push_back(x: Inst);
1068 }
1069}
1070
1071void MCStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
1072 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1073 if (!CurFrame)
1074 return;
1075 if (Size == 0)
1076 return getContext().reportError(L: Loc,
1077 Msg: "stack allocation size must be non-zero");
1078 if (Size & 7)
1079 return getContext().reportError(
1080 L: Loc, Msg: "stack allocation size is not a multiple of 8");
1081
1082 MCSymbol *Label = emitCFILabel();
1083
1084 WinEH::Instruction Inst = Win64EH::Instruction::Alloc(L: Label, Size);
1085 if (CurrentWinEpilog) {
1086 if (CurFrame->Version < 3)
1087 return getContext().reportError(
1088 L: Loc, Msg: ".seh_stackalloc inside epilog requires unwind v3");
1089 CurrentWinEpilog->Instructions.push_back(x: Inst);
1090 } else {
1091 CurFrame->Instructions.push_back(x: Inst);
1092 }
1093}
1094
1095void MCStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
1096 SMLoc Loc) {
1097 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1098 if (!CurFrame)
1099 return;
1100
1101 if (Offset & 7)
1102 return getContext().reportError(
1103 L: Loc, Msg: "register save offset is not 8 byte aligned");
1104
1105 MCSymbol *Label = emitCFILabel();
1106
1107 WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(
1108 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset);
1109 if (CurrentWinEpilog) {
1110 if (CurFrame->Version < 3)
1111 return getContext().reportError(
1112 L: Loc, Msg: ".seh_savereg inside epilog requires unwind v3");
1113 CurrentWinEpilog->Instructions.push_back(x: Inst);
1114 } else {
1115 if (checkUnwindV3ExtendedReg(Ctx&: getContext(), Inst, Version: CurFrame->Version, Loc,
1116 Directive: ".seh_savereg"))
1117 return;
1118 CurFrame->Instructions.push_back(x: Inst);
1119 }
1120}
1121
1122void MCStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
1123 SMLoc Loc) {
1124 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1125 if (!CurFrame)
1126 return;
1127 if (Offset & 0x0F)
1128 return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16");
1129
1130 MCSymbol *Label = emitCFILabel();
1131
1132 WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(
1133 L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset);
1134 if (CurrentWinEpilog) {
1135 if (CurFrame->Version < 3)
1136 return getContext().reportError(
1137 L: Loc, Msg: ".seh_savexmm inside epilog requires unwind v3");
1138 CurrentWinEpilog->Instructions.push_back(x: Inst);
1139 } else {
1140 if (checkUnwindV3ExtendedReg(Ctx&: getContext(), Inst, Version: CurFrame->Version, Loc,
1141 Directive: ".seh_savexmm"))
1142 return;
1143 CurFrame->Instructions.push_back(x: Inst);
1144 }
1145}
1146
1147void MCStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
1148 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1149 if (!CurFrame)
1150 return;
1151 if (CurrentWinEpilog) {
1152 if (CurFrame->Version < 3)
1153 return getContext().reportError(
1154 L: Loc, Msg: ".seh_pushframe inside epilog requires unwind v3");
1155 MCSymbol *Label = emitCFILabel();
1156 WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(L: Label, Code);
1157 CurrentWinEpilog->Instructions.push_back(x: Inst);
1158 return;
1159 }
1160 if (!CurFrame->Instructions.empty())
1161 return getContext().reportError(
1162 L: Loc, Msg: "If present, PushMachFrame must be the first UOP");
1163
1164 MCSymbol *Label = emitCFILabel();
1165
1166 WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(L: Label, Code);
1167 CurFrame->Instructions.push_back(x: Inst);
1168}
1169
1170void MCStreamer::emitWinCFIEndProlog(SMLoc Loc) {
1171 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1172 if (!CurFrame)
1173 return;
1174
1175 MCSymbol *Label = emitCFILabel();
1176
1177 CurFrame->PrologEnd = Label;
1178}
1179
1180void MCStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) {
1181 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1182 if (!CurFrame)
1183 return;
1184
1185 MCSymbol *Label = emitCFILabel();
1186
1187 if (!CurFrame->PrologEnd) {
1188 CurFrame->PrologEnd = Label;
1189 getContext().reportError(
1190 L: Loc, Msg: "starting epilogue (.seh_startepilogue) before prologue has ended "
1191 "(.seh_endprologue) in " +
1192 CurFrame->Function->getName());
1193 }
1194 CurrentWinEpilog =
1195 &CurFrame->EpilogMap.insert_or_assign(Key: Label, Val: WinEH::FrameInfo::Epilog())
1196 .first->second;
1197 CurrentWinEpilog->Start = Label;
1198 CurrentWinEpilog->Loc = Loc;
1199}
1200
1201void MCStreamer::emitWinCFIEndEpilogue(SMLoc Loc) {
1202 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1203 if (!CurFrame)
1204 return;
1205
1206 if (!CurrentWinEpilog)
1207 return getContext().reportError(L: Loc, Msg: "Stray .seh_endepilogue in " +
1208 CurFrame->Function->getName());
1209
1210 if ((CurFrame->Version == 2) && !CurrentWinEpilog->UnwindV2Start) {
1211 // Set UnwindV2Start to... something... to prevent crashes later.
1212 CurrentWinEpilog->UnwindV2Start = CurrentWinEpilog->Start;
1213 getContext().reportError(L: Loc, Msg: "Missing .seh_unwindv2start in " +
1214 CurFrame->Function->getName());
1215 }
1216
1217 CurrentWinEpilog->End = emitCFILabel();
1218 CurrentWinEpilog = nullptr;
1219}
1220
1221void MCStreamer::emitWinCFIUnwindV2Start(SMLoc Loc) {
1222 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
1223 if (!CurFrame)
1224 return;
1225
1226 if (!CurrentWinEpilog)
1227 return getContext().reportError(L: Loc, Msg: "Stray .seh_unwindv2start in " +
1228 CurFrame->Function->getName());
1229
1230 if (CurrentWinEpilog->UnwindV2Start)
1231 return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindv2start in " +
1232 CurFrame->Function->getName());
1233
1234 MCSymbol *Label = emitCFILabel();
1235 CurrentWinEpilog->UnwindV2Start = Label;
1236}
1237
1238void MCStreamer::emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc) {
1239 bool SupportedVersion = (Version >= 1 && Version <= 3);
1240
1241 // If called outside a proc, set the module-level default.
1242 if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
1243 if (!SupportedVersion)
1244 return getContext().reportError(
1245 L: Loc, Msg: "Unsupported version for .seh_unwindversion");
1246 setDefaultWinCFIUnwindVersion(Version);
1247 return;
1248 }
1249
1250 // Per-function override (existing behaviour).
1251 WinEH::FrameInfo *CurFrame = CurrentWinFrameInfo;
1252
1253 if (CurFrame->Version != DefaultWinCFIUnwindVersion &&
1254 CurFrame->Version != WinEH::FrameInfo::DefaultVersion)
1255 return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindversion in " +
1256 CurFrame->Function->getName());
1257
1258 if (!SupportedVersion)
1259 return getContext().reportError(
1260 L: Loc, Msg: "Unsupported version specified in .seh_unwindversion in " +
1261 CurFrame->Function->getName());
1262
1263 CurFrame->Version = Version;
1264}
1265
1266void MCStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {}
1267
1268void MCStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {}
1269
1270void MCStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {}
1271
1272void MCStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
1273
1274void MCStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
1275
1276void MCStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {}
1277
1278void MCStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {}
1279
1280/// EmitRawText - If this file is backed by an assembly streamer, this dumps
1281/// the specified string in the output .s file. This capability is
1282/// indicated by the hasRawTextSupport() predicate.
1283void MCStreamer::emitRawTextImpl(StringRef String) {
1284 // This is not llvm_unreachable for the sake of out of tree backend
1285 // developers who may not have assembly streamers and should serve as a
1286 // reminder to not accidentally call EmitRawText in the absence of such.
1287 report_fatal_error(reason: "EmitRawText called on an MCStreamer that doesn't support "
1288 "it (target backend is likely missing an AsmStreamer "
1289 "implementation)");
1290}
1291
1292void MCStreamer::emitRawText(const Twine &T) {
1293 SmallString<128> Str;
1294 emitRawTextImpl(String: T.toStringRef(Out&: Str));
1295}
1296
1297void MCStreamer::emitWindowsUnwindTables() {}
1298
1299void MCStreamer::emitWindowsUnwindTables(WinEH::FrameInfo *Frame) {}
1300
1301void MCStreamer::finish(SMLoc EndLoc) {
1302 if (hasUnfinishedDwarfFrameInfo() ||
1303 (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
1304 getContext().reportError(L: EndLoc, Msg: "Unfinished frame!");
1305 return;
1306 }
1307
1308 if (LFIRewriter)
1309 LFIRewriter->finish(Out&: *this);
1310
1311 MCTargetStreamer *TS = getTargetStreamer();
1312 if (TS)
1313 TS->finish();
1314
1315 finishImpl();
1316}
1317
1318void MCStreamer::maybeEmitDwarf64Mark() {
1319 if (Context.getDwarfFormat() != dwarf::DWARF64)
1320 return;
1321 AddComment(T: "DWARF64 Mark");
1322 emitInt32(Value: dwarf::DW_LENGTH_DWARF64);
1323}
1324
1325void MCStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
1326 assert(Context.getDwarfFormat() == dwarf::DWARF64 ||
1327 Length <= dwarf::DW_LENGTH_lo_reserved);
1328 maybeEmitDwarf64Mark();
1329 AddComment(T: Comment);
1330 emitIntValue(Value: Length, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat()));
1331}
1332
1333MCSymbol *MCStreamer::emitDwarfUnitLength(const Twine &Prefix,
1334 const Twine &Comment) {
1335 maybeEmitDwarf64Mark();
1336 AddComment(T: Comment);
1337 MCSymbol *Lo = Context.createTempSymbol(Name: Prefix + "_start");
1338 MCSymbol *Hi = Context.createTempSymbol(Name: Prefix + "_end");
1339
1340 emitAbsoluteSymbolDiff(
1341 Hi, Lo, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat()));
1342 // emit the begin symbol after we generate the length field.
1343 emitLabel(Symbol: Lo);
1344 // Return the Hi symbol to the caller.
1345 return Hi;
1346}
1347
1348void MCStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
1349 // Set the value of the symbol, as we are at the start of the line table.
1350 emitLabel(Symbol: StartSym);
1351}
1352
1353void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
1354 visitUsedExpr(Expr: *Value);
1355 Symbol->setVariableValue(Value);
1356
1357 MCTargetStreamer *TS = getTargetStreamer();
1358 if (TS)
1359 TS->emitAssignment(Symbol, Value);
1360}
1361
1362void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
1363 uint64_t Address, const MCInst &Inst,
1364 const MCSubtargetInfo &STI,
1365 raw_ostream &OS) {
1366 InstPrinter.printInst(MI: &Inst, Address, Annot: "", STI, OS);
1367}
1368
1369void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
1370}
1371
1372void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
1373 switch (Expr.getKind()) {
1374 case MCExpr::Target:
1375 cast<MCTargetExpr>(Val: Expr).visitUsedExpr(Streamer&: *this);
1376 break;
1377
1378 case MCExpr::Constant:
1379 break;
1380
1381 case MCExpr::Binary: {
1382 const MCBinaryExpr &BE = cast<MCBinaryExpr>(Val: Expr);
1383 visitUsedExpr(Expr: *BE.getLHS());
1384 visitUsedExpr(Expr: *BE.getRHS());
1385 break;
1386 }
1387
1388 case MCExpr::SymbolRef:
1389 visitUsedSymbol(Sym: cast<MCSymbolRefExpr>(Val: Expr).getSymbol());
1390 break;
1391
1392 case MCExpr::Unary:
1393 visitUsedExpr(Expr: *cast<MCUnaryExpr>(Val: Expr).getSubExpr());
1394 break;
1395
1396 case MCExpr::Specifier:
1397 visitUsedExpr(Expr: *cast<MCSpecifierExpr>(Val: Expr).getSubExpr());
1398 break;
1399 }
1400}
1401
1402void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
1403 // Scan for values.
1404 for (unsigned i = Inst.getNumOperands(); i--;)
1405 if (Inst.getOperand(i).isExpr())
1406 visitUsedExpr(Expr: *Inst.getOperand(i).getExpr());
1407}
1408
1409void MCStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
1410 uint64_t Attr, uint64_t Discriminator,
1411 const MCPseudoProbeInlineStack &InlineStack,
1412 MCSymbol *FnSym) {
1413 auto &Context = getContext();
1414
1415 // Create a symbol at in the current section for use in the probe.
1416 MCSymbol *ProbeSym = Context.createTempSymbol();
1417
1418 // Set the value of the symbol to use for the MCPseudoProbe.
1419 emitLabel(Symbol: ProbeSym);
1420
1421 // Create a (local) probe entry with the symbol.
1422 MCPseudoProbe Probe(ProbeSym, Guid, Index, Type, Attr, Discriminator);
1423
1424 // Add the probe entry to this section's entries.
1425 Context.getMCPseudoProbeTable().getProbeSections().addPseudoProbe(
1426 FuncSym: FnSym, Probe, InlineStack);
1427}
1428
1429void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
1430 unsigned Size) {
1431 // Get the Hi-Lo expression.
1432 const MCExpr *Diff =
1433 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context),
1434 RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context);
1435
1436 const MCAsmInfo &MAI = Context.getAsmInfo();
1437 if (!MAI.doesSetDirectiveSuppressReloc()) {
1438 emitValue(Value: Diff, Size);
1439 return;
1440 }
1441
1442 // Otherwise, emit with .set (aka assignment).
1443 MCSymbol *SetLabel = Context.createTempSymbol(Name: "set");
1444 emitAssignment(Symbol: SetLabel, Value: Diff);
1445 emitSymbolValue(Sym: SetLabel, Size);
1446}
1447
1448void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
1449 const MCSymbol *Lo) {
1450 // Get the Hi-Lo expression.
1451 const MCExpr *Diff =
1452 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context),
1453 RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context);
1454
1455 emitULEB128Value(Value: Diff);
1456}
1457
1458void MCStreamer::emitSubsectionsViaSymbols() {
1459 llvm_unreachable(
1460 "emitSubsectionsViaSymbols only supported on Mach-O targets");
1461}
1462void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
1463void MCStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
1464 llvm_unreachable("this directive only supported on COFF targets");
1465}
1466void MCStreamer::endCOFFSymbolDef() {
1467 llvm_unreachable("this directive only supported on COFF targets");
1468}
1469void MCStreamer::emitFileDirective(StringRef Filename) {}
1470void MCStreamer::emitFileDirective(StringRef Filename,
1471 StringRef CompilerVersion,
1472 StringRef TimeStamp, StringRef Description) {
1473}
1474void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
1475 llvm_unreachable("this directive only supported on COFF targets");
1476}
1477void MCStreamer::emitCOFFSymbolType(int Type) {
1478 llvm_unreachable("this directive only supported on COFF targets");
1479}
1480void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
1481 MCSymbol *CsectSym,
1482 Align Alignment) {
1483 llvm_unreachable("this directive only supported on XCOFF targets");
1484}
1485
1486void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
1487 MCSymbolAttr Linkage,
1488 MCSymbolAttr Visibility) {
1489 llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on "
1490 "XCOFF targets");
1491}
1492
1493void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
1494 StringRef Rename) {}
1495
1496void MCStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
1497 llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
1498}
1499
1500void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
1501 const MCSymbol *Trap,
1502 unsigned Lang, unsigned Reason,
1503 unsigned FunctionSize,
1504 bool hasDebug) {
1505 report_fatal_error(reason: "emitXCOFFExceptDirective is only supported on "
1506 "XCOFF targets");
1507}
1508
1509void MCStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
1510 llvm_unreachable("emitXCOFFCInfoSym is only supported on"
1511 "XCOFF targets");
1512}
1513
1514void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
1515void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
1516 StringRef Name, bool KeepOriginalSym) {}
1517void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1518 Align ByteAlignment) {}
1519void MCStreamer::emitZerofill(MCSection *, MCSymbol *, uint64_t, Align, SMLoc) {
1520}
1521void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1522 uint64_t Size, Align ByteAlignment) {}
1523
1524void MCStreamer::changeSection(MCSection *Sec, uint32_t) {
1525 CurFrag = &Sec->getDummyFragment();
1526 auto *Sym = Sec->getBeginSymbol();
1527 if (!Sym || !Sym->isUndefined())
1528 return;
1529 // In Mach-O, DWARF sections use Begin as a temporary label, requiring a label
1530 // definition, unlike section symbols in other file formats.
1531 if (getContext().getObjectFileType() == MCContext::IsMachO)
1532 emitLabel(Symbol: Sym);
1533 else
1534 Sym->setFragment(CurFrag);
1535}
1536
1537void MCStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
1538void MCStreamer::emitBytes(StringRef Data) {}
1539void MCStreamer::emitBinaryData(StringRef Data) { emitBytes(Data); }
1540void MCStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
1541 visitUsedExpr(Expr: *Value);
1542}
1543void MCStreamer::emitULEB128Value(const MCExpr *Value) {}
1544void MCStreamer::emitSLEB128Value(const MCExpr *Value) {}
1545void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
1546void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
1547 SMLoc Loc) {}
1548void MCStreamer::emitValueToAlignment(Align, int64_t, uint8_t, unsigned) {}
1549void MCStreamer::emitPrefAlign(Align A, const MCSymbol &End, bool EmitNops,
1550 uint8_t Fill, const MCSubtargetInfo &STI) {}
1551void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo &STI,
1552 unsigned MaxBytesToEmit) {}
1553void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
1554 SMLoc Loc) {}
1555static void reportBundlingUnsupported(MCStreamer &S) {
1556 S.getContext().reportError(
1557 L: S.getStartTokLoc(),
1558 Msg: "aligned bundling is not supported by this object file format");
1559}
1560void MCStreamer::emitBundleAlignMode(Align) {
1561 reportBundlingUnsupported(S&: *this);
1562}
1563void MCStreamer::emitBundleLock(bool, const MCSubtargetInfo &) {
1564 reportBundlingUnsupported(S&: *this);
1565}
1566void MCStreamer::emitBundleUnlock(const MCSubtargetInfo &) {
1567 reportBundlingUnsupported(S&: *this);
1568}
1569void MCStreamer::finishImpl() {}
1570
1571bool MCStreamer::popSection() {
1572 if (SectionStack.size() <= 1)
1573 return false;
1574 auto I = SectionStack.end();
1575 --I;
1576 MCSectionSubPair OldSec = I->first;
1577 --I;
1578 MCSectionSubPair NewSec = I->first;
1579
1580 if (NewSec.first && OldSec != NewSec)
1581 changeSection(Sec: NewSec.first, NewSec.second);
1582 SectionStack.pop_back();
1583 return true;
1584}
1585
1586void MCStreamer::switchSection(MCSection *Section, uint32_t Subsection) {
1587 assert(Section && "Cannot switch to a null section!");
1588 MCSectionSubPair curSection = SectionStack.back().first;
1589 SectionStack.back().second = curSection;
1590 if (MCSectionSubPair(Section, Subsection) != curSection) {
1591 changeSection(Sec: Section, Subsection);
1592 SectionStack.back().first = MCSectionSubPair(Section, Subsection);
1593 assert(!Section->hasEnded() && "Section already ended");
1594 }
1595}
1596
1597bool MCStreamer::switchSection(MCSection *Section, const MCExpr *SubsecExpr) {
1598 int64_t Subsec = 0;
1599 if (SubsecExpr) {
1600 if (!SubsecExpr->evaluateAsAbsolute(Res&: Subsec, Asm: getAssemblerPtr())) {
1601 getContext().reportError(L: SubsecExpr->getLoc(),
1602 Msg: "cannot evaluate subsection number");
1603 return true;
1604 }
1605 if (!isUInt<31>(x: Subsec)) {
1606 getContext().reportError(L: SubsecExpr->getLoc(),
1607 Msg: "subsection number " + Twine(Subsec) +
1608 " is not within [0,2147483647]");
1609 return true;
1610 }
1611 }
1612 switchSection(Section, Subsection: Subsec);
1613 return false;
1614}
1615
1616void MCStreamer::switchSectionNoPrint(MCSection *Section) {
1617 SectionStack.back().second = SectionStack.back().first;
1618 SectionStack.back().first = MCSectionSubPair(Section, 0);
1619 changeSection(Sec: Section, 0);
1620}
1621
1622MCSymbol *MCStreamer::endSection(MCSection *Section) {
1623 // TODO: keep track of the last subsection so that this symbol appears in the
1624 // correct place.
1625 MCSymbol *Sym = Section->getEndSymbol(Ctx&: Context);
1626 if (Sym->isInSection())
1627 return Sym;
1628
1629 switchSection(Section);
1630 emitLabel(Symbol: Sym);
1631 return Sym;
1632}
1633
1634void MCStreamer::addFragment(MCFragment *F) {
1635 auto *Sec = CurFrag->getParent();
1636 F->setParent(Sec);
1637 F->setLayoutOrder(CurFrag->getLayoutOrder() + 1);
1638 CurFrag->Next = F;
1639 CurFrag = F;
1640 Sec->curFragList()->Tail = F;
1641}
1642
1643static VersionTuple
1644targetVersionOrMinimumSupportedOSVersion(const Triple &Target,
1645 VersionTuple TargetVersion) {
1646 VersionTuple Min = Target.getMinimumSupportedOSVersion();
1647 return !Min.empty() && Min > TargetVersion ? Min : TargetVersion;
1648}
1649
1650static MCVersionMinType
1651getMachoVersionMinLoadCommandType(const Triple &Target) {
1652 assert(Target.isOSDarwin() && "expected a darwin OS");
1653 switch (Target.getOS()) {
1654 case Triple::MacOSX:
1655 case Triple::Darwin:
1656 return MCVM_OSXVersionMin;
1657 case Triple::IOS:
1658 assert(!Target.isMacCatalystEnvironment() &&
1659 "mac Catalyst should use LC_BUILD_VERSION");
1660 return MCVM_IOSVersionMin;
1661 case Triple::TvOS:
1662 return MCVM_TvOSVersionMin;
1663 case Triple::WatchOS:
1664 return MCVM_WatchOSVersionMin;
1665 default:
1666 break;
1667 }
1668 llvm_unreachable("unexpected OS type");
1669}
1670
1671static VersionTuple getMachoBuildVersionSupportedOS(const Triple &Target) {
1672 assert(Target.isOSDarwin() && "expected a darwin OS");
1673 switch (Target.getOS()) {
1674 case Triple::MacOSX:
1675 case Triple::Darwin:
1676 return VersionTuple(10, 14);
1677 case Triple::IOS:
1678 // Mac Catalyst always uses the build version load command.
1679 if (Target.isMacCatalystEnvironment())
1680 return VersionTuple();
1681 [[fallthrough]];
1682 case Triple::TvOS:
1683 return VersionTuple(12);
1684 case Triple::WatchOS:
1685 return VersionTuple(5);
1686 case Triple::DriverKit:
1687 case Triple::BridgeOS:
1688 case Triple::XROS:
1689 // DriverKit/BridgeOS/XROS always use the build version load command.
1690 return VersionTuple();
1691 default:
1692 break;
1693 }
1694 llvm_unreachable("unexpected OS type");
1695}
1696
1697static MachO::PlatformType
1698getMachoBuildVersionPlatformType(const Triple &Target) {
1699 assert(Target.isOSDarwin() && "expected a darwin OS");
1700 switch (Target.getOS()) {
1701 case Triple::MacOSX:
1702 case Triple::Darwin:
1703 return MachO::PLATFORM_MACOS;
1704 case Triple::IOS:
1705 if (Target.isMacCatalystEnvironment())
1706 return MachO::PLATFORM_MACCATALYST;
1707 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
1708 : MachO::PLATFORM_IOS;
1709 case Triple::TvOS:
1710 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
1711 : MachO::PLATFORM_TVOS;
1712 case Triple::WatchOS:
1713 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
1714 : MachO::PLATFORM_WATCHOS;
1715 case Triple::DriverKit:
1716 return MachO::PLATFORM_DRIVERKIT;
1717 case Triple::XROS:
1718 return Target.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR
1719 : MachO::PLATFORM_XROS;
1720 case Triple::BridgeOS:
1721 return MachO::PLATFORM_BRIDGEOS;
1722 default:
1723 break;
1724 }
1725 llvm_unreachable("unexpected OS type");
1726}
1727
1728void MCStreamer::emitVersionForTarget(
1729 const Triple &Target, const VersionTuple &SDKVersion,
1730 const Triple *DarwinTargetVariantTriple,
1731 const VersionTuple &DarwinTargetVariantSDKVersion) {
1732 if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
1733 return;
1734 // Do we even know the version?
1735 if (Target.getOSMajorVersion() == 0)
1736 return;
1737
1738 VersionTuple Version;
1739 switch (Target.getOS()) {
1740 case Triple::MacOSX:
1741 case Triple::Darwin:
1742 Target.getMacOSXVersion(Version);
1743 break;
1744 case Triple::IOS:
1745 case Triple::TvOS:
1746 Version = Target.getiOSVersion();
1747 break;
1748 case Triple::WatchOS:
1749 Version = Target.getWatchOSVersion();
1750 break;
1751 case Triple::DriverKit:
1752 Version = Target.getDriverKitVersion();
1753 break;
1754 case Triple::XROS:
1755 case Triple::BridgeOS:
1756 Version = Target.getOSVersion();
1757 break;
1758 default:
1759 llvm_unreachable("unexpected OS type");
1760 }
1761 assert(Version.getMajor() != 0 && "A non-zero major version is expected");
1762 auto LinkedTargetVersion =
1763 targetVersionOrMinimumSupportedOSVersion(Target, TargetVersion: Version);
1764 auto BuildVersionOSVersion = getMachoBuildVersionSupportedOS(Target);
1765 bool ShouldEmitBuildVersion = false;
1766 if (BuildVersionOSVersion.empty() ||
1767 LinkedTargetVersion >= BuildVersionOSVersion) {
1768 if (Target.isMacCatalystEnvironment() && DarwinTargetVariantTriple &&
1769 DarwinTargetVariantTriple->isMacOSX()) {
1770 emitVersionForTarget(Target: *DarwinTargetVariantTriple,
1771 SDKVersion: DarwinTargetVariantSDKVersion,
1772 /*DarwinTargetVariantTriple=*/nullptr,
1773 /*DarwinTargetVariantSDKVersion=*/VersionTuple());
1774 emitDarwinTargetVariantBuildVersion(
1775 Platform: getMachoBuildVersionPlatformType(Target),
1776 Major: LinkedTargetVersion.getMajor(),
1777 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1778 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1779 return;
1780 }
1781 emitBuildVersion(Platform: getMachoBuildVersionPlatformType(Target),
1782 Major: LinkedTargetVersion.getMajor(),
1783 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1784 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1785 ShouldEmitBuildVersion = true;
1786 }
1787
1788 if (const Triple *TVT = DarwinTargetVariantTriple) {
1789 if (Target.isMacOSX() && TVT->isMacCatalystEnvironment()) {
1790 auto TVLinkedTargetVersion =
1791 targetVersionOrMinimumSupportedOSVersion(Target: *TVT, TargetVersion: TVT->getiOSVersion());
1792 emitDarwinTargetVariantBuildVersion(
1793 Platform: getMachoBuildVersionPlatformType(Target: *TVT),
1794 Major: TVLinkedTargetVersion.getMajor(),
1795 Minor: TVLinkedTargetVersion.getMinor().value_or(u: 0),
1796 Update: TVLinkedTargetVersion.getSubminor().value_or(u: 0),
1797 SDKVersion: DarwinTargetVariantSDKVersion);
1798 }
1799 }
1800
1801 if (ShouldEmitBuildVersion)
1802 return;
1803
1804 emitVersionMin(Type: getMachoVersionMinLoadCommandType(Target),
1805 Major: LinkedTargetVersion.getMajor(),
1806 Minor: LinkedTargetVersion.getMinor().value_or(u: 0),
1807 Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion);
1808}
1809