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