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