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