LLVM 23.0.0git
MCAsmStreamer.cpp
Go to the documentation of this file.
1//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
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
12#include "llvm/ADT/Twine.h"
15#include "llvm/MC/MCAsmInfo.h"
16#include "llvm/MC/MCAssembler.h"
18#include "llvm/MC/MCCodeView.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCLFI.h"
28#include "llvm/MC/MCRegister.h"
31#include "llvm/MC/MCStreamer.h"
35#include "llvm/Support/Format.h"
37#include "llvm/Support/LEB128.h"
39#include "llvm/Support/Path.h"
40#include <algorithm>
41#include <optional>
42
43using namespace llvm;
44
46 std::unique_ptr<MCCodeEmitter> Emitter,
47 std::unique_ptr<MCAsmBackend> AsmBackend)
48 : MCStreamer(Context),
49 Assembler(std::make_unique<MCAssembler>(
50 Context, std::move(AsmBackend), std::move(Emitter),
51 (AsmBackend) ? AsmBackend->createObjectWriter(NullStream) : nullptr)),
53
55 const MCSubtargetInfo &STI) {
59
60 // If we have no code emitter, don't emit code.
61 if (!getAssembler().getEmitterPtr())
62 return;
63
64 getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
65
66 // RISC-V instructions are always little-endian, even on BE systems.
67 bool ForceLE = getContext().getTargetTriple().isRISCV();
68
69 const MCAsmInfo &MAI = getContext().getAsmInfo();
70
71 // If we are showing fixups, create symbolic markers in the encoded
72 // representation. We do this by making a per-bit map to the fixup item index,
73 // then trying to display it as nicely as possible.
75 FixupMap.resize(Code.size() * 8);
76 for (unsigned I = 0, E = Code.size() * 8; I != E; ++I)
77 FixupMap[I] = 0;
78
79 for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
80 MCFixup &F = Fixups[I];
81 MCFixupKindInfo Info =
83 for (unsigned J = 0; J != Info.TargetSize; ++J) {
84 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + J;
85 assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
86 FixupMap[Index] = 1 + I;
87 }
88 }
89
90 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
91 // high order halfword of a 32-bit Thumb2 instruction is emitted first.
92 OS << "encoding: [";
93 for (unsigned I = 0, E = Code.size(); I != E; ++I) {
94 if (I)
95 OS << ',';
96
97 // See if all bits are the same map entry.
98 uint8_t MapEntry = FixupMap[I * 8 + 0];
99 for (unsigned J = 1; J != 8; ++J) {
100 if (FixupMap[I * 8 + J] == MapEntry)
101 continue;
102
103 MapEntry = uint8_t(~0U);
104 break;
105 }
106
107 if (MapEntry != uint8_t(~0U)) {
108 if (MapEntry == 0) {
109 OS << format("0x%02x", uint8_t(Code[I]));
110 } else {
111 if (Code[I]) {
112 // FIXME: Some of the 8 bits require fix up.
113 OS << format("0x%02x", uint8_t(Code[I])) << '\''
114 << char('A' + MapEntry - 1) << '\'';
115 } else
116 OS << char('A' + MapEntry - 1);
117 }
118 } else {
119 // Otherwise, write out in binary.
120 OS << "0b";
121 for (unsigned J = 8; J--;) {
122 unsigned Bit = (Code[I] >> J) & 1;
123
124 unsigned FixupBit;
125 // RISC-V instructions are always little-endian.
126 // The FixupMap is indexed by actual bit positions in the LE
127 // instruction.
128 if (MAI.isLittleEndian() || ForceLE)
129 FixupBit = I * 8 + J;
130 else
131 FixupBit = I * 8 + (7 - J);
132
133 if (uint8_t MapEntry = FixupMap[FixupBit]) {
134 assert(Bit == 0 && "Encoder wrote into fixed up bit!");
135 OS << char('A' + MapEntry - 1);
136 } else
137 OS << Bit;
138 }
139 }
140 }
141 OS << "]\n";
142
143 for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
144 MCFixup &F = Fixups[I];
145 OS << " fixup " << char('A' + I) << " - "
146 << "offset: " << F.getOffset() << ", value: ";
147 MAI.printExpr(OS, *F.getValue());
148 auto Kind = F.getKind();
149 if (mc::isRelocation(Kind))
150 OS << ", relocation type: " << Kind;
151 else {
152 OS << ", kind: ";
153 auto Info = getAssembler().getBackend().getFixupKindInfo(Kind);
154 if (F.isPCRel() && StringRef(Info.Name).starts_with("FK_Data_"))
155 OS << "FK_PCRel_" << (Info.TargetSize / 8);
156 else
157 OS << Info.Name;
158 }
159 OS << '\n';
160 }
161}
162
163namespace {
164
165class MCAsmStreamer final : public MCAsmBaseStreamer {
166 std::unique_ptr<formatted_raw_ostream> OSOwner;
168 const MCAsmInfo *MAI;
169 std::unique_ptr<MCInstPrinter> InstPrinter;
170
171 SmallString<128> ExplicitCommentToEmit;
172
173 bool EmittedSectionDirective = false;
174
175 bool IsVerboseAsm = false;
176 bool ShowInst = false;
177 bool UseDwarfDirectory = false;
178
179 void EmitRegisterName(int64_t Register);
180 void PrintQuotedString(StringRef Data, raw_ostream &OS) const;
181 void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
183 std::optional<MD5::MD5Result> Checksum,
184 std::optional<StringRef> Source,
185 bool UseDwarfDirectory,
186 raw_svector_ostream &OS) const;
187 void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
188 void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
189
190 /// Helper to emit common .loc directive flags, isa, and discriminator.
191 void emitDwarfLocDirectiveFlags(unsigned Flags, unsigned Isa,
192 unsigned Discriminator);
193
194 /// Helper to emit the common suffix of .loc directives (flags, comment, EOL,
195 /// parent call).
196 void emitDwarfLocDirectiveSuffix(unsigned FileNo, unsigned Line,
197 unsigned Column, unsigned Flags,
198 unsigned Isa, unsigned Discriminator,
199 StringRef FileName, StringRef Comment);
200
201public:
202 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
203 std::unique_ptr<MCInstPrinter> printer,
204 std::unique_ptr<MCCodeEmitter> emitter,
205 std::unique_ptr<MCAsmBackend> asmbackend)
206 : MCAsmBaseStreamer(Context, std::move(emitter), std::move(asmbackend)),
207 OSOwner(std::move(os)), OS(*OSOwner), MAI(&Context.getAsmInfo()),
208 InstPrinter(std::move(printer)) {
209 assert(InstPrinter);
210 if (Assembler->getBackendPtr())
211 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
212
213 Context.setUseNamesOnTempLabels(true);
214
215 const MCTargetOptions &TO = Context.getTargetOptions();
216 IsVerboseAsm = TO.AsmVerbose;
217 if (IsVerboseAsm)
218 InstPrinter->setCommentStream(CommentStream);
219 ShowInst = TO.ShowMCInst;
220 switch (TO.MCUseDwarfDirectory) {
222 UseDwarfDirectory = false;
223 break;
225 UseDwarfDirectory = true;
226 break;
228 UseDwarfDirectory =
229 Context.getAsmInfo().enableDwarfFileDirectoryDefault();
230 break;
231 }
232 }
233
234 MCAssembler *getAssemblerPtr() override { return nullptr; }
235
236 inline void EmitEOL() {
237 // Dump Explicit Comments here.
238 emitExplicitComments();
239 // If we don't have any comments, just emit a \n.
240 if (!IsVerboseAsm) {
241 OS << '\n';
242 return;
243 }
244 EmitCommentsAndEOL();
245 }
246
247 void emitSyntaxDirective(StringRef Syntax, StringRef Options) override;
248
249 void EmitCommentsAndEOL();
250
251 /// Return true if this streamer supports verbose assembly at all.
252 bool isVerboseAsm() const override { return IsVerboseAsm; }
253
254 /// Do we support EmitRawText?
255 bool hasRawTextSupport() const override { return true; }
256
257 /// Add a comment that can be emitted to the generated .s file to make the
258 /// output of the compiler more readable. This only affects the MCAsmStreamer
259 /// and only when verbose assembly output is enabled.
260 void AddComment(const Twine &T, bool EOL = true) override;
261
262 void emitRawComment(const Twine &T, bool TabPrefix = true) override;
263
264 void addExplicitComment(const Twine &T) override;
265 void emitExplicitComments() override;
266
267 /// Emit a blank line to a .s file to pretty it up.
268 void addBlankLine() override { EmitEOL(); }
269
270 /// @name MCStreamer Interface
271 /// @{
272
273 void switchSection(MCSection *Section, uint32_t Subsection) override;
274 bool popSection() override;
275
276 void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
277 bool KeepOriginalSym) override;
278
279 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
280
281 void emitGNUAttribute(unsigned Tag, unsigned Value) override;
282
283 StringRef getMnemonic(const MCInst &MI) const override {
284 auto [Ptr, Bits] = InstPrinter->getMnemonic(MI);
285 assert((Bits != 0 || Ptr == nullptr) &&
286 "Invalid char pointer for instruction with no mnemonic");
287 return Ptr;
288 }
289
290 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
291
292 void emitSubsectionsViaSymbols() override;
293 void emitLinkerOptions(ArrayRef<std::string> Options) override;
294 void emitDataRegion(MCDataRegionType Kind) override;
295 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
296 unsigned Update, VersionTuple SDKVersion) override;
297 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
298 unsigned Update, VersionTuple SDKVersion) override;
299 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
300 unsigned Minor, unsigned Update,
301 VersionTuple SDKVersion) override;
302
303 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
304 void emitConditionalAssignment(MCSymbol *Symbol,
305 const MCExpr *Value) override;
306 void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
307 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
308
309 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
310 void beginCOFFSymbolDef(const MCSymbol *Symbol) override;
311 void emitCOFFSymbolStorageClass(int StorageClass) override;
312 void emitCOFFSymbolType(int Type) override;
313 void endCOFFSymbolDef() override;
314 void emitCOFFSafeSEH(MCSymbol const *Symbol) override;
315 void emitCOFFSymbolIndex(MCSymbol const *Symbol) override;
316 void emitCOFFSectionIndex(MCSymbol const *Symbol) override;
317 void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
318 void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
319 void emitCOFFSecNumber(MCSymbol const *Symbol) override;
320 void emitCOFFSecOffset(MCSymbol const *Symbol) override;
321 void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
322 MCSymbol *CsectSym, Align Alignment) override;
323 void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
325 MCSymbolAttr Visibility) override;
326 void emitXCOFFRenameDirective(const MCSymbol *Name,
327 StringRef Rename) override;
328
329 void emitXCOFFRefDirective(const MCSymbol *Symbol) override;
330
331 void emitXCOFFExceptDirective(const MCSymbol *Symbol,
332 const MCSymbol *Trap,
333 unsigned Lang, unsigned Reason,
334 unsigned FunctionSize, bool hasDebug) override;
335 void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override;
336
337 void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
338 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
339 Align ByteAlignment) override;
340
341 /// Emit a local common (.lcomm) symbol.
342 ///
343 /// @param Symbol - The common symbol to emit.
344 /// @param Size - The size of the common symbol.
345 /// @param ByteAlignment - The alignment of the common symbol in bytes.
346 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
347 Align ByteAlignment) override;
348
349 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
350 uint64_t Size = 0, Align ByteAlignment = Align(1),
351 SMLoc Loc = SMLoc()) override;
352
353 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
354 Align ByteAlignment = Align(1)) override;
355
356 void emitBinaryData(StringRef Data) override;
357
358 void emitBytes(StringRef Data) override;
359
360 void emitValueImpl(const MCExpr *Value, unsigned Size,
361 SMLoc Loc = SMLoc()) override;
362 void emitIntValue(uint64_t Value, unsigned Size) override;
363 void emitIntValueInHex(uint64_t Value, unsigned Size) override;
364 void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
365
366 void emitULEB128Value(const MCExpr *Value) override;
367
368 void emitSLEB128Value(const MCExpr *Value) override;
369
370 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
371 SMLoc Loc = SMLoc()) override;
372
373 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
374 SMLoc Loc = SMLoc()) override;
375
376 void emitAlignmentDirective(uint64_t ByteAlignment,
377 std::optional<int64_t> Value, unsigned ValueSize,
378 unsigned MaxBytesToEmit);
379
380 void emitValueToAlignment(Align Alignment, int64_t Fill = 0,
381 uint8_t FillLen = 1,
382 unsigned MaxBytesToEmit = 0) override;
383
384 void emitCodeAlignment(Align Alignment, const MCSubtargetInfo &STI,
385 unsigned MaxBytesToEmit = 0) override;
386 void emitPrefAlign(Align Alignment, const MCSymbol &End, bool EmitNops,
387 uint8_t Fill, const MCSubtargetInfo &STI) override;
388
389 void emitValueToOffset(const MCExpr *Offset,
390 unsigned char Value,
391 SMLoc Loc) override;
392
393 void emitFileDirective(StringRef Filename) override;
394 void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
395 StringRef TimeStamp, StringRef Description) override;
396 Expected<unsigned> tryEmitDwarfFileDirective(
397 unsigned FileNo, StringRef Directory, StringRef Filename,
398 std::optional<MD5::MD5Result> Checksum = std::nullopt,
399 std::optional<StringRef> Source = std::nullopt,
400 unsigned CUID = 0) override;
401 void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
402 std::optional<MD5::MD5Result> Checksum,
403 std::optional<StringRef> Source,
404 unsigned CUID = 0) override;
405 void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
406 unsigned Flags, unsigned Isa,
407 unsigned Discriminator, StringRef FileName,
408 StringRef Location = {}) override;
409 void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) override;
410
411 /// This is same as emitDwarfLocDirective, except also emits inlined function
412 /// and inlined callsite information.
413 void emitDwarfLocDirectiveWithInlinedAt(unsigned FileNo, unsigned Line,
414 unsigned Column, unsigned FileIA,
415 unsigned LineIA, unsigned ColIA,
416 const MCSymbol *Sym, unsigned Flags,
417 unsigned Isa, unsigned Discriminator,
418 StringRef FileName,
419 StringRef Comment = {}) override;
420
421 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
422
423 bool emitCVFileDirective(unsigned FileNo, StringRef Filename,
424 ArrayRef<uint8_t> Checksum,
425 unsigned ChecksumKind) override;
426 bool emitCVFuncIdDirective(unsigned FuncId) override;
427 bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
428 unsigned IAFile, unsigned IALine,
429 unsigned IACol, SMLoc Loc) override;
430 void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
431 unsigned Column, bool PrologueEnd, bool IsStmt,
432 StringRef FileName, SMLoc Loc) override;
433 void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
434 const MCSymbol *FnEnd) override;
435 void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
436 unsigned SourceFileId,
437 unsigned SourceLineNum,
438 const MCSymbol *FnStartSym,
439 const MCSymbol *FnEndSym) override;
440
441 void PrintCVDefRangePrefix(
442 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
443
444 void emitCVDefRangeDirective(
445 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
446 codeview::DefRangeRegisterRelHeader DRHdr) override;
447
448 void emitCVDefRangeDirective(
449 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
450 codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
451
452 void emitCVDefRangeDirective(
453 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
454 codeview::DefRangeRegisterHeader DRHdr) override;
455
456 void emitCVDefRangeDirective(
457 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
458 codeview::DefRangeFramePointerRelHeader DRHdr) override;
459
460 void emitCVDefRangeDirective(
461 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
462 codeview::DefRangeRegisterRelIndirHeader DRHdr) override;
463
464 void emitCVStringTableDirective() override;
465 void emitCVFileChecksumsDirective() override;
466 void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
467 void emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
468
469 void emitIdent(StringRef IdentString) override;
470 void emitCFIBKeyFrame() override;
471 void emitCFIMTETaggedFrame() override;
472 void emitCFISections(bool EH, bool Debug, bool SFrame) override;
473 void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) override;
474 void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) override;
475 void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) override;
476 void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
477 int64_t AddressSpace, SMLoc Loc) override;
478 void emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;
479 void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
480 void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
481 void emitCFIRememberState(SMLoc Loc) override;
482 void emitCFIRestoreState(SMLoc Loc) override;
483 void emitCFIRestore(int64_t Register, SMLoc Loc) override;
484 void emitCFISameValue(int64_t Register, SMLoc Loc) override;
485 void emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;
486 void emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) override;
487 void emitCFIEscape(StringRef Values, SMLoc Loc) override;
488 void emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) override;
489 void emitCFISignalFrame() override;
490 void emitCFIUndefined(int64_t Register, SMLoc Loc) override;
491 void emitCFIRegister(int64_t Register1, int64_t Register2,
492 SMLoc Loc) override;
493 void emitCFIWindowSave(SMLoc Loc) override;
494 void emitCFINegateRAState(SMLoc Loc) override;
495 void emitCFINegateRAStateWithPC(SMLoc Loc) override;
496 void emitCFIReturnColumn(int64_t Register) override;
497 void emitCFILLVMRegisterPair(int64_t Register, int64_t R1, int64_t R1Size,
498 int64_t R2, int64_t R2Size, SMLoc Loc) override;
499 void emitCFILLVMVectorRegisters(
501 SMLoc Loc) override;
502 void emitCFILLVMVectorOffset(int64_t Register, int64_t RegisterSize,
503 int64_t MaskRegister, int64_t MaskRegisterSize,
504 int64_t Offset, SMLoc Loc) override;
505 void emitCFILLVMVectorRegisterMask(int64_t Register, int64_t SpillRegister,
506 int64_t SpillRegisterLaneSizeInBits,
507 int64_t MaskRegister,
508 int64_t MaskRegisterSizeInBits,
509 SMLoc Loc) override;
510
511 void emitCFILabelDirective(SMLoc Loc, StringRef Name) override;
512 void emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;
513
514 void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
515 void emitWinCFIEndProc(SMLoc Loc) override;
516 void emitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
517 void emitWinCFISplitChained(SMLoc Loc) override;
518 void emitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
519 void emitWinCFIPush2Regs(MCRegister Reg1, MCRegister Reg2,
520 SMLoc Loc) override;
521 void emitWinCFISetFrame(MCRegister Register, unsigned Offset,
522 SMLoc Loc) override;
523 void emitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
524 void emitWinCFISaveReg(MCRegister Register, unsigned Offset,
525 SMLoc Loc) override;
526 void emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
527 SMLoc Loc) override;
528 void emitWinCFIPushFrame(bool Code, SMLoc Loc) override;
529 void emitWinCFIEndProlog(SMLoc Loc) override;
530 void emitWinCFIBeginEpilogue(SMLoc Loc) override;
531 void emitWinCFIEndEpilogue(SMLoc Loc) override;
532 void emitWinCFIUnwindV2Start(SMLoc Loc) override;
533 void emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc) override;
534
535 void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
536 SMLoc Loc) override;
537 void emitWinEHHandlerData(SMLoc Loc) override;
538
539 void emitCGProfileEntry(const MCSymbolRefExpr *From,
540 const MCSymbolRefExpr *To, uint64_t Count) override;
541
542 void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
543
544 void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
545 uint64_t Attr, uint64_t Discriminator,
546 const MCPseudoProbeInlineStack &InlineStack,
547 MCSymbol *FnSym) override;
548
549 void emitRelocDirective(const MCExpr &Offset, StringRef Name,
550 const MCExpr *Expr, SMLoc Loc) override;
551
552 void emitAddrsig() override;
553 void emitAddrsigSym(const MCSymbol *Sym) override;
554
555 /// If this file is backed by an assembly streamer, this dumps the specified
556 /// string in the output .s file. This capability is indicated by the
557 /// hasRawTextSupport() predicate.
558 void emitRawTextImpl(StringRef String) override;
559
560 void finishImpl() override;
561
562 void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;
563
564 MCSymbol *emitDwarfUnitLength(const Twine &Prefix,
565 const Twine &Comment) override;
566
567 void emitDwarfLineStartLabel(MCSymbol *StartSym) override;
568
569 void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel,
570 MCSymbol *EndLabel = nullptr) override;
571
572 void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
573 const MCSymbol *Label,
574 unsigned PointerSize) override;
575};
576
577} // end anonymous namespace.
578
579void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
580 if (!IsVerboseAsm) return;
581
582 T.toVector(CommentToEmit);
583
584 if (EOL)
585 CommentToEmit.push_back('\n'); // Place comment in a new line.
586}
587
588void MCAsmStreamer::EmitCommentsAndEOL() {
589 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
590 OS << '\n';
591 return;
592 }
593
594 StringRef Comments = CommentToEmit;
595
596 assert(Comments.back() == '\n' &&
597 "Comment array not newline terminated");
598 do {
599 // Emit a line of comments.
600 OS.PadToColumn(MAI->getCommentColumn());
601 size_t Position = Comments.find('\n');
602 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
603
604 Comments = Comments.substr(Position+1);
605 } while (!Comments.empty());
606
607 CommentToEmit.clear();
608}
609
610static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
611 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
612 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
613}
614
615void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
616 if (TabPrefix)
617 OS << '\t';
618 OS << MAI->getCommentString() << T;
619 EmitEOL();
620}
621
622void MCAsmStreamer::addExplicitComment(const Twine &T) {
623 StringRef c = T.getSingleStringRef();
624 if (c == MAI->getSeparatorString())
625 return;
626 if (c.starts_with(StringRef("//"))) {
627 ExplicitCommentToEmit.append("\t");
628 ExplicitCommentToEmit.append(MAI->getCommentString());
629 // drop //
630 ExplicitCommentToEmit.append(c.substr(2).str());
631 } else if (c.starts_with(StringRef("/*"))) {
632 size_t p = 2, len = c.size() - 2;
633 // emit each line in comment as separate newline.
634 do {
635 size_t newp = std::min(len, c.find_first_of("\r\n", p));
636 ExplicitCommentToEmit.append("\t");
637 ExplicitCommentToEmit.append(MAI->getCommentString());
638 ExplicitCommentToEmit.append(c.slice(p, newp).str());
639 // If we have another line in this comment add line
640 if (newp < len)
641 ExplicitCommentToEmit.append("\n");
642 p = newp + 1;
643 } while (p < len);
644 } else if (c.starts_with(StringRef(MAI->getCommentString()))) {
645 ExplicitCommentToEmit.append("\t");
646 ExplicitCommentToEmit.append(c.str());
647 } else if (c.front() == '#') {
648
649 ExplicitCommentToEmit.append("\t");
650 ExplicitCommentToEmit.append(MAI->getCommentString());
651 ExplicitCommentToEmit.append(c.substr(1).str());
652 } else
653 assert(false && "Unexpected Assembly Comment");
654 // full line comments immediately output
655 if (c.back() == '\n')
656 emitExplicitComments();
657}
658
659void MCAsmStreamer::emitExplicitComments() {
660 StringRef Comments = ExplicitCommentToEmit;
661 if (!Comments.empty())
662 OS << Comments;
663 ExplicitCommentToEmit.clear();
664}
665
666void MCAsmStreamer::switchSection(MCSection *Section, uint32_t Subsection) {
667 MCSectionSubPair Cur = getCurrentSection();
668 if (!EmittedSectionDirective ||
669 MCSectionSubPair(Section, Subsection) != Cur) {
670 EmittedSectionDirective = true;
671 if (MCTargetStreamer *TS = getTargetStreamer()) {
672 TS->changeSection(Cur.first, Section, Subsection, OS);
673 } else {
674 MAI->printSwitchToSection(*Section, Subsection,
675 getContext().getTargetTriple(), OS);
676 }
677 }
678 MCStreamer::switchSection(Section, Subsection);
679}
680
681bool MCAsmStreamer::popSection() {
683 return false;
684 auto [Sec, Subsec] = getCurrentSection();
685 MAI->printSwitchToSection(*Sec, Subsec, getContext().getTargetTriple(), OS);
686 return true;
687}
688
689void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
690 StringRef Name,
691 bool KeepOriginalSym) {
692 OS << ".symver ";
693 OriginalSym->print(OS, MAI);
694 OS << ", " << Name;
695 if (!KeepOriginalSym && !Name.contains("@@@"))
696 OS << ", remove";
697 EmitEOL();
698}
699
700void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
701 MCStreamer::emitLabel(Symbol, Loc);
702 // FIXME: Fix CodeGen/AArch64/arm64ec-varargs.ll. emitLabel is followed by
703 // setVariableValue, leading to an assertion failure if setOffset(0) is
704 // called.
705 if (!Symbol->isVariable() &&
706 getContext().getObjectFileType() != MCContext::IsCOFF)
707 Symbol->setOffset(0);
708
709 Symbol->print(OS, MAI);
710 OS << MAI->getLabelSuffix();
711
712 EmitEOL();
713}
714
715void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
716 StringRef str = MCLOHIdToName(Kind);
717
718#ifndef NDEBUG
719 int NbArgs = MCLOHIdToNbArgs(Kind);
720 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
721 assert(str != "" && "Invalid LOH name");
722#endif
723
724 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
725 bool IsFirst = true;
726 for (const MCSymbol *Arg : Args) {
727 if (!IsFirst)
728 OS << ", ";
729 IsFirst = false;
730 Arg->print(OS, MAI);
731 }
732 EmitEOL();
733}
734
735void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
736 OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
737}
738
739void MCAsmStreamer::emitSubsectionsViaSymbols() {
740 OS << ".subsections_via_symbols\n";
741}
742
743void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
744 assert(!Options.empty() && "At least one option is required!");
745 OS << "\t.linker_option \"" << Options[0] << '"';
746 for (const std::string &Opt : llvm::drop_begin(Options))
747 OS << ", " << '"' << Opt << '"';
748 EmitEOL();
749}
750
751void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
753 return;
754 switch (Kind) {
755 case MCDR_DataRegion: OS << "\t.data_region"; break;
756 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
757 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
758 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
759 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
760 }
761 EmitEOL();
762}
763
765 switch (Type) {
766 case MCVM_WatchOSVersionMin: return ".watchos_version_min";
767 case MCVM_TvOSVersionMin: return ".tvos_version_min";
768 case MCVM_IOSVersionMin: return ".ios_version_min";
769 case MCVM_OSXVersionMin: return ".macosx_version_min";
770 }
771 llvm_unreachable("Invalid MC version min type");
772}
773
775 const VersionTuple &SDKVersion) {
776 if (SDKVersion.empty())
777 return;
778 OS << '\t' << "sdk_version " << SDKVersion.getMajor();
779 if (auto Minor = SDKVersion.getMinor()) {
780 OS << ", " << *Minor;
781 if (auto Subminor = SDKVersion.getSubminor()) {
782 OS << ", " << *Subminor;
783 }
784 }
785}
786
787void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
788 unsigned Minor, unsigned Update,
789 VersionTuple SDKVersion) {
790 OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
791 if (Update)
792 OS << ", " << Update;
793 EmitSDKVersionSuffix(OS, SDKVersion);
794 EmitEOL();
795}
796
798 switch (Type) {
799#define PLATFORM(platform, id, name, build_name, target, tapi_target, \
800 marketing) \
801 case MachO::PLATFORM_##platform: \
802 return #build_name;
803#include "llvm/BinaryFormat/MachO.def"
804 }
805 llvm_unreachable("Invalid Mach-O platform type");
806}
807
808void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
809 unsigned Minor, unsigned Update,
810 VersionTuple SDKVersion) {
811 const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
812 OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
813 if (Update)
814 OS << ", " << Update;
815 EmitSDKVersionSuffix(OS, SDKVersion);
816 EmitEOL();
817}
818
819void MCAsmStreamer::emitDarwinTargetVariantBuildVersion(
820 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,
821 VersionTuple SDKVersion) {
822 emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
823}
824
825void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
826 bool UseSet = MAI->usesSetToEquateSymbol();
827 if (UseSet)
828 OS << ".set ";
829 Symbol->print(OS, MAI);
830 OS << (UseSet ? ", " : " = ");
831 MAI->printExpr(OS, *Value);
832
833 EmitEOL();
835}
836
837void MCAsmStreamer::emitConditionalAssignment(MCSymbol *Symbol,
838 const MCExpr *Value) {
839 OS << ".lto_set_conditional ";
840 Symbol->print(OS, MAI);
841 OS << ", ";
842 MAI->printExpr(OS, *Value);
843 EmitEOL();
844}
845
846void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
847 OS << ".weakref ";
848 Alias->print(OS, MAI);
849 OS << ", ";
850 Symbol->print(OS, MAI);
851 EmitEOL();
852}
853
854bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
856 switch (Attribute) {
857 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
858 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
859 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
860 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
861 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
862 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
863 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
864 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
865 if (!MAI->hasDotTypeDotSizeDirective())
866 return false; // Symbol attribute not supported
867 OS << "\t.type\t";
868 Symbol->print(OS, MAI);
869 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
870 switch (Attribute) {
871 default: return false;
872 case MCSA_ELF_TypeFunction: OS << "function"; break;
873 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
874 case MCSA_ELF_TypeObject: OS << "object"; break;
875 case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
876 case MCSA_ELF_TypeCommon: OS << "common"; break;
877 case MCSA_ELF_TypeNoType: OS << "notype"; break;
878 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
879 }
880 EmitEOL();
881 return true;
882 case MCSA_Global: // .globl/.global
883 OS << MAI->getGlobalDirective();
884 break;
885 case MCSA_LGlobal: OS << "\t.lglobl\t"; break;
886 case MCSA_Hidden: OS << "\t.hidden\t"; break;
887 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
888 case MCSA_Internal: OS << "\t.internal\t"; break;
889 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
890 case MCSA_Local: OS << "\t.local\t"; break;
891 case MCSA_NoDeadStrip:
892 if (!MAI->hasNoDeadStrip())
893 return false;
894 OS << "\t.no_dead_strip\t";
895 break;
896 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
897 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
899 OS << "\t.private_extern\t";
900 break;
901 case MCSA_Protected: OS << "\t.protected\t"; break;
902 case MCSA_Reference: OS << "\t.reference\t"; break;
903 case MCSA_Extern:
904 OS << "\t.extern\t";
905 break;
906 case MCSA_Weak: OS << MAI->getWeakDirective(); break;
908 OS << "\t.weak_definition\t";
909 break;
910 // .weak_reference
911 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
912 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
913 case MCSA_Cold:
914 // Assemblers currently do not support a .cold directive.
915 case MCSA_Exported:
916 // Non-AIX assemblers currently do not support exported visibility.
917 case MCSA_OSLinkage:
918 case MCSA_XPLinkage:
919 // Only for HLASM.
920 return false;
921 case MCSA_Memtag:
922 OS << "\t.memtag\t";
923 break;
924 case MCSA_WeakAntiDep:
925 OS << "\t.weak_anti_dep\t";
926 break;
927 }
928
929 Symbol->print(OS, MAI);
930 EmitEOL();
931
932 return true;
933}
934
935void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
936 OS << ".desc" << ' ';
937 Symbol->print(OS, MAI);
938 OS << ',' << DescValue;
939 EmitEOL();
940}
941
942void MCAsmStreamer::emitSyntaxDirective(StringRef Syntax, StringRef Options) {
943 OS << "\t." << Syntax << "_syntax";
944 if (!Options.empty())
945 OS << " " << Options;
946 EmitEOL();
947}
948
949void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
950 OS << "\t.def\t";
951 Symbol->print(OS, MAI);
952 OS << ';';
953 EmitEOL();
954}
955
956void MCAsmStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
957 OS << "\t.scl\t" << StorageClass << ';';
958 EmitEOL();
959}
960
961void MCAsmStreamer::emitCOFFSymbolType(int Type) {
962 OS << "\t.type\t" << Type << ';';
963 EmitEOL();
964}
965
966void MCAsmStreamer::endCOFFSymbolDef() {
967 OS << "\t.endef";
968 EmitEOL();
969}
970
971void MCAsmStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {
972 OS << "\t.safeseh\t";
973 Symbol->print(OS, MAI);
974 EmitEOL();
975}
976
977void MCAsmStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
978 OS << "\t.symidx\t";
979 Symbol->print(OS, MAI);
980 EmitEOL();
981}
982
983void MCAsmStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {
984 OS << "\t.secidx\t";
985 Symbol->print(OS, MAI);
986 EmitEOL();
987}
988
989void MCAsmStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
990 OS << "\t.secrel32\t";
991 Symbol->print(OS, MAI);
992 if (Offset != 0)
993 OS << '+' << Offset;
994 EmitEOL();
995}
996
997void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
998 OS << "\t.rva\t";
999 Symbol->print(OS, MAI);
1000 if (Offset > 0)
1001 OS << '+' << Offset;
1002 else if (Offset < 0)
1003 OS << '-' << -Offset;
1004 EmitEOL();
1005}
1006
1007void MCAsmStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
1008 OS << "\t.secnum\t";
1009 Symbol->print(OS, MAI);
1010 EmitEOL();
1011}
1012
1013void MCAsmStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
1014 OS << "\t.secoffset\t";
1015 Symbol->print(OS, MAI);
1016 EmitEOL();
1017}
1018
1019// We need an XCOFF-specific version of this directive as the AIX syntax
1020// requires a QualName argument identifying the csect name and storage mapping
1021// class to appear before the alignment if we are specifying it.
1022void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
1023 uint64_t Size,
1024 MCSymbol *CsectSym,
1025 Align Alignment) {
1027 "We only support writing log base-2 alignment format with XCOFF.");
1028
1029 OS << "\t.lcomm\t";
1030 LabelSym->print(OS, MAI);
1031 OS << ',' << Size << ',';
1032 CsectSym->print(OS, MAI);
1033 OS << ',' << Log2(Alignment);
1034
1035 EmitEOL();
1036
1037 // Print symbol's rename (original name contains invalid character(s)) if
1038 // there is one.
1039 auto *XSym = static_cast<MCSymbolXCOFF *>(CsectSym);
1040 if (XSym->hasRename())
1041 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
1042}
1043
1044void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
1045 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
1046 auto &Sym = static_cast<MCSymbolXCOFF &>(*Symbol);
1047 switch (Linkage) {
1048 case MCSA_Global:
1049 OS << MAI->getGlobalDirective();
1050 break;
1051 case MCSA_Weak:
1052 OS << MAI->getWeakDirective();
1053 break;
1054 case MCSA_Extern:
1055 OS << "\t.extern\t";
1056 break;
1057 case MCSA_LGlobal:
1058 OS << "\t.lglobl\t";
1059 break;
1060 default:
1061 report_fatal_error("unhandled linkage type");
1062 }
1063
1064 Symbol->print(OS, MAI);
1065
1066 switch (Visibility) {
1067 case MCSA_Invalid:
1068 // Nothing to do.
1069 break;
1070 case MCSA_Hidden:
1071 OS << ",hidden";
1072 break;
1073 case MCSA_Protected:
1074 OS << ",protected";
1075 break;
1076 case MCSA_Exported:
1077 OS << ",exported";
1078 break;
1079 default:
1080 report_fatal_error("unexpected value for Visibility type");
1081 }
1082 EmitEOL();
1083
1084 // Print symbol's rename (original name contains invalid character(s)) if
1085 // there is one.
1086 if (Sym.hasRename())
1087 emitXCOFFRenameDirective(&Sym, Sym.getSymbolTableName());
1088}
1089
1090void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
1091 StringRef Rename) {
1092 OS << "\t.rename\t";
1093 Name->print(OS, MAI);
1094 const char DQ = '"';
1095 OS << ',' << DQ;
1096 for (char C : Rename) {
1097 // To escape a double quote character, the character should be doubled.
1098 if (C == DQ)
1099 OS << DQ;
1100 OS << C;
1101 }
1102 OS << DQ;
1103 EmitEOL();
1104}
1105
1106void MCAsmStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
1107 OS << "\t.ref ";
1108 Symbol->print(OS, MAI);
1109 EmitEOL();
1110}
1111
1112void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
1113 const MCSymbol *Trap,
1114 unsigned Lang,
1115 unsigned Reason,
1116 unsigned FunctionSize,
1117 bool hasDebug) {
1118 OS << "\t.except\t";
1119 Symbol->print(OS, MAI);
1120 OS << ", " << Lang << ", " << Reason;
1121 EmitEOL();
1122}
1123
1124void MCAsmStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
1125 const char InfoDirective[] = "\t.info ";
1126 const char *Separator = ", ";
1127 constexpr int WordSize = sizeof(uint32_t);
1128
1129 // Start by emitting the .info pseudo-op and C_INFO symbol name.
1130 OS << InfoDirective;
1131 PrintQuotedString(Name, OS);
1132 OS << Separator;
1133
1134 size_t MetadataSize = Metadata.size();
1135
1136 // Emit the 4-byte length of the metadata.
1137 OS << format_hex(MetadataSize, 10) << Separator;
1138
1139 // Nothing left to do if there's no metadata.
1140 if (MetadataSize == 0) {
1141 EmitEOL();
1142 return;
1143 }
1144
1145 // Metadata needs to be padded out to an even word size when generating
1146 // assembly because the .info pseudo-op can only generate words of data. We
1147 // apply the same restriction to the object case for consistency, however the
1148 // linker doesn't require padding, so it will only save bytes specified by the
1149 // length and discard any padding.
1150 uint32_t PaddedSize = alignTo(MetadataSize, WordSize);
1151 uint32_t PaddingSize = PaddedSize - MetadataSize;
1152
1153 // Write out the payload a word at a time.
1154 //
1155 // The assembler has a limit on the number of operands in an expression,
1156 // so we need multiple .info pseudo-ops. We choose a small number of words
1157 // per pseudo-op to keep the assembly readable.
1158 constexpr int WordsPerDirective = 5;
1159 // Force emitting a new directive to keep the first directive purely about the
1160 // name and size of the note.
1161 int WordsBeforeNextDirective = 0;
1162 auto PrintWord = [&](const uint8_t *WordPtr) {
1163 if (WordsBeforeNextDirective-- == 0) {
1164 EmitEOL();
1165 OS << InfoDirective;
1166 WordsBeforeNextDirective = WordsPerDirective;
1167 }
1168 OS << Separator;
1169 uint32_t Word = llvm::support::endian::read32be(WordPtr);
1170 OS << format_hex(Word, 10);
1171 };
1172
1173 size_t Index = 0;
1174 for (; Index + WordSize <= MetadataSize; Index += WordSize)
1175 PrintWord(reinterpret_cast<const uint8_t *>(Metadata.data()) + Index);
1176
1177 // If there is padding, then we have at least one byte of payload left
1178 // to emit.
1179 if (PaddingSize) {
1180 assert(PaddedSize - Index == WordSize);
1181 std::array<uint8_t, WordSize> LastWord = {0};
1182 ::memcpy(LastWord.data(), Metadata.data() + Index, MetadataSize - Index);
1183 PrintWord(LastWord.data());
1184 }
1185 EmitEOL();
1186}
1187
1188void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
1190 OS << "\t.size\t";
1191 Symbol->print(OS, MAI);
1192 OS << ", ";
1193 MAI->printExpr(OS, *Value);
1194 EmitEOL();
1195}
1196
1197void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1198 Align ByteAlignment) {
1199 OS << "\t.comm\t";
1200 Symbol->print(OS, MAI);
1201 OS << ',' << Size;
1202
1204 OS << ',' << ByteAlignment.value();
1205 else
1206 OS << ',' << Log2(ByteAlignment);
1207 EmitEOL();
1208
1209 // Print symbol's rename (original name contains invalid character(s)) if
1210 // there is one.
1211 if (getContext().isXCOFF()) {
1212 auto *XSym = static_cast<MCSymbolXCOFF *>(Symbol);
1213 if (XSym && XSym->hasRename())
1214 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
1215 }
1216}
1217
1218void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1219 Align ByteAlign) {
1220 OS << "\t.lcomm\t";
1221 Symbol->print(OS, MAI);
1222 OS << ',' << Size;
1223
1224 if (ByteAlign > 1) {
1225 switch (MAI->getLCOMMDirectiveAlignmentType()) {
1226 case LCOMM::NoAlignment:
1227 llvm_unreachable("alignment not supported on .lcomm!");
1229 OS << ',' << ByteAlign.value();
1230 break;
1232 OS << ',' << Log2(ByteAlign);
1233 break;
1234 }
1235 }
1236 EmitEOL();
1237}
1238
1239void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
1240 uint64_t Size, Align ByteAlignment,
1241 SMLoc Loc) {
1242 if (Symbol)
1243 Symbol->setFragment(&Section->getDummyFragment());
1244
1245 // Note: a .zerofill directive does not switch sections.
1246 OS << ".zerofill ";
1247
1248 assert(getContext().getObjectFileType() == MCContext::IsMachO &&
1249 ".zerofill is a Mach-O specific directive");
1250 // This is a mach-o specific directive.
1251
1252 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
1253 OS << MOSection->getSegmentName() << "," << MOSection->getName();
1254
1255 if (Symbol) {
1256 OS << ',';
1257 Symbol->print(OS, MAI);
1258 OS << ',' << Size;
1259 OS << ',' << Log2(ByteAlignment);
1260 }
1261 EmitEOL();
1262}
1263
1264// .tbss sym, size, align
1265// This depends that the symbol has already been mangled from the original,
1266// e.g. _a.
1267void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1268 uint64_t Size, Align ByteAlignment) {
1269 Symbol->setFragment(&Section->getDummyFragment());
1270
1271 // Instead of using the Section we'll just use the shortcut.
1272
1273 assert(getContext().getObjectFileType() == MCContext::IsMachO &&
1274 ".zerofill is a Mach-O specific directive");
1275 // This is a mach-o specific directive and section.
1276
1277 OS << ".tbss ";
1278 Symbol->print(OS, MAI);
1279 OS << ", " << Size;
1280
1281 // Output align if we have it. We default to 1 so don't bother printing
1282 // that.
1283 if (ByteAlignment > 1)
1284 OS << ", " << Log2(ByteAlignment);
1285
1286 EmitEOL();
1287}
1288
1289static inline bool isPrintableString(StringRef Data) {
1290 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1291 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1292 if (!isPrint(C))
1293 return false;
1294 }
1295 return isPrint(Data.back()) || Data.back() == 0;
1296}
1297
1298static inline char toOctal(int X) { return (X&7)+'0'; }
1299
1302 assert(!Data.empty() && "Cannot generate an empty list.");
1303 const auto printCharacterInOctal = [&OS](unsigned char C) {
1304 OS << '0';
1305 OS << toOctal(C >> 6);
1306 OS << toOctal(C >> 3);
1307 OS << toOctal(C >> 0);
1308 };
1309 const auto printOneCharacterFor = [printCharacterInOctal](
1310 auto printOnePrintingCharacter) {
1311 return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
1312 if (isPrint(C)) {
1313 printOnePrintingCharacter(static_cast<char>(C));
1314 return;
1315 }
1316 printCharacterInOctal(C);
1317 };
1318 };
1319 const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1320 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1321 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1322 printOneCharacter(C);
1323 OS << ',';
1324 }
1325 printOneCharacter(*(EndPtr - 1));
1326 };
1327 switch (ACLS) {
1329 printCharacterList(printCharacterInOctal);
1330 return;
1332 printCharacterList(printOneCharacterFor([&OS](char C) {
1333 const char AsmCharLitBuf[2] = {'\'', C};
1334 OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1335 }));
1336 return;
1337 }
1338 llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
1339}
1340
1341void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {
1342 OS << '"';
1343
1344 if (MAI->isAIX()) {
1345 for (unsigned char C : Data) {
1346 if (C == '"')
1347 OS << "\"\"";
1348 else
1349 OS << (char)C;
1350 }
1351 } else {
1352 for (unsigned char C : Data) {
1353 if (C == '"' || C == '\\') {
1354 OS << '\\' << (char)C;
1355 continue;
1356 }
1357
1358 if (isPrint(C)) {
1359 OS << (char)C;
1360 continue;
1361 }
1362
1363 switch (C) {
1364 case '\b':
1365 OS << "\\b";
1366 break;
1367 case '\f':
1368 OS << "\\f";
1369 break;
1370 case '\n':
1371 OS << "\\n";
1372 break;
1373 case '\r':
1374 OS << "\\r";
1375 break;
1376 case '\t':
1377 OS << "\\t";
1378 break;
1379 default:
1380 OS << '\\';
1381 OS << toOctal(C >> 6);
1382 OS << toOctal(C >> 3);
1383 OS << toOctal(C >> 0);
1384 break;
1385 }
1386 }
1387 }
1388
1389 OS << '"';
1390}
1391
1392void MCAsmStreamer::emitBytes(StringRef Data) {
1393 assert(getCurrentSectionOnly() &&
1394 "Cannot emit contents before setting section!");
1395 if (Data.empty()) return;
1396
1397 const auto emitAsString = [this](StringRef Data) {
1398 if (MAI->isAIX()) {
1399 if (isPrintableString(Data)) {
1400 // For target with DoubleQuoteString constants, .string and .byte are
1401 // used as replacement of .asciz and .ascii.
1402 if (Data.back() == 0) {
1403 OS << "\t.string\t";
1404 Data = Data.substr(0, Data.size() - 1);
1405 } else {
1406 OS << "\t.byte\t";
1407 }
1408 PrintQuotedString(Data, OS);
1409 } else {
1410 OS << "\t.byte\t";
1412 }
1413 EmitEOL();
1414 return true;
1415 }
1416
1417 // If the data ends with 0 and the target supports .asciz, use it, otherwise
1418 // use .ascii or a byte-list directive
1419 if (MAI->getAscizDirective() && Data.back() == 0) {
1420 OS << MAI->getAscizDirective();
1421 Data = Data.substr(0, Data.size() - 1);
1422 } else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
1423 OS << MAI->getAsciiDirective();
1424 } else {
1425 return false;
1426 }
1427
1428 PrintQuotedString(Data, OS);
1429 EmitEOL();
1430 return true;
1431 };
1432
1433 if (Data.size() != 1 && emitAsString(Data))
1434 return;
1435
1436 // Only single byte is provided or no ascii, asciz, or byte-list directives
1437 // are applicable. Emit as vector of individual 8bits data elements.
1438 if (MCTargetStreamer *TS = getTargetStreamer()) {
1439 TS->emitRawBytes(Data);
1440 return;
1441 }
1442 const char *Directive = MAI->getData8bitsDirective();
1443 for (const unsigned char C : Data.bytes()) {
1444 OS << Directive << (unsigned)C;
1445 EmitEOL();
1446 }
1447}
1448
1449void MCAsmStreamer::emitBinaryData(StringRef Data) {
1450 // This is binary data. Print it in a grid of hex bytes for readability.
1451 const size_t Cols = 4;
1452 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
1453 size_t J = I, EJ = std::min(I + Cols, Data.size());
1454 assert(EJ > 0);
1455 OS << MAI->getData8bitsDirective();
1456 for (; J < EJ - 1; ++J)
1457 OS << format("0x%02x", uint8_t(Data[J])) << ", ";
1458 OS << format("0x%02x", uint8_t(Data[J]));
1459 EmitEOL();
1460 }
1461}
1462
1463void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1465}
1466
1467void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
1468 emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
1469}
1470
1471void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
1472 unsigned Size) {
1473 emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
1474}
1475
1476void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1477 SMLoc Loc) {
1478 assert(Size <= 8 && "Invalid size");
1479 assert(getCurrentSectionOnly() &&
1480 "Cannot emit contents before setting section!");
1481 const char *Directive = nullptr;
1482 switch (Size) {
1483 default: break;
1484 case 1: Directive = MAI->getData8bitsDirective(); break;
1485 case 2: Directive = MAI->getData16bitsDirective(); break;
1486 case 4: Directive = MAI->getData32bitsDirective(); break;
1487 case 8: Directive = MAI->getData64bitsDirective(); break;
1488 }
1489
1490 if (!Directive) {
1491 int64_t IntValue;
1492 if (!Value->evaluateAsAbsolute(IntValue))
1493 report_fatal_error("Don't know how to emit this value.");
1494
1495 // We couldn't handle the requested integer size so we fallback by breaking
1496 // the request down into several, smaller, integers.
1497 // Since sizes greater or equal to "Size" are invalid, we use the greatest
1498 // power of 2 that is less than "Size" as our largest piece of granularity.
1499 bool IsLittleEndian = MAI->isLittleEndian();
1500 for (unsigned Emitted = 0; Emitted != Size;) {
1501 unsigned Remaining = Size - Emitted;
1502 // The size of our partial emission must be a power of two less than
1503 // Size.
1504 unsigned EmissionSize = llvm::bit_floor(std::min(Remaining, Size - 1));
1505 // Calculate the byte offset of our partial emission taking into account
1506 // the endianness of the target.
1507 unsigned ByteOffset =
1508 IsLittleEndian ? Emitted : (Remaining - EmissionSize);
1509 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
1510 // We truncate our partial emission to fit within the bounds of the
1511 // emission domain. This produces nicer output and silences potential
1512 // truncation warnings when round tripping through another assembler.
1513 uint64_t Shift = 64 - EmissionSize * 8;
1514 assert(Shift < static_cast<uint64_t>(
1515 std::numeric_limits<unsigned long long>::digits) &&
1516 "undefined behavior");
1517 ValueToEmit &= ~0ULL >> Shift;
1518 emitIntValue(ValueToEmit, EmissionSize);
1519 Emitted += EmissionSize;
1520 }
1521 return;
1522 }
1523
1524 assert(Directive && "Invalid size for machine code value!");
1525 OS << Directive;
1526 if (MCTargetStreamer *TS = getTargetStreamer()) {
1527 TS->emitValue(Value);
1528 } else {
1529 MAI->printExpr(OS, *Value);
1530 EmitEOL();
1531 }
1532}
1533
1534void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
1535 int64_t IntValue;
1536 if (Value->evaluateAsAbsolute(IntValue)) {
1537 emitULEB128IntValue(IntValue);
1538 return;
1539 }
1540 OS << "\t.uleb128 ";
1541 MAI->printExpr(OS, *Value);
1542 EmitEOL();
1543}
1544
1545void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
1546 int64_t IntValue;
1547 if (Value->evaluateAsAbsolute(IntValue)) {
1548 emitSLEB128IntValue(IntValue);
1549 return;
1550 }
1551 OS << "\t.sleb128 ";
1552 MAI->printExpr(OS, *Value);
1553 EmitEOL();
1554}
1555
1556void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1557 SMLoc Loc) {
1558 int64_t IntNumBytes;
1559 const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
1560 if (IsAbsolute && IntNumBytes == 0)
1561 return;
1562
1563 if (const char *ZeroDirective = MAI->getZeroDirective()) {
1564 if (!MAI->isAIX() || FillValue == 0) {
1565 // FIXME: Emit location directives
1566 OS << ZeroDirective;
1567 MAI->printExpr(OS, NumBytes);
1568 if (FillValue != 0)
1569 OS << ',' << (int)FillValue;
1570 EmitEOL();
1571 } else {
1572 if (!IsAbsolute)
1574 "Cannot emit non-absolute expression lengths of fill.");
1575 for (int i = 0; i < IntNumBytes; ++i) {
1576 OS << MAI->getData8bitsDirective() << (int)FillValue;
1577 EmitEOL();
1578 }
1579 }
1580 return;
1581 }
1582
1583 MCStreamer::emitFill(NumBytes, FillValue);
1584}
1585
1586void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1587 int64_t Expr, SMLoc Loc) {
1588 // FIXME: Emit location directives
1589 OS << "\t.fill\t";
1590 MAI->printExpr(OS, NumValues);
1591 OS << ", " << Size << ", 0x";
1592 OS.write_hex(truncateToSize(Expr, 4));
1593 EmitEOL();
1594}
1595
1596void MCAsmStreamer::emitAlignmentDirective(uint64_t ByteAlignment,
1597 std::optional<int64_t> Value,
1598 unsigned ValueSize,
1599 unsigned MaxBytesToEmit) {
1600 if (MAI->isAIX()) {
1601 if (!isPowerOf2_64(ByteAlignment))
1602 report_fatal_error("Only power-of-two alignments are supported "
1603 "with .align.");
1604 OS << "\t.align\t";
1605 OS << Log2_64(ByteAlignment);
1606 EmitEOL();
1607 return;
1608 }
1609
1610 // Some assemblers don't support non-power of two alignments, so we always
1611 // emit alignments as a power of two if possible.
1612 if (isPowerOf2_64(ByteAlignment)) {
1613 switch (ValueSize) {
1614 default:
1615 llvm_unreachable("Invalid size for machine code value!");
1616 case 1:
1617 OS << "\t.p2align\t";
1618 break;
1619 case 2:
1620 OS << ".p2alignw ";
1621 break;
1622 case 4:
1623 OS << ".p2alignl ";
1624 break;
1625 case 8:
1626 llvm_unreachable("Unsupported alignment size!");
1627 }
1628
1629 OS << Log2_64(ByteAlignment);
1630
1631 if (Value.has_value() || MaxBytesToEmit) {
1632 if (Value.has_value()) {
1633 OS << ", 0x";
1634 OS.write_hex(truncateToSize(*Value, ValueSize));
1635 } else {
1636 OS << ", ";
1637 }
1638
1639 if (MaxBytesToEmit)
1640 OS << ", " << MaxBytesToEmit;
1641 }
1642 EmitEOL();
1643 return;
1644 }
1645
1646 // Non-power of two alignment. This is not widely supported by assemblers.
1647 // FIXME: Parameterize this based on MAI.
1648 switch (ValueSize) {
1649 default: llvm_unreachable("Invalid size for machine code value!");
1650 case 1: OS << ".balign"; break;
1651 case 2: OS << ".balignw"; break;
1652 case 4: OS << ".balignl"; break;
1653 case 8: llvm_unreachable("Unsupported alignment size!");
1654 }
1655
1656 OS << ' ' << ByteAlignment;
1657 if (Value.has_value())
1658 OS << ", " << truncateToSize(*Value, ValueSize);
1659 else if (MaxBytesToEmit)
1660 OS << ", ";
1661 if (MaxBytesToEmit)
1662 OS << ", " << MaxBytesToEmit;
1663 EmitEOL();
1664}
1665
1666void MCAsmStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
1667 uint8_t FillLen,
1668 unsigned MaxBytesToEmit) {
1669 emitAlignmentDirective(Alignment.value(), Fill, FillLen, MaxBytesToEmit);
1670}
1671
1672void MCAsmStreamer::emitCodeAlignment(Align Alignment,
1673 const MCSubtargetInfo &STI,
1674 unsigned MaxBytesToEmit) {
1675 // Emit with a text fill value.
1676 if (MAI->getTextAlignFillValue())
1677 emitAlignmentDirective(Alignment.value(), MAI->getTextAlignFillValue(), 1,
1678 MaxBytesToEmit);
1679 else
1680 emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
1681}
1682
1683void MCAsmStreamer::emitPrefAlign(Align Alignment, const MCSymbol &End,
1684 bool EmitNops, uint8_t Fill,
1685 const MCSubtargetInfo &) {
1686 OS << "\t.prefalign\t" << Log2(Alignment) << ", ";
1687 End.print(OS, MAI);
1688 if (EmitNops)
1689 OS << ", nop";
1690 else
1691 OS << ", " << static_cast<unsigned>(Fill);
1692 EmitEOL();
1693}
1694
1695void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1696 unsigned char Value,
1697 SMLoc Loc) {
1698 // FIXME: Verify that Offset is associated with the current section.
1699 OS << ".org ";
1700 MAI->printExpr(OS, *Offset);
1701 OS << ", " << (unsigned)Value;
1702 EmitEOL();
1703}
1704
1705void MCAsmStreamer::emitFileDirective(StringRef Filename) {
1707 OS << "\t.file\t";
1708 PrintQuotedString(Filename, OS);
1709 EmitEOL();
1710}
1711
1712void MCAsmStreamer::emitFileDirective(StringRef Filename,
1713 StringRef CompilerVersion,
1714 StringRef TimeStamp,
1715 StringRef Description) {
1716 assert(MAI->isAIX());
1717 OS << "\t.file\t";
1718 PrintQuotedString(Filename, OS);
1719 bool useTimeStamp = !TimeStamp.empty();
1720 bool useCompilerVersion = !CompilerVersion.empty();
1721 bool useDescription = !Description.empty();
1722 if (useTimeStamp || useCompilerVersion || useDescription) {
1723 OS << ",";
1724 if (useTimeStamp)
1725 PrintQuotedString(TimeStamp, OS);
1726 if (useCompilerVersion || useDescription) {
1727 OS << ",";
1728 if (useCompilerVersion)
1729 PrintQuotedString(CompilerVersion, OS);
1730 if (useDescription) {
1731 OS << ",";
1732 PrintQuotedString(Description, OS);
1733 }
1734 }
1735 }
1736 EmitEOL();
1737}
1738
1739void MCAsmStreamer::printDwarfFileDirective(
1740 unsigned FileNo, StringRef Directory, StringRef Filename,
1741 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1742 bool UseDwarfDirectory, raw_svector_ostream &OS) const {
1743 SmallString<128> FullPathName;
1744
1745 if (!UseDwarfDirectory && !Directory.empty()) {
1747 Directory = "";
1748 else {
1749 FullPathName = Directory;
1750 sys::path::append(FullPathName, Filename);
1751 Directory = "";
1752 Filename = FullPathName;
1753 }
1754 }
1755
1756 OS << "\t.file\t" << FileNo << ' ';
1757 if (!Directory.empty()) {
1758 PrintQuotedString(Directory, OS);
1759 OS << ' ';
1760 }
1761 PrintQuotedString(Filename, OS);
1762 if (Checksum)
1763 OS << " md5 0x" << Checksum->digest();
1764 if (Source) {
1765 OS << " source ";
1766 PrintQuotedString(*Source, OS);
1767 }
1768}
1769
1770Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1771 unsigned FileNo, StringRef Directory, StringRef Filename,
1772 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1773 unsigned CUID) {
1774 assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
1775
1776 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1777 unsigned NumFiles = Table.getMCDwarfFiles().size();
1778 Expected<unsigned> FileNoOrErr =
1779 Table.tryGetFile(Directory, Filename, Checksum, Source,
1780 getContext().getDwarfVersion(), FileNo);
1781 if (!FileNoOrErr)
1782 return FileNoOrErr.takeError();
1783 FileNo = FileNoOrErr.get();
1784
1785 // Return early if this file is already emitted before or if target doesn't
1786 // support .file directive.
1787 if (NumFiles == Table.getMCDwarfFiles().size() || MAI->isAIX())
1788 return FileNo;
1789
1790 SmallString<128> Str;
1791 raw_svector_ostream OS1(Str);
1792 printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1793 UseDwarfDirectory, OS1);
1794
1795 if (MCTargetStreamer *TS = getTargetStreamer())
1796 TS->emitDwarfFileDirective(OS1.str());
1797 else
1798 emitRawText(OS1.str());
1799
1800 return FileNo;
1801}
1802
1803void MCAsmStreamer::emitDwarfFile0Directive(
1804 StringRef Directory, StringRef Filename,
1805 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1806 unsigned CUID) {
1807 assert(CUID == 0);
1808 // .file 0 is new for DWARF v5.
1809 if (getContext().getDwarfVersion() < 5)
1810 return;
1811 // Inform MCDwarf about the root file.
1812 getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1813 Source);
1814
1815 // Target doesn't support .loc/.file directives, return early.
1816 if (MAI->isAIX())
1817 return;
1818
1819 SmallString<128> Str;
1820 raw_svector_ostream OS1(Str);
1821 printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1822 UseDwarfDirectory, OS1);
1823
1824 if (MCTargetStreamer *TS = getTargetStreamer())
1825 TS->emitDwarfFileDirective(OS1.str());
1826 else
1827 emitRawText(OS1.str());
1828}
1829
1830/// Helper to emit common .loc directive flags, isa, and discriminator.
1831void MCAsmStreamer::emitDwarfLocDirectiveFlags(unsigned Flags, unsigned Isa,
1832 unsigned Discriminator) {
1834 return;
1835
1836 if (Flags & DWARF2_FLAG_BASIC_BLOCK)
1837 OS << " basic_block";
1838 if (Flags & DWARF2_FLAG_PROLOGUE_END)
1839 OS << " prologue_end";
1840 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
1841 OS << " epilogue_begin";
1842
1843 const unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1844 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
1845 OS << " is_stmt ";
1846 OS << ((Flags & DWARF2_FLAG_IS_STMT) ? "1" : "0");
1847 }
1848
1849 if (Isa)
1850 OS << " isa " << Isa;
1851 if (Discriminator)
1852 OS << " discriminator " << Discriminator;
1853}
1854
1855/// Helper to emit the common suffix of .loc directives.
1856void MCAsmStreamer::emitDwarfLocDirectiveSuffix(unsigned FileNo, unsigned Line,
1857 unsigned Column, unsigned Flags,
1858 unsigned Isa,
1859 unsigned Discriminator,
1860 StringRef FileName,
1861 StringRef Comment) {
1862 // Emit flags, isa, and discriminator.
1863 emitDwarfLocDirectiveFlags(Flags, Isa, Discriminator);
1864
1865 // Emit verbose comment if enabled.
1866 if (IsVerboseAsm) {
1867 OS.PadToColumn(MAI->getCommentColumn());
1868 OS << MAI->getCommentString() << ' ';
1869 if (Comment.empty())
1870 OS << FileName << ':' << Line << ':' << Column;
1871 else
1872 OS << Comment;
1873 }
1874
1875 // Emit end of line and update the baseclass state.
1876 EmitEOL();
1877 MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1878 Discriminator, FileName, Comment);
1879}
1880
1881void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
1882 unsigned Column, unsigned Flags,
1883 unsigned Isa, unsigned Discriminator,
1884 StringRef FileName,
1885 StringRef Comment) {
1886 // If target doesn't support .loc/.file directive, we need to record the lines
1887 // same way like we do in object mode.
1888 if (MAI->isAIX()) {
1889 // In case we see two .loc directives in a row, make sure the
1890 // first one gets a line entry.
1891 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1892 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1893 Discriminator, FileName, Comment);
1894 return;
1895 }
1896
1897 // Emit the basic .loc directive.
1898 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1899
1900 // Emit common suffix (flags, comment, EOL, parent call).
1901 emitDwarfLocDirectiveSuffix(FileNo, Line, Column, Flags, Isa, Discriminator,
1902 FileName, Comment);
1903}
1904
1905/// This is same as emitDwarfLocDirective, except also emits inlined function
1906/// and inlined callsite information.
1907void MCAsmStreamer::emitDwarfLocDirectiveWithInlinedAt(
1908 unsigned FileNo, unsigned Line, unsigned Column, unsigned FileIA,
1909 unsigned LineIA, unsigned ColIA, const MCSymbol *Sym, unsigned Flags,
1910 unsigned Isa, unsigned Discriminator, StringRef FileName,
1911 StringRef Comment) {
1912 // Emit the basic .loc directive with NVPTX-specific extensions.
1913 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1914 OS << ", function_name " << *Sym;
1915 OS << ", inlined_at " << FileIA << " " << LineIA << " " << ColIA;
1916
1917 // Emit common suffix (flags, comment, EOL, parent call).
1918 emitDwarfLocDirectiveSuffix(FileNo, Line, Column, Flags, Isa, Discriminator,
1919 FileName, Comment);
1920}
1921
1922void MCAsmStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) {
1924 OS << ".loc_label\t" << Name;
1925 EmitEOL();
1926}
1927
1928MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1929 // Always use the zeroth line table, since asm syntax only supports one line
1930 // table for now.
1932}
1933
1934bool MCAsmStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
1935 ArrayRef<uint8_t> Checksum,
1936 unsigned ChecksumKind) {
1937 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1938 ChecksumKind))
1939 return false;
1940
1941 OS << "\t.cv_file\t" << FileNo << ' ';
1942 PrintQuotedString(Filename, OS);
1943
1944 if (!ChecksumKind) {
1945 EmitEOL();
1946 return true;
1947 }
1948
1949 OS << ' ';
1950 PrintQuotedString(toHex(Checksum), OS);
1951 OS << ' ' << ChecksumKind;
1952
1953 EmitEOL();
1954 return true;
1955}
1956
1957bool MCAsmStreamer::emitCVFuncIdDirective(unsigned FuncId) {
1958 OS << "\t.cv_func_id " << FuncId << '\n';
1959 return MCStreamer::emitCVFuncIdDirective(FuncId);
1960}
1961
1962bool MCAsmStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,
1963 unsigned IAFunc,
1964 unsigned IAFile,
1965 unsigned IALine, unsigned IACol,
1966 SMLoc Loc) {
1967 OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1968 << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1970 IALine, IACol, Loc);
1971}
1972
1973void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1974 unsigned Line, unsigned Column,
1975 bool PrologueEnd, bool IsStmt,
1976 StringRef FileName, SMLoc Loc) {
1977 // Validate the directive.
1978 if (!checkCVLocSection(FunctionId, Loc))
1979 return;
1980
1981 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1982 << Column;
1983 if (PrologueEnd)
1984 OS << " prologue_end";
1985
1986 if (IsStmt)
1987 OS << " is_stmt 1";
1988
1989 if (IsVerboseAsm) {
1990 OS.PadToColumn(MAI->getCommentColumn());
1991 OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1992 << Column;
1993 }
1994 EmitEOL();
1995}
1996
1997void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
1998 const MCSymbol *FnStart,
1999 const MCSymbol *FnEnd) {
2000 OS << "\t.cv_linetable\t" << FunctionId << ", ";
2001 FnStart->print(OS, MAI);
2002 OS << ", ";
2003 FnEnd->print(OS, MAI);
2004 EmitEOL();
2005 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
2006}
2007
2008void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
2009 unsigned SourceFileId,
2010 unsigned SourceLineNum,
2011 const MCSymbol *FnStartSym,
2012 const MCSymbol *FnEndSym) {
2013 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
2014 << ' ' << SourceLineNum << ' ';
2015 FnStartSym->print(OS, MAI);
2016 OS << ' ';
2017 FnEndSym->print(OS, MAI);
2018 EmitEOL();
2020 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
2021}
2022
2023void MCAsmStreamer::PrintCVDefRangePrefix(
2024 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
2025 OS << "\t.cv_def_range\t";
2026 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
2027 OS << ' ';
2028 Range.first->print(OS, MAI);
2029 OS << ' ';
2030 Range.second->print(OS, MAI);
2031 }
2032}
2033
2034void MCAsmStreamer::emitCVDefRangeDirective(
2035 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2037 PrintCVDefRangePrefix(Ranges);
2038 OS << ", reg_rel, ";
2039 OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
2040 << DRHdr.BasePointerOffset;
2041 EmitEOL();
2042}
2043
2044void MCAsmStreamer::emitCVDefRangeDirective(
2045 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2047 PrintCVDefRangePrefix(Ranges);
2048 OS << ", subfield_reg, ";
2049 OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
2050 EmitEOL();
2051}
2052
2053void MCAsmStreamer::emitCVDefRangeDirective(
2054 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2056 PrintCVDefRangePrefix(Ranges);
2057 OS << ", reg, ";
2058 OS << DRHdr.Register;
2059 EmitEOL();
2060}
2061
2062void MCAsmStreamer::emitCVDefRangeDirective(
2063 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2065 PrintCVDefRangePrefix(Ranges);
2066 OS << ", frame_ptr_rel, ";
2067 OS << DRHdr.Offset;
2068 EmitEOL();
2069}
2070
2071void MCAsmStreamer::emitCVDefRangeDirective(
2072 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2074 PrintCVDefRangePrefix(Ranges);
2075 OS << ", reg_rel_indir, ";
2076 OS << DRHdr.Register << ", " << DRHdr.Flags << ", " << DRHdr.BasePointerOffset
2077 << ", " << DRHdr.OffsetInUdt;
2078 EmitEOL();
2079}
2080
2081void MCAsmStreamer::emitCVStringTableDirective() {
2082 OS << "\t.cv_stringtable";
2083 EmitEOL();
2084}
2085
2086void MCAsmStreamer::emitCVFileChecksumsDirective() {
2087 OS << "\t.cv_filechecksums";
2088 EmitEOL();
2089}
2090
2091void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
2092 OS << "\t.cv_filechecksumoffset\t" << FileNo;
2093 EmitEOL();
2094}
2095
2096void MCAsmStreamer::emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
2097 OS << "\t.cv_fpo_data\t";
2098 ProcSym->print(OS, MAI);
2099 EmitEOL();
2100}
2101
2102void MCAsmStreamer::emitIdent(StringRef IdentString) {
2103 assert(MAI->hasIdentDirective() && ".ident directive not supported");
2104 OS << "\t.ident\t";
2105 PrintQuotedString(IdentString, OS);
2106 EmitEOL();
2107}
2108
2109void MCAsmStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
2111 OS << "\t.cfi_sections ";
2112 bool C = false;
2113 if (EH) {
2114 OS << ".eh_frame";
2115 C = true;
2116 }
2117 if (Debug) {
2118 if (C)
2119 OS << ", ";
2120 OS << ".debug_frame";
2121 C = true;
2122 }
2123 if (SFrame) {
2124 if (C)
2125 OS << ", ";
2126 OS << ".sframe";
2127 }
2128
2129 EmitEOL();
2130}
2131
2132void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
2133 OS << "\t.cfi_startproc";
2134 if (Frame.IsSimple)
2135 OS << " simple";
2136 EmitEOL();
2137}
2138
2139void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
2141 OS << "\t.cfi_endproc";
2142 EmitEOL();
2143}
2144
2145void MCAsmStreamer::EmitRegisterName(int64_t Register) {
2146 if (!MAI->useDwarfRegNumForCFI()) {
2147 // User .cfi_* directives can use arbitrary DWARF register numbers, not
2148 // just ones that map to LLVM register numbers and have known names.
2149 // Fall back to using the original number directly if no name is known.
2150 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
2151 if (std::optional<MCRegister> LLVMRegister =
2152 MRI->getLLVMRegNum(Register, true)) {
2153 InstPrinter->printRegName(OS, *LLVMRegister);
2154 return;
2155 }
2156 }
2157 OS << Register;
2158}
2159
2160void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) {
2162 OS << "\t.cfi_def_cfa ";
2163 EmitRegisterName(Register);
2164 OS << ", " << Offset;
2165 EmitEOL();
2166}
2167
2168void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) {
2170 OS << "\t.cfi_def_cfa_offset " << Offset;
2171 EmitEOL();
2172}
2173
2174void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
2175 int64_t AddressSpace, SMLoc Loc) {
2177 OS << "\t.cfi_llvm_def_aspace_cfa ";
2178 EmitRegisterName(Register);
2179 OS << ", " << Offset;
2180 OS << ", " << AddressSpace;
2181 EmitEOL();
2182}
2183
2185 OS << "\t.cfi_escape ";
2186 if (!Values.empty()) {
2187 size_t e = Values.size() - 1;
2188 for (size_t i = 0; i < e; ++i)
2189 OS << format("0x%02x", uint8_t(Values[i])) << ", ";
2190 OS << format("0x%02x", uint8_t(Values[e]));
2191 }
2192}
2193
2194void MCAsmStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) {
2197 EmitEOL();
2198}
2199
2200void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) {
2202
2203 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
2204 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
2205
2206 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
2207 EmitEOL();
2208}
2209
2210void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) {
2212 OS << "\t.cfi_def_cfa_register ";
2213 EmitRegisterName(Register);
2214 EmitEOL();
2215}
2216
2217void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
2219 OS << "\t.cfi_offset ";
2220 EmitRegisterName(Register);
2221 OS << ", " << Offset;
2222 EmitEOL();
2223}
2224
2225void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
2226 unsigned Encoding) {
2227 MCStreamer::emitCFIPersonality(Sym, Encoding);
2228 OS << "\t.cfi_personality " << Encoding << ", ";
2229 Sym->print(OS, MAI);
2230 EmitEOL();
2231}
2232
2233void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
2234 MCStreamer::emitCFILsda(Sym, Encoding);
2235 OS << "\t.cfi_lsda " << Encoding << ", ";
2236 Sym->print(OS, MAI);
2237 EmitEOL();
2238}
2239
2240void MCAsmStreamer::emitCFIRememberState(SMLoc Loc) {
2242 OS << "\t.cfi_remember_state";
2243 EmitEOL();
2244}
2245
2246void MCAsmStreamer::emitCFIRestoreState(SMLoc Loc) {
2248 OS << "\t.cfi_restore_state";
2249 EmitEOL();
2250}
2251
2252void MCAsmStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) {
2254 OS << "\t.cfi_restore ";
2255 EmitRegisterName(Register);
2256 EmitEOL();
2257}
2258
2259void MCAsmStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) {
2261 OS << "\t.cfi_same_value ";
2262 EmitRegisterName(Register);
2263 EmitEOL();
2264}
2265
2266void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset,
2267 SMLoc Loc) {
2269 OS << "\t.cfi_rel_offset ";
2270 EmitRegisterName(Register);
2271 OS << ", " << Offset;
2272 EmitEOL();
2273}
2274
2275void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) {
2277 OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
2278 EmitEOL();
2279}
2280
2281void MCAsmStreamer::emitCFISignalFrame() {
2283 OS << "\t.cfi_signal_frame";
2284 EmitEOL();
2285}
2286
2287void MCAsmStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) {
2289 OS << "\t.cfi_undefined ";
2290 EmitRegisterName(Register);
2291 EmitEOL();
2292}
2293
2294void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2,
2295 SMLoc Loc) {
2296 MCStreamer::emitCFIRegister(Register1, Register2, Loc);
2297 OS << "\t.cfi_register ";
2298 EmitRegisterName(Register1);
2299 OS << ", ";
2300 EmitRegisterName(Register2);
2301 EmitEOL();
2302}
2303
2304void MCAsmStreamer::emitCFILLVMRegisterPair(int64_t Register, int64_t R1,
2305 int64_t R1Size, int64_t R2,
2306 int64_t R2Size, SMLoc Loc) {
2307 MCStreamer::emitCFILLVMRegisterPair(Register, R1, R1Size, R2, R2Size, Loc);
2308
2309 OS << "\t.cfi_llvm_register_pair ";
2310 EmitRegisterName(Register);
2311 OS << ", ";
2312 EmitRegisterName(R1);
2313 OS << ", " << R1Size << ", ";
2314 EmitRegisterName(R2);
2315 OS << ", " << R2Size;
2316 EmitEOL();
2317}
2318
2319void MCAsmStreamer::emitCFILLVMVectorRegisters(
2321 SMLoc Loc) {
2323
2324 OS << "\t.cfi_llvm_vector_registers ";
2325 EmitRegisterName(Register);
2326 for (auto [Reg, Lane, Size] : VRs)
2327 OS << ", " << Reg << ", " << Lane << ", " << Size;
2328 EmitEOL();
2329}
2330
2331void MCAsmStreamer::emitCFILLVMVectorOffset(int64_t Register,
2332 int64_t RegisterSize,
2333 int64_t MaskRegister,
2334 int64_t MaskRegisterSize,
2335 int64_t Offset, SMLoc Loc) {
2336 MCStreamer::emitCFILLVMVectorOffset(Register, RegisterSize, MaskRegister,
2337 MaskRegisterSize, Offset, Loc);
2338
2339 OS << "\t.cfi_llvm_vector_offset ";
2340 EmitRegisterName(Register);
2341 OS << ", " << RegisterSize << ", ";
2342 EmitRegisterName(MaskRegister);
2343 OS << ", " << MaskRegisterSize << ", " << Offset;
2344 EmitEOL();
2345}
2346
2347void MCAsmStreamer::emitCFILLVMVectorRegisterMask(
2348 int64_t Register, int64_t SpillRegister,
2349 int64_t SpillRegisterLaneSizeInBits, int64_t MaskRegister,
2350 int64_t MaskRegisterSizeInBits, SMLoc Loc) {
2352 Register, SpillRegister, SpillRegisterLaneSizeInBits, MaskRegister,
2353 MaskRegisterSizeInBits, Loc);
2354
2355 OS << "\t.cfi_llvm_vector_register_mask ";
2356 EmitRegisterName(Register);
2357 OS << ", ";
2358 EmitRegisterName(SpillRegister);
2359 OS << ", " << SpillRegisterLaneSizeInBits << ", ";
2360 EmitRegisterName(MaskRegister);
2361 OS << ", " << MaskRegisterSizeInBits;
2362 EmitEOL();
2363}
2364
2365void MCAsmStreamer::emitCFIWindowSave(SMLoc Loc) {
2367 OS << "\t.cfi_window_save";
2368 EmitEOL();
2369}
2370
2371void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) {
2373 OS << "\t.cfi_negate_ra_state";
2374 EmitEOL();
2375}
2376
2377void MCAsmStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) {
2379 OS << "\t.cfi_negate_ra_state_with_pc";
2380 EmitEOL();
2381}
2382
2383void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
2385 OS << "\t.cfi_return_column ";
2386 EmitRegisterName(Register);
2387 EmitEOL();
2388}
2389
2390void MCAsmStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
2392 OS << "\t.cfi_label " << Name;
2393 EmitEOL();
2394}
2395
2396void MCAsmStreamer::emitCFIBKeyFrame() {
2398 OS << "\t.cfi_b_key_frame";
2399 EmitEOL();
2400}
2401
2402void MCAsmStreamer::emitCFIMTETaggedFrame() {
2404 OS << "\t.cfi_mte_tagged_frame";
2405 EmitEOL();
2406}
2407
2408void MCAsmStreamer::emitCFIValOffset(int64_t Register, int64_t Offset,
2409 SMLoc Loc) {
2411 OS << "\t.cfi_val_offset ";
2412 EmitRegisterName(Register);
2413 OS << ", " << Offset;
2414 EmitEOL();
2415}
2416
2417void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
2419
2420 OS << ".seh_proc ";
2421 Symbol->print(OS, MAI);
2422 EmitEOL();
2423}
2424
2425void MCAsmStreamer::emitWinCFIEndProc(SMLoc Loc) {
2427
2428 OS << "\t.seh_endproc";
2429 EmitEOL();
2430}
2431
2432void MCAsmStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
2434
2435 OS << "\t.seh_endfunclet";
2436 EmitEOL();
2437}
2438
2439void MCAsmStreamer::emitWinCFISplitChained(SMLoc Loc) {
2441
2442 OS << "\t.seh_splitchained";
2443 EmitEOL();
2444}
2445
2446void MCAsmStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind,
2447 bool Except, SMLoc Loc) {
2448 MCStreamer::emitWinEHHandler(Sym, Unwind, Except, Loc);
2449
2450 OS << "\t.seh_handler ";
2451 Sym->print(OS, MAI);
2452 char Marker = '@';
2453 const Triple &T = getContext().getTargetTriple();
2454 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
2455 Marker = '%';
2456 if (Unwind)
2457 OS << ", " << Marker << "unwind";
2458 if (Except)
2459 OS << ", " << Marker << "except";
2460 EmitEOL();
2461}
2462
2463void MCAsmStreamer::emitWinEHHandlerData(SMLoc Loc) {
2465
2466 // Switch sections. Don't call switchSection directly, because that will
2467 // cause the section switch to be visible in the emitted assembly.
2468 // We only do this so the section switch that terminates the handler
2469 // data block is visible.
2470 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
2471
2472 // Do nothing if no frame is open. MCStreamer should've already reported an
2473 // error.
2474 if (!CurFrame)
2475 return;
2476
2477 MCSection *TextSec = &CurFrame->Function->getSection();
2478 MCSection *XData = getAssociatedXDataSection(TextSec);
2479 switchSectionNoPrint(XData);
2480
2481 OS << "\t.seh_handlerdata";
2482 EmitEOL();
2483}
2484
2485void MCAsmStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
2487
2488 OS << "\t.seh_pushreg ";
2489 InstPrinter->printRegName(OS, Register);
2490 EmitEOL();
2491}
2492
2493void MCAsmStreamer::emitWinCFIPush2Regs(MCRegister Reg1, MCRegister Reg2,
2494 SMLoc Loc) {
2496
2497 OS << "\t.seh_push2regs ";
2498 InstPrinter->printRegName(OS, Reg1);
2499 OS << ", ";
2500 InstPrinter->printRegName(OS, Reg2);
2501 EmitEOL();
2502}
2503
2504void MCAsmStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
2505 SMLoc Loc) {
2507
2508 OS << "\t.seh_setframe ";
2509 InstPrinter->printRegName(OS, Register);
2510 OS << ", " << Offset;
2511 EmitEOL();
2512}
2513
2514void MCAsmStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
2516
2517 OS << "\t.seh_stackalloc " << Size;
2518 EmitEOL();
2519}
2520
2521void MCAsmStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
2522 SMLoc Loc) {
2524
2525 OS << "\t.seh_savereg ";
2526 InstPrinter->printRegName(OS, Register);
2527 OS << ", " << Offset;
2528 EmitEOL();
2529}
2530
2531void MCAsmStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
2532 SMLoc Loc) {
2534
2535 OS << "\t.seh_savexmm ";
2536 InstPrinter->printRegName(OS, Register);
2537 OS << ", " << Offset;
2538 EmitEOL();
2539}
2540
2541void MCAsmStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
2543
2544 OS << "\t.seh_pushframe";
2545 if (Code)
2546 OS << " @code";
2547 EmitEOL();
2548}
2549
2550void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) {
2552
2553 OS << "\t.seh_endprologue";
2554 EmitEOL();
2555}
2556
2557void MCAsmStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) {
2559
2560 OS << "\t.seh_startepilogue";
2561 EmitEOL();
2562}
2563
2564void MCAsmStreamer::emitWinCFIEndEpilogue(SMLoc Loc) {
2566
2567 OS << "\t.seh_endepilogue";
2568 EmitEOL();
2569}
2570
2571void MCAsmStreamer::emitWinCFIUnwindV2Start(SMLoc Loc) {
2573
2574 OS << "\t.seh_unwindv2start";
2575 EmitEOL();
2576}
2577
2578void MCAsmStreamer::emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc) {
2580
2581 OS << "\t.seh_unwindversion " << (unsigned)Version;
2582 EmitEOL();
2583}
2584
2585void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
2586 const MCSymbolRefExpr *To,
2587 uint64_t Count) {
2588 OS << "\t.cg_profile ";
2589 From->getSymbol().print(OS, MAI);
2590 OS << ", ";
2591 To->getSymbol().print(OS, MAI);
2592 OS << ", " << Count;
2593 EmitEOL();
2594}
2595
2596void MCAsmStreamer::emitInstruction(const MCInst &Inst,
2597 const MCSubtargetInfo &STI) {
2598 if (LFIRewriter && LFIRewriter->rewriteInst(Inst, *this, STI))
2599 return;
2600
2601 if (CurFrag) {
2602 MCSection *Sec = getCurrentSectionOnly();
2603 Sec->setHasInstructions(true);
2604 }
2605
2606 if (MAI->isAIX() && CurFrag)
2607 // Now that a machine instruction has been assembled into this section, make
2608 // a line entry for any .loc directive that has been seen.
2609 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
2610
2611 // Show the encoding in a comment if we have a code emitter.
2612 addEncodingComment(Inst, STI);
2613
2614 // Show the MCInst if enabled.
2615 if (ShowInst) {
2616 Inst.dump_pretty(getCommentOS(), InstPrinter.get(), "\n ", &getContext());
2617 getCommentOS() << "\n";
2618 }
2619
2620 if(getTargetStreamer())
2621 getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
2622 else
2623 InstPrinter->printInst(&Inst, 0, "", STI, OS);
2624
2625 StringRef Comments = CommentToEmit;
2626 if (Comments.size() && Comments.back() != '\n')
2627 getCommentOS() << "\n";
2628
2629 EmitEOL();
2630}
2631
2632void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
2633 uint64_t Type, uint64_t Attr,
2634 uint64_t Discriminator,
2635 const MCPseudoProbeInlineStack &InlineStack,
2636 MCSymbol *FnSym) {
2637 OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " " << Attr;
2638 if (Discriminator)
2639 OS << " " << Discriminator;
2640 // Emit inline stack like
2641 // @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2642 for (const auto &Site : InlineStack)
2643 OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2644
2645 OS << " ";
2646 FnSym->print(OS, MAI);
2647
2648 EmitEOL();
2649}
2650
2651void MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2652 const MCExpr *Expr, SMLoc) {
2653 OS << "\t.reloc ";
2654 MAI->printExpr(OS, Offset);
2655 OS << ", " << Name;
2656 if (Expr) {
2657 OS << ", ";
2658 MAI->printExpr(OS, *Expr);
2659 }
2660 EmitEOL();
2661}
2662
2663void MCAsmStreamer::emitAddrsig() {
2664 OS << "\t.addrsig";
2665 EmitEOL();
2666}
2667
2668void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
2669 OS << "\t.addrsig_sym ";
2670 Sym->print(OS, MAI);
2671 EmitEOL();
2672}
2673
2674/// EmitRawText - If this file is backed by an assembly streamer, this dumps
2675/// the specified string in the output .s file. This capability is
2676/// indicated by the hasRawTextSupport() predicate.
2677void MCAsmStreamer::emitRawTextImpl(StringRef String) {
2678 String.consume_back("\n");
2679 OS << String;
2680 EmitEOL();
2681}
2682
2683void MCAsmStreamer::finishImpl() {
2684 if (getContext().getTargetTriple().isLFI())
2686
2687 // If we are generating dwarf for assembly source files dump out the sections.
2688 if (getContext().getGenDwarfForAssembly())
2690
2691 // Now it is time to emit debug line sections if target doesn't support .loc
2692 // and .line directives.
2693 if (MAI->isAIX()) {
2694 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
2695 return;
2696 }
2697
2698 // Emit the label for the line table, if requested - since the rest of the
2699 // line table will be defined by .loc/.file directives, and not emitted
2700 // directly, the label is the only work required here.
2701 const auto &Tables = getContext().getMCDwarfLineTables();
2702 if (!Tables.empty()) {
2703 assert(Tables.size() == 1 && "asm output only supports one line table");
2704 if (auto *Label = Tables.begin()->second.getLabel()) {
2705 switchSection(getContext().getObjectFileInfo()->getDwarfLineSection(), 0);
2706 emitLabel(Label);
2707 }
2708 }
2709}
2710
2711void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
2712 // If the assembler on some target fills in the DWARF unit length, we
2713 // don't want to emit the length in the compiler. For example, the AIX
2714 // assembler requires the assembly file with the unit length omitted from
2715 // the debug section headers. In such cases, any label we placed occurs
2716 // after the implied length field. We need to adjust the reference here
2717 // to account for the offset introduced by the inserted length field.
2718 if (MAI->isAIX())
2719 return;
2721}
2722
2723MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,
2724 const Twine &Comment) {
2725 // If the assembler on some target fills in the DWARF unit length, we
2726 // don't want to emit the length in the compiler. For example, the AIX
2727 // assembler requires the assembly file with the unit length omitted from
2728 // the debug section headers. In such cases, any label we placed occurs
2729 // after the implied length field. We need to adjust the reference here
2730 // to account for the offset introduced by the inserted length field.
2731 if (MAI->isAIX())
2732 return getContext().createTempSymbol(Prefix + "_end");
2733 return MCStreamer::emitDwarfUnitLength(Prefix, Comment);
2734}
2735
2736void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
2737 // If the assembler on some target fills in the DWARF unit length, we
2738 // don't want to emit the length in the compiler. For example, the AIX
2739 // assembler requires the assembly file with the unit length omitted from
2740 // the debug section headers. In such cases, any label we placed occurs
2741 // after the implied length field. We need to adjust the reference here
2742 // to account for the offset introduced by the inserted length field.
2743 MCContext &Ctx = getContext();
2744 if (MAI->isAIX()) {
2745 MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");
2746 // Emit the symbol which does not contain the unit length field.
2747 emitLabel(DebugLineSymTmp);
2748
2749 // Adjust the outer reference to account for the offset introduced by the
2750 // inserted length field.
2751 unsigned LengthFieldSize =
2753 const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);
2754 const MCExpr *OuterSym = MCBinaryExpr::createSub(
2755 MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);
2756
2757 emitAssignment(StartSym, OuterSym);
2758 return;
2759 }
2761}
2762
2763void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,
2764 MCSymbol *LastLabel,
2765 MCSymbol *EndLabel) {
2766 // If the targets write the raw debug line data for assembly output (We can
2767 // not switch to Section and add the end symbol there for assembly output)
2768 // we currently use the .text end label as any section end. This will not
2769 // impact the debugability as we will jump to the caller of the last function
2770 // in the section before we come into the .text end address.
2771 assert(MAI->isAIX() &&
2772 ".loc should not be generated together with raw data!");
2773
2774 MCContext &Ctx = getContext();
2775
2776 // FIXME: use section end symbol as end of the Section. We need to consider
2777 // the explicit sections and -ffunction-sections when we try to generate or
2778 // find section end symbol for the Section.
2779 MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();
2780 assert(TextSection->hasEnded() && ".text section is not end!");
2781
2782 if (!EndLabel)
2783 EndLabel = TextSection->getEndSymbol(Ctx);
2784 const MCAsmInfo &AsmInfo = Ctx.getAsmInfo();
2785 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, EndLabel,
2786 AsmInfo.getCodePointerSize());
2787}
2788
2789// Generate DWARF line sections for assembly mode without .loc/.file
2790void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
2791 const MCSymbol *LastLabel,
2792 const MCSymbol *Label,
2793 unsigned PointerSize) {
2794 assert(MAI->isAIX() &&
2795 ".loc/.file don't need raw data in debug line section!");
2796
2797 // Set to new address.
2798 AddComment("Set address to " + Label->getName());
2799 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2800 emitULEB128IntValue(PointerSize + 1);
2801 emitIntValue(dwarf::DW_LNE_set_address, 1);
2802 emitSymbolValue(Label, PointerSize);
2803
2804 if (!LastLabel) {
2805 // Emit the sequence for the LineDelta (from 1) and a zero address delta.
2806 AddComment("Start sequence");
2807 MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);
2808 return;
2809 }
2810
2811 // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence
2812 // for the end of the section.
2813 if (LineDelta == INT64_MAX) {
2814 AddComment("End sequence");
2815 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2816 emitULEB128IntValue(1);
2817 emitIntValue(dwarf::DW_LNE_end_sequence, 1);
2818 return;
2819 }
2820
2821 // Advance line.
2822 AddComment("Advance line " + Twine(LineDelta));
2823 emitIntValue(dwarf::DW_LNS_advance_line, 1);
2824 emitSLEB128IntValue(LineDelta);
2825 emitIntValue(dwarf::DW_LNS_copy, 1);
2826}
2827
2829 std::unique_ptr<formatted_raw_ostream> OS,
2830 std::unique_ptr<MCInstPrinter> IP,
2831 std::unique_ptr<MCCodeEmitter> CE,
2832 std::unique_ptr<MCAsmBackend> MAB) {
2833 return new MCAsmStreamer(Context, std::move(OS), std::move(IP), std::move(CE),
2834 std::move(MAB));
2835}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu next use printer
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:337
dxil DXContainer Global Emitter
DXIL Finalize Linkage
dxil translate DXIL Translate Metadata
static ManagedStatic< cl::opt< bool, true >, CreateDebug > Debug
Definition Debug.cpp:147
IRTranslator LLVM IR MI
static LVOptions Options
Definition LVOptions.cpp:25
static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values)
static const char * getVersionMinDirective(MCVersionMinType Type)
static bool isPrintableString(StringRef Data)
static void PrintByteList(StringRef Data, raw_ostream &OS, MCAsmInfo::AsmCharLiteralSyntax ACLS)
static char toOctal(int X)
static void EmitSDKVersionSuffix(raw_ostream &OS, const VersionTuple &SDKVersion)
static int64_t truncateToSize(int64_t Value, unsigned Bytes)
static const char * getPlatformName(MachO::PlatformType Type)
#define DWARF2_FLAG_IS_STMT
Definition MCDwarf.h:119
#define DWARF2_FLAG_BASIC_BLOCK
Definition MCDwarf.h:120
#define DWARF2_FLAG_PROLOGUE_END
Definition MCDwarf.h:121
#define DWARF2_FLAG_EPILOGUE_BEGIN
Definition MCDwarf.h:122
This file declares the MCLFIRewriter class, an abstract class that encapsulates the rewriting logic f...
LFI-specific code for MC.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
#define R2(n)
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file defines the SmallString class.
This file contains some functions that are useful when dealing with strings.
StringRef getMnemonic(unsigned Opc)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
LLVM_ABI void print(raw_ostream &OS) const
Print out the bounds to a stream.
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
void addEncodingComment(const MCInst &Inst, const MCSubtargetInfo &STI)
Add a comment showing the encoding of an instruction.
std::unique_ptr< MCAssembler > Assembler
SmallString< 128 > CommentToEmit
MCAssembler & getAssembler()
raw_ostream & getCommentOS() override
Return a raw_ostream that comments can be written to.
raw_null_ostream NullStream
MCAsmBaseStreamer(MCContext &Context, std::unique_ptr< MCCodeEmitter > Emitter, std::unique_ptr< MCAsmBackend > AsmBackend)
raw_svector_ostream CommentStream
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:66
const char * getLabelSuffix() const
Definition MCAsmInfo.h:557
bool hasDotTypeDotSizeDirective() const
Definition MCAsmInfo.h:628
bool isLittleEndian() const
True if the target is little endian.
Definition MCAsmInfo.h:461
bool doesSupportDataRegionDirectives() const
Definition MCAsmInfo.h:595
bool usesSetToEquateSymbol() const
Definition MCAsmInfo.h:559
const char * getData32bitsDirective() const
Definition MCAsmInfo.h:472
unsigned getTextAlignFillValue() const
Definition MCAsmInfo.h:611
bool useDwarfRegNumForCFI() const
Definition MCAsmInfo.h:685
bool supportsExtendedDwarfLocDirective() const
Definition MCAsmInfo.h:688
const char * getData8bitsDirective() const
Definition MCAsmInfo.h:470
const char * getData64bitsDirective() const
Definition MCAsmInfo.h:473
AsmCharLiteralSyntax characterLiteralSyntax() const
Definition MCAsmInfo.h:607
bool isAIX() const
Definition MCAsmInfo.h:536
LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const
Definition MCAsmInfo.h:622
void printExpr(raw_ostream &, const MCExpr &) const
virtual void printSwitchToSection(const MCSection &, uint32_t Subsection, const Triple &, raw_ostream &) const
Definition MCAsmInfo.h:506
StringRef getCommentString() const
Definition MCAsmInfo.h:555
const char * getAscizDirective() const
Definition MCAsmInfo.h:606
const char * getZeroDirective() const
Definition MCAsmInfo.h:604
const char * getWeakDirective() const
Definition MCAsmInfo.h:632
const char * getData16bitsDirective() const
Definition MCAsmInfo.h:471
const char * getSeparatorString() const
Definition MCAsmInfo.h:550
bool getCOMMDirectiveAlignmentIsInBytes() const
Definition MCAsmInfo.h:618
const char * getGlobalDirective() const
Definition MCAsmInfo.h:612
unsigned getCommentColumn() const
Definition MCAsmInfo.h:552
bool hasSingleParameterDotFile() const
Definition MCAsmInfo.h:629
const char * getAsciiDirective() const
Definition MCAsmInfo.h:605
AsmCharLiteralSyntax
Assembly character literal syntax types.
Definition MCAsmInfo.h:69
@ ACLS_SingleQuotePrefix
Unknown; character literals not used by LLVM for this target.
Definition MCAsmInfo.h:72
const char * getWeakRefDirective() const
Definition MCAsmInfo.h:633
bool hasNoDeadStrip() const
Definition MCAsmInfo.h:631
bool hasIdentDirective() const
Definition MCAsmInfo.h:630
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
Definition MCAsmInfo.h:452
MCCodeEmitter & getEmitter() const
MCAsmBackend & getBackend() const
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
const MCObjectFileInfo * getObjectFileInfo() const
Definition MCContext.h:413
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
dwarf::DwarfFormat getDwarfFormat() const
Definition MCContext.h:811
const MCAsmInfo & getAsmInfo() const
Definition MCContext.h:409
const Triple & getTargetTriple() const
Definition MCContext.h:397
static LLVM_ABI void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta)
Utility function to emit the encoding to a streamer.
Definition MCDwarf.cpp:729
static LLVM_ABI void make(MCStreamer *MCOS, MCSection *Section)
Definition MCDwarf.cpp:91
static LLVM_ABI void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params)
Definition MCDwarf.cpp:307
LLVM_ABI Expected< unsigned > tryGetFile(StringRef &Directory, StringRef &FileName, std::optional< MD5::MD5Result > Checksum, std::optional< StringRef > Source, uint16_t DwarfVersion, unsigned FileNumber=0)
Definition MCDwarf.cpp:630
const SmallVectorImpl< MCDwarfFile > & getMCDwarfFiles() const
Definition MCDwarf.h:443
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition MCFixup.h:61
static LLVM_ABI void Emit(MCStreamer *MCOS)
Definition MCDwarf.cpp:1204
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
LLVM_ABI void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer=nullptr, StringRef Separator=" ", const MCContext *Ctx=nullptr) const
Dump the MCInst as prettily as possible using the additional MC structures, if given.
Definition MCInst.cpp:90
MCSection * getTextSection() const
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
std::optional< MCRegister > getLLVMRegNum(uint64_t RegNum, bool isEH) const
Map a dwarf register back to a target register.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
This represents a section on a Mach-O system (used by Mac OS X).
StringRef getSegmentName() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:573
MCSymbol * getEndSymbol(MCContext &Ctx)
Definition MCSection.cpp:27
void setHasInstructions(bool Value)
Definition MCSection.h:670
StringRef getName() const
Definition MCSection.h:643
bool hasEnded() const
Definition MCSection.cpp:33
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual void emitCFIGnuArgsSize(int64_t Size, SMLoc Loc={})
virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value)
Emit an assignment of Value to Symbol.
virtual void emitCFILLVMVectorOffset(int64_t Register, int64_t RegisterSizeInBits, int64_t MaskRegister, int64_t MaskRegisterSizeInBits, int64_t Offset, SMLoc Loc={})
virtual void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc={})
virtual void emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc=SMLoc())
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitCFIBKeyFrame()
virtual void emitWinCFIPushReg(MCRegister Register, SMLoc Loc=SMLoc())
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, SMLoc Loc=SMLoc())
virtual void emitCFISections(bool EH, bool Debug, bool SFrame)
virtual void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name)
This implements the '.loc_label Name' directive.
virtual void emitCFINegateRAStateWithPC(SMLoc Loc={})
virtual void emitCFISameValue(int64_t Register, SMLoc Loc={})
virtual void emitCFIReturnColumn(int64_t Register)
virtual void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding)
virtual void emitDwarfUnitLength(uint64_t Length, const Twine &Comment)
Emit a unit length field.
virtual void emitCFIWindowSave(SMLoc Loc={})
virtual void emitCFILLVMRegisterPair(int64_t Register, int64_t R1, int64_t R1SizeInBits, int64_t R2, int64_t R2SizeInBits, SMLoc Loc={})
virtual void emitWinCFIUnwindV2Start(SMLoc Loc=SMLoc())
virtual void emitWinCFIEndEpilogue(SMLoc Loc=SMLoc())
virtual void emitWinCFIPushFrame(bool Code, SMLoc Loc=SMLoc())
virtual void emitWinEHHandlerData(SMLoc Loc=SMLoc())
virtual void emitCFIUndefined(int64_t Register, SMLoc Loc={})
virtual void emitWinCFISaveXMM(MCRegister Register, unsigned Offset, SMLoc Loc=SMLoc())
virtual void emitCFINegateRAState(SMLoc Loc={})
virtual void emitCFILsda(const MCSymbol *Sym, unsigned Encoding)
MCContext & getContext() const
Definition MCStreamer.h:326
virtual void emitWinCFIBeginEpilogue(SMLoc Loc=SMLoc())
virtual void emitCFIMTETaggedFrame()
virtual void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc=SMLoc())
virtual void emitDwarfLineStartLabel(MCSymbol *StartSym)
Emit the debug line start label.
virtual void emitCFIEscape(StringRef Values, SMLoc Loc={})
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitCFIRememberState(SMLoc Loc)
virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name)
virtual void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName, StringRef Comment={})
This implements the DWARF2 '.loc fileno lineno ...' assembler directive.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
MCStreamer(MCContext &Ctx)
virtual void emitWinCFISaveReg(MCRegister Register, unsigned Offset, SMLoc Loc=SMLoc())
virtual void emitWinCFIEndProlog(SMLoc Loc=SMLoc())
virtual void emitWinCFIEndProc(SMLoc Loc=SMLoc())
virtual void emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame)
virtual void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc={})
virtual MCSymbol * getDwarfLineTableSymbol(unsigned CUID)
virtual void emitCFIRegister(int64_t Register1, int64_t Register2, SMLoc Loc={})
virtual void emitWinCFIFuncletOrFuncEnd(SMLoc Loc=SMLoc())
This is used on platforms, such as Windows on ARM64, that require function or funclet sizes to be emi...
virtual void emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc={})
virtual void emitWinCFIPush2Regs(MCRegister Reg1, MCRegister Reg2, SMLoc Loc=SMLoc())
virtual void emitCFILLVMVectorRegisterMask(int64_t Register, int64_t SpillRegister, int64_t SpillRegisterLaneSizeInBits, int64_t MaskRegister, int64_t MaskRegisterSizeInBits, SMLoc Loc={})
virtual void emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc)
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
virtual void emitCFIRestoreState(SMLoc Loc)
virtual void emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc={})
virtual void emitWinCFISetFrame(MCRegister Register, unsigned Offset, SMLoc Loc=SMLoc())
virtual void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc={})
virtual void emitWinCFISplitChained(SMLoc Loc=SMLoc())
virtual void emitWinCFIAllocStack(unsigned Size, SMLoc Loc=SMLoc())
virtual void emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc={})
virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)
Introduces an inline call site id for use with .cv_loc.
virtual void emitCFISignalFrame()
virtual void emitCFILLVMVectorRegisters(int64_t Register, ArrayRef< MCCFIInstruction::VectorRegisterWithLane > VRs, SMLoc Loc={})
virtual void emitCFIRestore(int64_t Register, SMLoc Loc={})
virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
This implements the CodeView '.cv_inline_linetable' assembler directive.
void emitFill(uint64_t NumBytes, uint8_t FillValue)
Emit NumBytes bytes worth of the value specified by FillValue.
virtual void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, int64_t AddressSpace, SMLoc Loc={})
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
const MCSymbol & getSymbol() const
Definition MCExpr.h:226
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
Definition MCSymbol.h:251
DwarfDirectory MCUseDwarfDirectory
Target specific streamer interface.
Definition MCStreamer.h:95
Root of the metadata hierarchy.
Definition Metadata.h:64
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Represents a location in source code.
Definition SMLoc.h:22
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
void resize(size_type N)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
char back() const
Get the last character in the string.
Definition StringRef.h:153
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:720
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
char front() const
Get the first character in the string.
Definition StringRef.h:147
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition StringRef.h:396
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
bool isRISCV() const
Tests whether the target is RISC-V (32- and 64-bit).
Definition Triple.h:1177
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
Represents a version number in the form major[.minor[.subminor[.build]]].
unsigned getMajor() const
Retrieve the major version number.
std::optional< unsigned > getSubminor() const
Retrieve the subminor version number, if provided.
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
std::optional< unsigned > getMinor() const
Retrieve the minor version number, if provided.
formatted_raw_ostream - A raw_ostream that wraps another one and keeps track of line and column posit...
formatted_raw_ostream & PadToColumn(unsigned NewCol)
PadToColumn - Align the output to some column number.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
A raw_ostream that writes to an SmallVector or SmallString.
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
#define INT64_MAX
Definition DataTypes.h:71
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
uint8_t getUnitLengthFieldByteSize(DwarfFormat Format)
Get the byte size of the unit length field depending on the DWARF format.
Definition Dwarf.h:1151
support::ulittle32_t Word
Definition IRSymtab.h:53
bool isRelocation(MCFixupKind FixupKind)
Definition MCFixup.h:130
LLVM_ABI int getDwarfVersion()
@ Emitted
Assigned address, still materializing.
Definition Core.h:570
uint32_t read32be(const void *P)
Definition Endian.h:441
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:688
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:467
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:573
@ Length
Definition DWP.cpp:573
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
@ Debug
Register 'use' is for debugging purpose.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static StringRef MCLOHDirectiveName()
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
LLVM_ABI MCStreamer * createAsmStreamer(MCContext &Ctx, std::unique_ptr< formatted_raw_ostream > OS, std::unique_ptr< MCInstPrinter > InstPrint, std::unique_ptr< MCCodeEmitter > CE, std::unique_ptr< MCAsmBackend > TAB)
Create a machine code streamer which will print out assembly for the native target,...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:337
MCDataRegionType
@ MCDR_DataRegionEnd
.end_data_region
@ MCDR_DataRegion
.data_region
@ MCDR_DataRegionJT8
.data_region jt8
@ MCDR_DataRegionJT32
.data_region jt32
@ MCDR_DataRegionJT16
.data_region jt16
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
MCLOHDirective::LOHArgs MCLOHArgs
LLVM_ABI void emitLFINoteSection(MCStreamer &Streamer, MCContext &Ctx)
Definition MCLFI.cpp:53
SmallVector< InlineSite, 8 > MCPseudoProbeInlineStack
MCVersionMinType
@ MCVM_WatchOSVersionMin
.watchos_version_min
@ MCVM_OSXVersionMin
.macosx_version_min
@ MCVM_TvOSVersionMin
.tvos_version_min
@ MCVM_IOSVersionMin
.ios_version_min
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:156
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:94
static int MCLOHIdToNbArgs(MCLOHType Kind)
MCLOHType
Linker Optimization Hint Type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
ArrayRef(const T &OneElt) -> ArrayRef< T >
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
bool isPrint(char C)
Checks whether character C is printable.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition LEB128.h:79
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
std::pair< MCSection *, uint32_t > MCSectionSubPair
Definition MCStreamer.h:68
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
@ MCSA_Local
.local (ELF)
@ MCSA_WeakDefAutoPrivate
.weak_def_can_be_hidden (MachO)
@ MCSA_Memtag
.memtag (ELF)
@ MCSA_Protected
.protected (ELF)
@ MCSA_OSLinkage
symbol uses OS linkage (GOFF)
@ MCSA_Exported
.globl _foo, exported (XCOFF)
@ MCSA_PrivateExtern
.private_extern (MachO)
@ MCSA_Internal
.internal (ELF)
@ MCSA_WeakReference
.weak_reference (MachO)
@ MCSA_AltEntry
.alt_entry (MachO)
@ MCSA_ELF_TypeIndFunction
.type _foo, STT_GNU_IFUNC
@ MCSA_LazyReference
.lazy_reference (MachO)
@ MCSA_ELF_TypeNoType
.type _foo, STT_NOTYPE # aka @notype
@ MCSA_Reference
.reference (MachO)
@ MCSA_SymbolResolver
.symbol_resolver (MachO)
@ MCSA_Weak
.weak
@ MCSA_ELF_TypeTLS
.type _foo, STT_TLS # aka @tls_object
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_WeakDefinition
.weak_definition (MachO)
@ MCSA_ELF_TypeCommon
.type _foo, STT_COMMON # aka @common
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_XPLinkage
symbol uses XP linkage (GOFF)
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_Cold
.cold (MachO)
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
@ MCSA_ELF_TypeGnuUniqueObject
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
@ MCSA_LGlobal
.lglobl (XCOFF)
@ MCSA_Invalid
Not a valid directive.
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
static StringRef MCLOHIdToName(MCLOHType Kind)
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Target independent information on a fixup kind.
const MCSymbol * Function
Definition MCWinEH.h:51
little32_t OffsetInUdt
Offset to add after dereferencing Register + BasePointerOffset.