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