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