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