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