[ARM] MVE sext costs
[llvm-complete.git] / lib / MC / MCStreamer.cpp
blob3a52cd9e18affc499e39afb50c3aa25a474ffa4e
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 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/MCStreamer.h"
10 #include "llvm/ADT/Optional.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/BinaryFormat/COFF.h"
15 #include "llvm/MC/MCAsmBackend.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/MCObjectFileInfo.h"
24 #include "llvm/MC/MCSection.h"
25 #include "llvm/MC/MCSectionCOFF.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/MC/MCWin64EH.h"
28 #include "llvm/MC/MCWinEH.h"
29 #include "llvm/Support/Casting.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/LEB128.h"
32 #include "llvm/Support/MathExtras.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <cassert>
35 #include <cstdint>
36 #include <cstdlib>
37 #include <utility>
39 using namespace llvm;
41 MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) {
42 S.setTargetStreamer(this);
45 // Pin the vtables to this file.
46 MCTargetStreamer::~MCTargetStreamer() = default;
48 void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {}
50 void MCTargetStreamer::finish() {}
52 void MCTargetStreamer::changeSection(const MCSection *CurSection,
53 MCSection *Section,
54 const MCExpr *Subsection,
55 raw_ostream &OS) {
56 Section->PrintSwitchToSection(
57 *Streamer.getContext().getAsmInfo(),
58 Streamer.getContext().getObjectFileInfo()->getTargetTriple(), OS,
59 Subsection);
62 void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) {
63 Streamer.EmitRawText(Directive);
66 void MCTargetStreamer::emitValue(const MCExpr *Value) {
67 SmallString<128> Str;
68 raw_svector_ostream OS(Str);
70 Value->print(OS, Streamer.getContext().getAsmInfo());
71 Streamer.EmitRawText(OS.str());
74 void MCTargetStreamer::emitRawBytes(StringRef Data) {
75 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
76 const char *Directive = MAI->getData8bitsDirective();
77 for (const unsigned char C : Data.bytes()) {
78 SmallString<128> Str;
79 raw_svector_ostream OS(Str);
81 OS << Directive << (unsigned)C;
82 Streamer.EmitRawText(OS.str());
86 void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
88 MCStreamer::MCStreamer(MCContext &Ctx)
89 : Context(Ctx), CurrentWinFrameInfo(nullptr),
90 UseAssemblerInfoForParsing(false) {
91 SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
94 MCStreamer::~MCStreamer() {}
96 void MCStreamer::reset() {
97 DwarfFrameInfos.clear();
98 CurrentWinFrameInfo = nullptr;
99 WinFrameInfos.clear();
100 SymbolOrdering.clear();
101 SectionStack.clear();
102 SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
105 raw_ostream &MCStreamer::GetCommentOS() {
106 // By default, discard comments.
107 return nulls();
110 unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); }
111 ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const {
112 return DwarfFrameInfos;
115 void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {}
117 void MCStreamer::addExplicitComment(const Twine &T) {}
118 void MCStreamer::emitExplicitComments() {}
120 void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
121 for (auto &FI : DwarfFrameInfos)
122 FI.CompactUnwindEncoding =
123 (MAB ? MAB->generateCompactUnwindEncoding(FI.Instructions) : 0);
126 /// EmitIntValue - Special case of EmitValue that avoids the client having to
127 /// pass in a MCExpr for constant integers.
128 void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
129 assert(1 <= Size && Size <= 8 && "Invalid size");
130 assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
131 "Invalid size");
132 char buf[8];
133 const bool isLittleEndian = Context.getAsmInfo()->isLittleEndian();
134 for (unsigned i = 0; i != Size; ++i) {
135 unsigned index = isLittleEndian ? i : (Size - i - 1);
136 buf[i] = uint8_t(Value >> (index * 8));
138 EmitBytes(StringRef(buf, Size));
141 /// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
142 /// client having to pass in a MCExpr for constant integers.
143 void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned PadTo) {
144 SmallString<128> Tmp;
145 raw_svector_ostream OSE(Tmp);
146 encodeULEB128(Value, OSE, PadTo);
147 EmitBytes(OSE.str());
150 /// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
151 /// client having to pass in a MCExpr for constant integers.
152 void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
153 SmallString<128> Tmp;
154 raw_svector_ostream OSE(Tmp);
155 encodeSLEB128(Value, OSE);
156 EmitBytes(OSE.str());
159 void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
160 EmitValueImpl(Value, Size, Loc);
163 void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
164 bool IsSectionRelative) {
165 assert((!IsSectionRelative || Size == 4) &&
166 "SectionRelative value requires 4-bytes");
168 if (!IsSectionRelative)
169 EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
170 else
171 EmitCOFFSecRel32(Sym, /*Offset=*/0);
174 void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
175 report_fatal_error("unsupported directive in streamer");
178 void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) {
179 report_fatal_error("unsupported directive in streamer");
182 void MCStreamer::EmitTPRel64Value(const MCExpr *Value) {
183 report_fatal_error("unsupported directive in streamer");
186 void MCStreamer::EmitTPRel32Value(const MCExpr *Value) {
187 report_fatal_error("unsupported directive in streamer");
190 void MCStreamer::EmitGPRel64Value(const MCExpr *Value) {
191 report_fatal_error("unsupported directive in streamer");
194 void MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
195 report_fatal_error("unsupported directive in streamer");
198 /// Emit NumBytes bytes worth of the value specified by FillValue.
199 /// This implements directives such as '.space'.
200 void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
201 emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue);
204 /// The implementation in this class just redirects to emitFill.
205 void MCStreamer::EmitZeros(uint64_t NumBytes) {
206 emitFill(NumBytes, 0);
209 Expected<unsigned>
210 MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
211 StringRef Filename,
212 Optional<MD5::MD5Result> Checksum,
213 Optional<StringRef> Source,
214 unsigned CUID) {
215 return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
216 Source, CUID);
219 void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
220 StringRef Filename,
221 Optional<MD5::MD5Result> Checksum,
222 Optional<StringRef> Source,
223 unsigned CUID) {
224 getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
225 Source);
228 void MCStreamer::EmitCFIBKeyFrame() {
229 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
230 if (!CurFrame)
231 return;
232 CurFrame->IsBKeyFrame = true;
235 void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
236 unsigned Column, unsigned Flags,
237 unsigned Isa,
238 unsigned Discriminator,
239 StringRef FileName) {
240 getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
241 Discriminator);
244 MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
245 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
246 if (!Table.getLabel()) {
247 StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix();
248 Table.setLabel(
249 Context.getOrCreateSymbol(Prefix + "line_table_start" + Twine(CUID)));
251 return Table.getLabel();
254 bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
255 return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End;
258 MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
259 if (!hasUnfinishedDwarfFrameInfo()) {
260 getContext().reportError(SMLoc(), "this directive must appear between "
261 ".cfi_startproc and .cfi_endproc "
262 "directives");
263 return nullptr;
265 return &DwarfFrameInfos.back();
268 bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
269 ArrayRef<uint8_t> Checksum,
270 unsigned ChecksumKind) {
271 return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
272 ChecksumKind);
275 bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
276 return getContext().getCVContext().recordFunctionId(FunctionId);
279 bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
280 unsigned IAFunc, unsigned IAFile,
281 unsigned IALine, unsigned IACol,
282 SMLoc Loc) {
283 if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) {
284 getContext().reportError(Loc, "parent function id not introduced by "
285 ".cv_func_id or .cv_inline_site_id");
286 return true;
289 return getContext().getCVContext().recordInlinedCallSiteId(
290 FunctionId, IAFunc, IAFile, IALine, IACol);
293 void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
294 unsigned Line, unsigned Column,
295 bool PrologueEnd, bool IsStmt,
296 StringRef FileName, SMLoc Loc) {}
298 bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
299 SMLoc Loc) {
300 CodeViewContext &CVC = getContext().getCVContext();
301 MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId);
302 if (!FI) {
303 getContext().reportError(
304 Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
305 return false;
308 // Track the section
309 if (FI->Section == nullptr)
310 FI->Section = getCurrentSectionOnly();
311 else if (FI->Section != getCurrentSectionOnly()) {
312 getContext().reportError(
313 Loc,
314 "all .cv_loc directives for a function must be in the same section");
315 return false;
317 return true;
320 void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
321 const MCSymbol *Begin,
322 const MCSymbol *End) {}
324 void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
325 unsigned SourceFileId,
326 unsigned SourceLineNum,
327 const MCSymbol *FnStartSym,
328 const MCSymbol *FnEndSym) {}
330 /// Only call this on endian-specific types like ulittle16_t and little32_t, or
331 /// structs composed of them.
332 template <typename T>
333 static void copyBytesForDefRange(SmallString<20> &BytePrefix,
334 codeview::SymbolKind SymKind,
335 const T &DefRangeHeader) {
336 BytePrefix.resize(2 + sizeof(T));
337 codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind);
338 memcpy(&BytePrefix[0], &SymKindLE, 2);
339 memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
342 void MCStreamer::EmitCVDefRangeDirective(
343 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
344 StringRef FixedSizePortion) {}
346 void MCStreamer::EmitCVDefRangeDirective(
347 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
348 codeview::DefRangeRegisterRelSym::Header DRHdr) {
349 SmallString<20> BytePrefix;
350 copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER_REL, DRHdr);
351 EmitCVDefRangeDirective(Ranges, BytePrefix);
354 void MCStreamer::EmitCVDefRangeDirective(
355 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
356 codeview::DefRangeSubfieldRegisterSym::Header DRHdr) {
357 SmallString<20> BytePrefix;
358 copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_SUBFIELD_REGISTER,
359 DRHdr);
360 EmitCVDefRangeDirective(Ranges, BytePrefix);
363 void MCStreamer::EmitCVDefRangeDirective(
364 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
365 codeview::DefRangeRegisterSym::Header DRHdr) {
366 SmallString<20> BytePrefix;
367 copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER, DRHdr);
368 EmitCVDefRangeDirective(Ranges, BytePrefix);
371 void MCStreamer::EmitCVDefRangeDirective(
372 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
373 codeview::DefRangeFramePointerRelSym::Header DRHdr) {
374 SmallString<20> BytePrefix;
375 copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_FRAMEPOINTER_REL,
376 DRHdr);
377 EmitCVDefRangeDirective(Ranges, BytePrefix);
380 void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
381 MCSymbol *EHSymbol) {
384 void MCStreamer::InitSections(bool NoExecStack) {
385 SwitchSection(getContext().getObjectFileInfo()->getTextSection());
388 void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
389 assert(Fragment);
390 Symbol->setFragment(Fragment);
392 // As we emit symbols into a section, track the order so that they can
393 // be sorted upon later. Zero is reserved to mean 'unemitted'.
394 SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
397 void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
398 Symbol->redefineIfPossible();
400 if (!Symbol->isUndefined() || Symbol->isVariable())
401 return getContext().reportError(Loc, "invalid symbol redefinition");
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!");
408 Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());
410 MCTargetStreamer *TS = getTargetStreamer();
411 if (TS)
412 TS->emitLabel(Symbol);
415 void MCStreamer::EmitCFISections(bool EH, bool Debug) {
416 assert(EH || Debug);
419 void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) {
420 if (hasUnfinishedDwarfFrameInfo())
421 return getContext().reportError(
422 Loc, "starting new .cfi frame before finishing the previous one");
424 MCDwarfFrameInfo Frame;
425 Frame.IsSimple = IsSimple;
426 EmitCFIStartProcImpl(Frame);
428 const MCAsmInfo* MAI = Context.getAsmInfo();
429 if (MAI) {
430 for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) {
431 if (Inst.getOperation() == MCCFIInstruction::OpDefCfa ||
432 Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) {
433 Frame.CurrentCfaRegister = Inst.getRegister();
438 DwarfFrameInfos.push_back(Frame);
441 void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
444 void MCStreamer::EmitCFIEndProc() {
445 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
446 if (!CurFrame)
447 return;
448 EmitCFIEndProcImpl(*CurFrame);
451 void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
452 // Put a dummy non-null value in Frame.End to mark that this frame has been
453 // closed.
454 Frame.End = (MCSymbol *)1;
457 MCSymbol *MCStreamer::EmitCFILabel() {
458 // Return a dummy non-null value so that label fields appear filled in when
459 // generating textual assembly.
460 return (MCSymbol *)1;
463 void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
464 MCSymbol *Label = EmitCFILabel();
465 MCCFIInstruction Instruction =
466 MCCFIInstruction::createDefCfa(Label, Register, Offset);
467 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
468 if (!CurFrame)
469 return;
470 CurFrame->Instructions.push_back(Instruction);
471 CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
474 void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
475 MCSymbol *Label = EmitCFILabel();
476 MCCFIInstruction Instruction =
477 MCCFIInstruction::createDefCfaOffset(Label, Offset);
478 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
479 if (!CurFrame)
480 return;
481 CurFrame->Instructions.push_back(Instruction);
484 void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
485 MCSymbol *Label = EmitCFILabel();
486 MCCFIInstruction Instruction =
487 MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment);
488 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
489 if (!CurFrame)
490 return;
491 CurFrame->Instructions.push_back(Instruction);
494 void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
495 MCSymbol *Label = EmitCFILabel();
496 MCCFIInstruction Instruction =
497 MCCFIInstruction::createDefCfaRegister(Label, Register);
498 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
499 if (!CurFrame)
500 return;
501 CurFrame->Instructions.push_back(Instruction);
502 CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
505 void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
506 MCSymbol *Label = EmitCFILabel();
507 MCCFIInstruction Instruction =
508 MCCFIInstruction::createOffset(Label, Register, Offset);
509 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
510 if (!CurFrame)
511 return;
512 CurFrame->Instructions.push_back(Instruction);
515 void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
516 MCSymbol *Label = EmitCFILabel();
517 MCCFIInstruction Instruction =
518 MCCFIInstruction::createRelOffset(Label, Register, Offset);
519 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
520 if (!CurFrame)
521 return;
522 CurFrame->Instructions.push_back(Instruction);
525 void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
526 unsigned Encoding) {
527 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
528 if (!CurFrame)
529 return;
530 CurFrame->Personality = Sym;
531 CurFrame->PersonalityEncoding = Encoding;
534 void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
535 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
536 if (!CurFrame)
537 return;
538 CurFrame->Lsda = Sym;
539 CurFrame->LsdaEncoding = Encoding;
542 void MCStreamer::EmitCFIRememberState() {
543 MCSymbol *Label = EmitCFILabel();
544 MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label);
545 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
546 if (!CurFrame)
547 return;
548 CurFrame->Instructions.push_back(Instruction);
551 void MCStreamer::EmitCFIRestoreState() {
552 // FIXME: Error if there is no matching cfi_remember_state.
553 MCSymbol *Label = EmitCFILabel();
554 MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label);
555 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
556 if (!CurFrame)
557 return;
558 CurFrame->Instructions.push_back(Instruction);
561 void MCStreamer::EmitCFISameValue(int64_t Register) {
562 MCSymbol *Label = EmitCFILabel();
563 MCCFIInstruction Instruction =
564 MCCFIInstruction::createSameValue(Label, Register);
565 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
566 if (!CurFrame)
567 return;
568 CurFrame->Instructions.push_back(Instruction);
571 void MCStreamer::EmitCFIRestore(int64_t Register) {
572 MCSymbol *Label = EmitCFILabel();
573 MCCFIInstruction Instruction =
574 MCCFIInstruction::createRestore(Label, Register);
575 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
576 if (!CurFrame)
577 return;
578 CurFrame->Instructions.push_back(Instruction);
581 void MCStreamer::EmitCFIEscape(StringRef Values) {
582 MCSymbol *Label = EmitCFILabel();
583 MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values);
584 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
585 if (!CurFrame)
586 return;
587 CurFrame->Instructions.push_back(Instruction);
590 void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
591 MCSymbol *Label = EmitCFILabel();
592 MCCFIInstruction Instruction =
593 MCCFIInstruction::createGnuArgsSize(Label, Size);
594 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
595 if (!CurFrame)
596 return;
597 CurFrame->Instructions.push_back(Instruction);
600 void MCStreamer::EmitCFISignalFrame() {
601 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
602 if (!CurFrame)
603 return;
604 CurFrame->IsSignalFrame = true;
607 void MCStreamer::EmitCFIUndefined(int64_t Register) {
608 MCSymbol *Label = EmitCFILabel();
609 MCCFIInstruction Instruction =
610 MCCFIInstruction::createUndefined(Label, Register);
611 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
612 if (!CurFrame)
613 return;
614 CurFrame->Instructions.push_back(Instruction);
617 void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
618 MCSymbol *Label = EmitCFILabel();
619 MCCFIInstruction Instruction =
620 MCCFIInstruction::createRegister(Label, Register1, Register2);
621 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
622 if (!CurFrame)
623 return;
624 CurFrame->Instructions.push_back(Instruction);
627 void MCStreamer::EmitCFIWindowSave() {
628 MCSymbol *Label = EmitCFILabel();
629 MCCFIInstruction Instruction =
630 MCCFIInstruction::createWindowSave(Label);
631 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
632 if (!CurFrame)
633 return;
634 CurFrame->Instructions.push_back(Instruction);
637 void MCStreamer::EmitCFINegateRAState() {
638 MCSymbol *Label = EmitCFILabel();
639 MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label);
640 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
641 if (!CurFrame)
642 return;
643 CurFrame->Instructions.push_back(Instruction);
646 void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
647 MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
648 if (!CurFrame)
649 return;
650 CurFrame->RAReg = Register;
653 WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
654 const MCAsmInfo *MAI = Context.getAsmInfo();
655 if (!MAI->usesWindowsCFI()) {
656 getContext().reportError(
657 Loc, ".seh_* directives are not supported on this target");
658 return nullptr;
660 if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
661 getContext().reportError(
662 Loc, ".seh_ directive must appear within an active frame");
663 return nullptr;
665 return CurrentWinFrameInfo;
668 void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
669 const MCAsmInfo *MAI = Context.getAsmInfo();
670 if (!MAI->usesWindowsCFI())
671 return getContext().reportError(
672 Loc, ".seh_* directives are not supported on this target");
673 if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
674 getContext().reportError(
675 Loc, "Starting a function before ending the previous one!");
677 MCSymbol *StartProc = EmitCFILabel();
679 WinFrameInfos.emplace_back(
680 std::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
681 CurrentWinFrameInfo = WinFrameInfos.back().get();
682 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
685 void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
686 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
687 if (!CurFrame)
688 return;
689 if (CurFrame->ChainedParent)
690 getContext().reportError(Loc, "Not all chained regions terminated!");
692 MCSymbol *Label = EmitCFILabel();
693 CurFrame->End = Label;
696 void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
697 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
698 if (!CurFrame)
699 return;
700 if (CurFrame->ChainedParent)
701 getContext().reportError(Loc, "Not all chained regions terminated!");
703 MCSymbol *Label = EmitCFILabel();
704 CurFrame->FuncletOrFuncEnd = Label;
707 void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
708 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
709 if (!CurFrame)
710 return;
712 MCSymbol *StartProc = EmitCFILabel();
714 WinFrameInfos.emplace_back(std::make_unique<WinEH::FrameInfo>(
715 CurFrame->Function, StartProc, CurFrame));
716 CurrentWinFrameInfo = WinFrameInfos.back().get();
717 CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
720 void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) {
721 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
722 if (!CurFrame)
723 return;
724 if (!CurFrame->ChainedParent)
725 return getContext().reportError(
726 Loc, "End of a chained region outside a chained region!");
728 MCSymbol *Label = EmitCFILabel();
730 CurFrame->End = Label;
731 CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
734 void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
735 SMLoc Loc) {
736 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
737 if (!CurFrame)
738 return;
739 if (CurFrame->ChainedParent)
740 return getContext().reportError(
741 Loc, "Chained unwind areas can't have handlers!");
742 CurFrame->ExceptionHandler = Sym;
743 if (!Except && !Unwind)
744 getContext().reportError(Loc, "Don't know what kind of handler this is!");
745 if (Unwind)
746 CurFrame->HandlesUnwind = true;
747 if (Except)
748 CurFrame->HandlesExceptions = true;
751 void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) {
752 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
753 if (!CurFrame)
754 return;
755 if (CurFrame->ChainedParent)
756 getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
759 void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
760 const MCSymbolRefExpr *To, uint64_t Count) {
763 static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
764 MCSection *MainCFISec,
765 const MCSection *TextSec) {
766 // If this is the main .text section, use the main unwind info section.
767 if (TextSec == Context.getObjectFileInfo()->getTextSection())
768 return MainCFISec;
770 const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec);
771 auto *MainCFISecCOFF = cast<MCSectionCOFF>(MainCFISec);
772 unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID);
774 // If this section is COMDAT, this unwind section should be COMDAT associative
775 // with its group.
776 const MCSymbol *KeySym = nullptr;
777 if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
778 KeySym = TextSecCOFF->getCOMDATSymbol();
780 // In a GNU environment, we can't use associative comdats. Instead, do what
781 // GCC does, which is to make plain comdat selectany section named like
782 // ".[px]data$_Z3foov".
783 if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
784 std::string SectionName =
785 (MainCFISecCOFF->getSectionName() + "$" +
786 TextSecCOFF->getSectionName().split('$').second)
787 .str();
788 return Context.getCOFFSection(
789 SectionName,
790 MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT,
791 MainCFISecCOFF->getKind(), "", COFF::IMAGE_COMDAT_SELECT_ANY);
795 return Context.getAssociativeCOFFSection(MainCFISecCOFF, KeySym, UniqueID);
798 MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
799 return getWinCFISection(getContext(), &NextWinCFIID,
800 getContext().getObjectFileInfo()->getPDataSection(),
801 TextSec);
804 MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
805 return getWinCFISection(getContext(), &NextWinCFIID,
806 getContext().getObjectFileInfo()->getXDataSection(),
807 TextSec);
810 void MCStreamer::EmitSyntaxDirective() {}
812 void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
813 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
814 if (!CurFrame)
815 return;
817 MCSymbol *Label = EmitCFILabel();
819 WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
820 CurFrame->Instructions.push_back(Inst);
823 void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
824 SMLoc Loc) {
825 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
826 if (!CurFrame)
827 return;
828 if (CurFrame->LastFrameInst >= 0)
829 return getContext().reportError(
830 Loc, "frame register and offset can be set at most once");
831 if (Offset & 0x0F)
832 return getContext().reportError(Loc, "offset is not a multiple of 16");
833 if (Offset > 240)
834 return getContext().reportError(
835 Loc, "frame offset must be less than or equal to 240");
837 MCSymbol *Label = EmitCFILabel();
839 WinEH::Instruction Inst =
840 Win64EH::Instruction::SetFPReg(Label, Register, Offset);
841 CurFrame->LastFrameInst = CurFrame->Instructions.size();
842 CurFrame->Instructions.push_back(Inst);
845 void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
846 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
847 if (!CurFrame)
848 return;
849 if (Size == 0)
850 return getContext().reportError(Loc,
851 "stack allocation size must be non-zero");
852 if (Size & 7)
853 return getContext().reportError(
854 Loc, "stack allocation size is not a multiple of 8");
856 MCSymbol *Label = EmitCFILabel();
858 WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
859 CurFrame->Instructions.push_back(Inst);
862 void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
863 SMLoc Loc) {
864 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
865 if (!CurFrame)
866 return;
868 if (Offset & 7)
869 return getContext().reportError(
870 Loc, "register save offset is not 8 byte aligned");
872 MCSymbol *Label = EmitCFILabel();
874 WinEH::Instruction Inst =
875 Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
876 CurFrame->Instructions.push_back(Inst);
879 void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
880 SMLoc Loc) {
881 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
882 if (!CurFrame)
883 return;
884 if (Offset & 0x0F)
885 return getContext().reportError(Loc, "offset is not a multiple of 16");
887 MCSymbol *Label = EmitCFILabel();
889 WinEH::Instruction Inst =
890 Win64EH::Instruction::SaveXMM(Label, Register, Offset);
891 CurFrame->Instructions.push_back(Inst);
894 void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
895 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
896 if (!CurFrame)
897 return;
898 if (!CurFrame->Instructions.empty())
899 return getContext().reportError(
900 Loc, "If present, PushMachFrame must be the first UOP");
902 MCSymbol *Label = EmitCFILabel();
904 WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
905 CurFrame->Instructions.push_back(Inst);
908 void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
909 WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
910 if (!CurFrame)
911 return;
913 MCSymbol *Label = EmitCFILabel();
915 CurFrame->PrologEnd = Label;
918 void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {}
920 void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {}
922 void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {}
924 void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
926 void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
928 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
929 /// the specified string in the output .s file. This capability is
930 /// indicated by the hasRawTextSupport() predicate.
931 void MCStreamer::EmitRawTextImpl(StringRef String) {
932 // This is not llvm_unreachable for the sake of out of tree backend
933 // developers who may not have assembly streamers and should serve as a
934 // reminder to not accidentally call EmitRawText in the absence of such.
935 report_fatal_error("EmitRawText called on an MCStreamer that doesn't support "
936 "it (target backend is likely missing an AsmStreamer "
937 "implementation)");
940 void MCStreamer::EmitRawText(const Twine &T) {
941 SmallString<128> Str;
942 EmitRawTextImpl(T.toStringRef(Str));
945 void MCStreamer::EmitWindowsUnwindTables() {
948 void MCStreamer::Finish() {
949 if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
950 (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
951 getContext().reportError(SMLoc(), "Unfinished frame!");
952 return;
955 MCTargetStreamer *TS = getTargetStreamer();
956 if (TS)
957 TS->finish();
959 FinishImpl();
962 void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
963 visitUsedExpr(*Value);
964 Symbol->setVariableValue(Value);
966 MCTargetStreamer *TS = getTargetStreamer();
967 if (TS)
968 TS->emitAssignment(Symbol, Value);
971 void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
972 raw_ostream &OS, const MCInst &Inst,
973 const MCSubtargetInfo &STI) {
974 InstPrinter.printInst(&Inst, OS, "", STI);
977 void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
980 void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
981 switch (Expr.getKind()) {
982 case MCExpr::Target:
983 cast<MCTargetExpr>(Expr).visitUsedExpr(*this);
984 break;
986 case MCExpr::Constant:
987 break;
989 case MCExpr::Binary: {
990 const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr);
991 visitUsedExpr(*BE.getLHS());
992 visitUsedExpr(*BE.getRHS());
993 break;
996 case MCExpr::SymbolRef:
997 visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol());
998 break;
1000 case MCExpr::Unary:
1001 visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr());
1002 break;
1006 void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
1007 // Scan for values.
1008 for (unsigned i = Inst.getNumOperands(); i--;)
1009 if (Inst.getOperand(i).isExpr())
1010 visitUsedExpr(*Inst.getOperand(i).getExpr());
1013 void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
1014 unsigned Size) {
1015 // Get the Hi-Lo expression.
1016 const MCExpr *Diff =
1017 MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
1018 MCSymbolRefExpr::create(Lo, Context), Context);
1020 const MCAsmInfo *MAI = Context.getAsmInfo();
1021 if (!MAI->doesSetDirectiveSuppressReloc()) {
1022 EmitValue(Diff, Size);
1023 return;
1026 // Otherwise, emit with .set (aka assignment).
1027 MCSymbol *SetLabel = Context.createTempSymbol("set", true);
1028 EmitAssignment(SetLabel, Diff);
1029 EmitSymbolValue(SetLabel, Size);
1032 void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
1033 const MCSymbol *Lo) {
1034 // Get the Hi-Lo expression.
1035 const MCExpr *Diff =
1036 MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
1037 MCSymbolRefExpr::create(Lo, Context), Context);
1039 EmitULEB128Value(Diff);
1042 void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
1043 void MCStreamer::EmitThumbFunc(MCSymbol *Func) {}
1044 void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
1045 void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
1046 llvm_unreachable("this directive only supported on COFF targets");
1048 void MCStreamer::EndCOFFSymbolDef() {
1049 llvm_unreachable("this directive only supported on COFF targets");
1051 void MCStreamer::EmitFileDirective(StringRef Filename) {}
1052 void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
1053 llvm_unreachable("this directive only supported on COFF targets");
1055 void MCStreamer::EmitCOFFSymbolType(int Type) {
1056 llvm_unreachable("this directive only supported on COFF targets");
1058 void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1059 unsigned ByteAlign) {
1060 llvm_unreachable("this directive only supported on XCOFF targets");
1062 void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
1063 void MCStreamer::emitELFSymverDirective(StringRef AliasName,
1064 const MCSymbol *Aliasee) {}
1065 void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1066 unsigned ByteAlignment) {}
1067 void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1068 uint64_t Size, unsigned ByteAlignment) {}
1069 void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {}
1070 void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
1071 void MCStreamer::EmitBytes(StringRef Data) {}
1072 void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); }
1073 void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
1074 visitUsedExpr(*Value);
1076 void MCStreamer::EmitULEB128Value(const MCExpr *Value) {}
1077 void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {}
1078 void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
1079 void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
1080 SMLoc Loc) {}
1081 void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
1082 unsigned ValueSize,
1083 unsigned MaxBytesToEmit) {}
1084 void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment,
1085 unsigned MaxBytesToEmit) {}
1086 void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
1087 SMLoc Loc) {}
1088 void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {}
1089 void MCStreamer::EmitBundleLock(bool AlignToEnd) {}
1090 void MCStreamer::FinishImpl() {}
1091 void MCStreamer::EmitBundleUnlock() {}
1093 void MCStreamer::SwitchSection(MCSection *Section, const MCExpr *Subsection) {
1094 assert(Section && "Cannot switch to a null section!");
1095 MCSectionSubPair curSection = SectionStack.back().first;
1096 SectionStack.back().second = curSection;
1097 if (MCSectionSubPair(Section, Subsection) != curSection) {
1098 ChangeSection(Section, Subsection);
1099 SectionStack.back().first = MCSectionSubPair(Section, Subsection);
1100 assert(!Section->hasEnded() && "Section already ended");
1101 MCSymbol *Sym = Section->getBeginSymbol();
1102 if (Sym && !Sym->isInSection())
1103 EmitLabel(Sym);
1107 MCSymbol *MCStreamer::endSection(MCSection *Section) {
1108 // TODO: keep track of the last subsection so that this symbol appears in the
1109 // correct place.
1110 MCSymbol *Sym = Section->getEndSymbol(Context);
1111 if (Sym->isInSection())
1112 return Sym;
1114 SwitchSection(Section);
1115 EmitLabel(Sym);
1116 return Sym;
1119 void MCStreamer::EmitVersionForTarget(const Triple &Target,
1120 const VersionTuple &SDKVersion) {
1121 if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
1122 return;
1123 // Do we even know the version?
1124 if (Target.getOSMajorVersion() == 0)
1125 return;
1127 unsigned Major;
1128 unsigned Minor;
1129 unsigned Update;
1130 if (Target.isMacCatalystEnvironment()) {
1131 // Mac Catalyst always uses the build version load command.
1132 Target.getiOSVersion(Major, Minor, Update);
1133 assert(Major && "A non-zero major version is expected");
1134 EmitBuildVersion(MachO::PLATFORM_MACCATALYST, Major, Minor, Update,
1135 SDKVersion);
1136 return;
1139 MCVersionMinType VersionType;
1140 if (Target.isWatchOS()) {
1141 VersionType = MCVM_WatchOSVersionMin;
1142 Target.getWatchOSVersion(Major, Minor, Update);
1143 } else if (Target.isTvOS()) {
1144 VersionType = MCVM_TvOSVersionMin;
1145 Target.getiOSVersion(Major, Minor, Update);
1146 } else if (Target.isMacOSX()) {
1147 VersionType = MCVM_OSXVersionMin;
1148 if (!Target.getMacOSXVersion(Major, Minor, Update))
1149 Major = 0;
1150 } else {
1151 VersionType = MCVM_IOSVersionMin;
1152 Target.getiOSVersion(Major, Minor, Update);
1154 if (Major != 0)
1155 EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion);