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