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