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