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