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