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