[RISCV] Refactor predicates for rvv intrinsic patterns.
[llvm-project.git] / llvm / lib / MC / MCAsmStreamer.cpp
blobe3d11a2a33744183078e9b77212dc7dc29a2cf4a
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 //===----------------------------------------------------------------------===//
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 <optional>
41 using namespace llvm;
43 namespace {
45 class MCAsmStreamer final : public MCStreamer {
46 std::unique_ptr<formatted_raw_ostream> OSOwner;
47 formatted_raw_ostream &OS;
48 const MCAsmInfo *MAI;
49 std::unique_ptr<MCInstPrinter> InstPrinter;
50 std::unique_ptr<MCAssembler> Assembler;
52 SmallString<128> ExplicitCommentToEmit;
53 SmallString<128> CommentToEmit;
54 raw_svector_ostream CommentStream;
55 raw_null_ostream NullStream;
57 unsigned IsVerboseAsm : 1;
58 unsigned ShowInst : 1;
59 unsigned UseDwarfDirectory : 1;
61 void EmitRegisterName(int64_t Register);
62 void PrintQuotedString(StringRef Data, raw_ostream &OS) const;
63 void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
64 StringRef Filename,
65 std::optional<MD5::MD5Result> Checksum,
66 std::optional<StringRef> Source,
67 bool UseDwarfDirectory,
68 raw_svector_ostream &OS) const;
69 void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
70 void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
72 public:
73 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
74 bool isVerboseAsm, bool useDwarfDirectory,
75 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
76 std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
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), IsVerboseAsm(isVerboseAsm),
84 ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
85 assert(InstPrinter);
86 if (IsVerboseAsm)
87 InstPrinter->setCommentStream(CommentStream);
88 if (Assembler->getBackendPtr())
89 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
91 Context.setUseNamesOnTempLabels(true);
94 MCAssembler &getAssembler() { return *Assembler; }
95 MCAssembler *getAssemblerPtr() override { return nullptr; }
97 inline void EmitEOL() {
98 // Dump Explicit Comments here.
99 emitExplicitComments();
100 // If we don't have any comments, just emit a \n.
101 if (!IsVerboseAsm) {
102 OS << '\n';
103 return;
105 EmitCommentsAndEOL();
108 void emitSyntaxDirective() override;
110 void EmitCommentsAndEOL();
112 /// Return true if this streamer supports verbose assembly at all.
113 bool isVerboseAsm() const override { return IsVerboseAsm; }
115 /// Do we support EmitRawText?
116 bool hasRawTextSupport() const override { return true; }
118 /// Add a comment that can be emitted to the generated .s file to make the
119 /// output of the compiler more readable. This only affects the MCAsmStreamer
120 /// and only when verbose assembly output is enabled.
121 void AddComment(const Twine &T, bool EOL = true) override;
123 /// Add a comment showing the encoding of an instruction.
124 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
126 /// Return a raw_ostream that comments can be written to.
127 /// Unlike AddComment, you are required to terminate comments with \n if you
128 /// use this method.
129 raw_ostream &getCommentOS() override {
130 if (!IsVerboseAsm)
131 return nulls(); // Discard comments unless in verbose asm mode.
132 return CommentStream;
135 void emitRawComment(const Twine &T, bool TabPrefix = true) override;
137 void addExplicitComment(const Twine &T) override;
138 void emitExplicitComments() override;
140 /// Emit a blank line to a .s file to pretty it up.
141 void addBlankLine() override { EmitEOL(); }
143 /// @name MCStreamer Interface
144 /// @{
146 void changeSection(MCSection *Section, const MCExpr *Subsection) override;
148 void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
149 bool KeepOriginalSym) override;
151 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
153 void emitGNUAttribute(unsigned Tag, unsigned Value) override;
155 StringRef getMnemonic(MCInst &MI) override {
156 return InstPrinter->getMnemonic(&MI).first;
159 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
161 void emitAssemblerFlag(MCAssemblerFlag Flag) override;
162 void emitLinkerOptions(ArrayRef<std::string> Options) override;
163 void emitDataRegion(MCDataRegionType Kind) override;
164 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
165 unsigned Update, VersionTuple SDKVersion) override;
166 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
167 unsigned Update, VersionTuple SDKVersion) override;
168 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
169 unsigned Minor, unsigned Update,
170 VersionTuple SDKVersion) override;
171 void emitThumbFunc(MCSymbol *Func) override;
173 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
174 void emitConditionalAssignment(MCSymbol *Symbol,
175 const MCExpr *Value) override;
176 void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
177 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
179 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
180 void beginCOFFSymbolDef(const MCSymbol *Symbol) override;
181 void emitCOFFSymbolStorageClass(int StorageClass) override;
182 void emitCOFFSymbolType(int Type) override;
183 void endCOFFSymbolDef() override;
184 void emitCOFFSafeSEH(MCSymbol const *Symbol) override;
185 void emitCOFFSymbolIndex(MCSymbol const *Symbol) override;
186 void emitCOFFSectionIndex(MCSymbol const *Symbol) override;
187 void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
188 void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
189 void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
190 MCSymbol *CsectSym, Align Alignment) override;
191 void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
192 MCSymbolAttr Linakge,
193 MCSymbolAttr Visibility) override;
194 void emitXCOFFRenameDirective(const MCSymbol *Name,
195 StringRef Rename) override;
197 void emitXCOFFRefDirective(const MCSymbol *Symbol) override;
199 void emitXCOFFExceptDirective(const MCSymbol *Symbol,
200 const MCSymbol *Trap,
201 unsigned Lang, unsigned Reason,
202 unsigned FunctionSize, bool hasDebug) override;
204 void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
205 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
206 Align ByteAlignment) override;
208 /// Emit a local common (.lcomm) symbol.
210 /// @param Symbol - The common symbol to emit.
211 /// @param Size - The size of the common symbol.
212 /// @param ByteAlignment - The alignment of the common symbol in bytes.
213 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
214 Align ByteAlignment) override;
216 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
217 uint64_t Size = 0, Align ByteAlignment = Align(1),
218 SMLoc Loc = SMLoc()) override;
220 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
221 Align ByteAlignment = Align(1)) override;
223 void emitBinaryData(StringRef Data) override;
225 void emitBytes(StringRef Data) override;
227 void emitValueImpl(const MCExpr *Value, unsigned Size,
228 SMLoc Loc = SMLoc()) override;
229 void emitIntValue(uint64_t Value, unsigned Size) override;
230 void emitIntValueInHex(uint64_t Value, unsigned Size) override;
231 void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
233 void emitULEB128Value(const MCExpr *Value) override;
235 void emitSLEB128Value(const MCExpr *Value) override;
237 void emitDTPRel32Value(const MCExpr *Value) override;
238 void emitDTPRel64Value(const MCExpr *Value) override;
239 void emitTPRel32Value(const MCExpr *Value) override;
240 void emitTPRel64Value(const MCExpr *Value) override;
242 void emitGPRel64Value(const MCExpr *Value) override;
244 void emitGPRel32Value(const MCExpr *Value) override;
246 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
247 SMLoc Loc = SMLoc()) override;
249 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
250 SMLoc Loc = SMLoc()) override;
252 void emitAlignmentDirective(unsigned ByteAlignment,
253 std::optional<int64_t> Value, unsigned ValueSize,
254 unsigned MaxBytesToEmit);
256 void emitValueToAlignment(Align Alignment, int64_t Value = 0,
257 unsigned ValueSize = 1,
258 unsigned MaxBytesToEmit = 0) override;
260 void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,
261 unsigned MaxBytesToEmit = 0) override;
263 void emitValueToOffset(const MCExpr *Offset,
264 unsigned char Value,
265 SMLoc Loc) override;
267 void emitFileDirective(StringRef Filename) override;
268 void emitFileDirective(StringRef Filename, StringRef CompilerVerion,
269 StringRef TimeStamp, StringRef Description) override;
270 Expected<unsigned> tryEmitDwarfFileDirective(
271 unsigned FileNo, StringRef Directory, StringRef Filename,
272 std::optional<MD5::MD5Result> Checksum = std::nullopt,
273 std::optional<StringRef> Source = std::nullopt,
274 unsigned CUID = 0) override;
275 void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
276 std::optional<MD5::MD5Result> Checksum,
277 std::optional<StringRef> Source,
278 unsigned CUID = 0) override;
279 void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
280 unsigned Flags, unsigned Isa,
281 unsigned Discriminator,
282 StringRef FileName) override;
283 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
285 bool emitCVFileDirective(unsigned FileNo, StringRef Filename,
286 ArrayRef<uint8_t> Checksum,
287 unsigned ChecksumKind) override;
288 bool emitCVFuncIdDirective(unsigned FuncId) override;
289 bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
290 unsigned IAFile, unsigned IALine,
291 unsigned IACol, SMLoc Loc) override;
292 void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
293 unsigned Column, bool PrologueEnd, bool IsStmt,
294 StringRef FileName, SMLoc Loc) override;
295 void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
296 const MCSymbol *FnEnd) override;
297 void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
298 unsigned SourceFileId,
299 unsigned SourceLineNum,
300 const MCSymbol *FnStartSym,
301 const MCSymbol *FnEndSym) override;
303 void PrintCVDefRangePrefix(
304 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
306 void emitCVDefRangeDirective(
307 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
308 codeview::DefRangeRegisterRelHeader DRHdr) override;
310 void emitCVDefRangeDirective(
311 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
312 codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
314 void emitCVDefRangeDirective(
315 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
316 codeview::DefRangeRegisterHeader DRHdr) override;
318 void emitCVDefRangeDirective(
319 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
320 codeview::DefRangeFramePointerRelHeader DRHdr) override;
322 void emitCVStringTableDirective() override;
323 void emitCVFileChecksumsDirective() override;
324 void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
325 void emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
327 void emitIdent(StringRef IdentString) override;
328 void emitCFIBKeyFrame() override;
329 void emitCFIMTETaggedFrame() override;
330 void emitCFISections(bool EH, bool Debug) override;
331 void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
332 void emitCFIDefCfaOffset(int64_t Offset) override;
333 void emitCFIDefCfaRegister(int64_t Register) override;
334 void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
335 int64_t AddressSpace) override;
336 void emitCFIOffset(int64_t Register, int64_t Offset) override;
337 void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
338 void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
339 void emitCFIRememberState() override;
340 void emitCFIRestoreState() override;
341 void emitCFIRestore(int64_t Register) override;
342 void emitCFISameValue(int64_t Register) override;
343 void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
344 void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
345 void emitCFIEscape(StringRef Values) override;
346 void emitCFIGnuArgsSize(int64_t Size) override;
347 void emitCFISignalFrame() override;
348 void emitCFIUndefined(int64_t Register) override;
349 void emitCFIRegister(int64_t Register1, int64_t Register2) override;
350 void emitCFIWindowSave() override;
351 void emitCFINegateRAState() override;
352 void emitCFIReturnColumn(int64_t Register) override;
354 void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
355 void emitWinCFIEndProc(SMLoc Loc) override;
356 void emitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
357 void emitWinCFIStartChained(SMLoc Loc) override;
358 void emitWinCFIEndChained(SMLoc Loc) override;
359 void emitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
360 void emitWinCFISetFrame(MCRegister Register, unsigned Offset,
361 SMLoc Loc) override;
362 void emitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
363 void emitWinCFISaveReg(MCRegister Register, unsigned Offset,
364 SMLoc Loc) override;
365 void emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
366 SMLoc Loc) override;
367 void emitWinCFIPushFrame(bool Code, SMLoc Loc) override;
368 void emitWinCFIEndProlog(SMLoc Loc) override;
370 void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
371 SMLoc Loc) override;
372 void emitWinEHHandlerData(SMLoc Loc) override;
374 void emitCGProfileEntry(const MCSymbolRefExpr *From,
375 const MCSymbolRefExpr *To, uint64_t Count) override;
377 void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
379 void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
380 uint64_t Attr, uint64_t Discriminator,
381 const MCPseudoProbeInlineStack &InlineStack,
382 MCSymbol *FnSym) override;
384 void emitBundleAlignMode(Align Alignment) override;
385 void emitBundleLock(bool AlignToEnd) override;
386 void emitBundleUnlock() override;
388 std::optional<std::pair<bool, std::string>>
389 emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
390 SMLoc Loc, const MCSubtargetInfo &STI) override;
392 void emitAddrsig() override;
393 void emitAddrsigSym(const MCSymbol *Sym) override;
395 /// If this file is backed by an assembly streamer, this dumps the specified
396 /// string in the output .s file. This capability is indicated by the
397 /// hasRawTextSupport() predicate.
398 void emitRawTextImpl(StringRef String) override;
400 void finishImpl() override;
402 void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;
404 MCSymbol *emitDwarfUnitLength(const Twine &Prefix,
405 const Twine &Comment) override;
407 void emitDwarfLineStartLabel(MCSymbol *StartSym) override;
409 void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;
411 void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
412 const MCSymbol *Label,
413 unsigned PointerSize) override;
415 void doFinalizationAtSectionEnd(MCSection *Section) override;
418 } // end anonymous namespace.
420 void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
421 if (!IsVerboseAsm) return;
423 T.toVector(CommentToEmit);
425 if (EOL)
426 CommentToEmit.push_back('\n'); // Place comment in a new line.
429 void MCAsmStreamer::EmitCommentsAndEOL() {
430 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
431 OS << '\n';
432 return;
435 StringRef Comments = CommentToEmit;
437 assert(Comments.back() == '\n' &&
438 "Comment array not newline terminated");
439 do {
440 // Emit a line of comments.
441 OS.PadToColumn(MAI->getCommentColumn());
442 size_t Position = Comments.find('\n');
443 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
445 Comments = Comments.substr(Position+1);
446 } while (!Comments.empty());
448 CommentToEmit.clear();
451 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
452 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
453 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
456 void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
457 if (TabPrefix)
458 OS << '\t';
459 OS << MAI->getCommentString() << T;
460 EmitEOL();
463 void MCAsmStreamer::addExplicitComment(const Twine &T) {
464 StringRef c = T.getSingleStringRef();
465 if (c.equals(StringRef(MAI->getSeparatorString())))
466 return;
467 if (c.startswith(StringRef("//"))) {
468 ExplicitCommentToEmit.append("\t");
469 ExplicitCommentToEmit.append(MAI->getCommentString());
470 // drop //
471 ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
472 } else if (c.startswith(StringRef("/*"))) {
473 size_t p = 2, len = c.size() - 2;
474 // emit each line in comment as separate newline.
475 do {
476 size_t newp = std::min(len, c.find_first_of("\r\n", p));
477 ExplicitCommentToEmit.append("\t");
478 ExplicitCommentToEmit.append(MAI->getCommentString());
479 ExplicitCommentToEmit.append(c.slice(p, newp).str());
480 // If we have another line in this comment add line
481 if (newp < len)
482 ExplicitCommentToEmit.append("\n");
483 p = newp + 1;
484 } while (p < len);
485 } else if (c.startswith(StringRef(MAI->getCommentString()))) {
486 ExplicitCommentToEmit.append("\t");
487 ExplicitCommentToEmit.append(c.str());
488 } else if (c.front() == '#') {
490 ExplicitCommentToEmit.append("\t");
491 ExplicitCommentToEmit.append(MAI->getCommentString());
492 ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
493 } else
494 assert(false && "Unexpected Assembly Comment");
495 // full line comments immediately output
496 if (c.back() == '\n')
497 emitExplicitComments();
500 void MCAsmStreamer::emitExplicitComments() {
501 StringRef Comments = ExplicitCommentToEmit;
502 if (!Comments.empty())
503 OS << Comments;
504 ExplicitCommentToEmit.clear();
507 void MCAsmStreamer::changeSection(MCSection *Section,
508 const MCExpr *Subsection) {
509 assert(Section && "Cannot switch to a null section!");
510 if (MCTargetStreamer *TS = getTargetStreamer()) {
511 TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
512 } else {
513 Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS,
514 Subsection);
518 void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
519 StringRef Name,
520 bool KeepOriginalSym) {
521 OS << ".symver ";
522 OriginalSym->print(OS, MAI);
523 OS << ", " << Name;
524 if (!KeepOriginalSym && !Name.contains("@@@"))
525 OS << ", remove";
526 EmitEOL();
529 void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
530 MCStreamer::emitLabel(Symbol, Loc);
532 Symbol->print(OS, MAI);
533 OS << MAI->getLabelSuffix();
535 EmitEOL();
538 void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
539 StringRef str = MCLOHIdToName(Kind);
541 #ifndef NDEBUG
542 int NbArgs = MCLOHIdToNbArgs(Kind);
543 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
544 assert(str != "" && "Invalid LOH name");
545 #endif
547 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
548 bool IsFirst = true;
549 for (const MCSymbol *Arg : Args) {
550 if (!IsFirst)
551 OS << ", ";
552 IsFirst = false;
553 Arg->print(OS, MAI);
555 EmitEOL();
558 void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
559 OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
562 void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
563 switch (Flag) {
564 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
565 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
566 case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
567 case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
568 case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
570 EmitEOL();
573 void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
574 assert(!Options.empty() && "At least one option is required!");
575 OS << "\t.linker_option \"" << Options[0] << '"';
576 for (const std::string &Opt : llvm::drop_begin(Options))
577 OS << ", " << '"' << Opt << '"';
578 EmitEOL();
581 void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
582 if (!MAI->doesSupportDataRegionDirectives())
583 return;
584 switch (Kind) {
585 case MCDR_DataRegion: OS << "\t.data_region"; break;
586 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
587 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
588 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
589 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
591 EmitEOL();
594 static const char *getVersionMinDirective(MCVersionMinType Type) {
595 switch (Type) {
596 case MCVM_WatchOSVersionMin: return ".watchos_version_min";
597 case MCVM_TvOSVersionMin: return ".tvos_version_min";
598 case MCVM_IOSVersionMin: return ".ios_version_min";
599 case MCVM_OSXVersionMin: return ".macosx_version_min";
601 llvm_unreachable("Invalid MC version min type");
604 static void EmitSDKVersionSuffix(raw_ostream &OS,
605 const VersionTuple &SDKVersion) {
606 if (SDKVersion.empty())
607 return;
608 OS << '\t' << "sdk_version " << SDKVersion.getMajor();
609 if (auto Minor = SDKVersion.getMinor()) {
610 OS << ", " << *Minor;
611 if (auto Subminor = SDKVersion.getSubminor()) {
612 OS << ", " << *Subminor;
617 void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
618 unsigned Minor, unsigned Update,
619 VersionTuple SDKVersion) {
620 OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
621 if (Update)
622 OS << ", " << Update;
623 EmitSDKVersionSuffix(OS, SDKVersion);
624 EmitEOL();
627 static const char *getPlatformName(MachO::PlatformType Type) {
628 switch (Type) {
629 case MachO::PLATFORM_UNKNOWN: /* silence warning*/
630 break;
631 case MachO::PLATFORM_MACOS: return "macos";
632 case MachO::PLATFORM_IOS: return "ios";
633 case MachO::PLATFORM_TVOS: return "tvos";
634 case MachO::PLATFORM_WATCHOS: return "watchos";
635 case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
636 case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
637 case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
638 case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
639 case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
640 case MachO::PLATFORM_DRIVERKIT: return "driverkit";
642 llvm_unreachable("Invalid Mach-O platform type");
645 void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
646 unsigned Minor, unsigned Update,
647 VersionTuple SDKVersion) {
648 const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
649 OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
650 if (Update)
651 OS << ", " << Update;
652 EmitSDKVersionSuffix(OS, SDKVersion);
653 EmitEOL();
656 void MCAsmStreamer::emitDarwinTargetVariantBuildVersion(
657 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,
658 VersionTuple SDKVersion) {
659 emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
662 void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
663 // This needs to emit to a temporary string to get properly quoted
664 // MCSymbols when they have spaces in them.
665 OS << "\t.thumb_func";
666 // Only Mach-O hasSubsectionsViaSymbols()
667 if (MAI->hasSubsectionsViaSymbols()) {
668 OS << '\t';
669 Func->print(OS, MAI);
671 EmitEOL();
674 void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
675 // Do not emit a .set on inlined target assignments.
676 bool EmitSet = true;
677 if (auto *E = dyn_cast<MCTargetExpr>(Value))
678 if (E->inlineAssignedExpr())
679 EmitSet = false;
680 if (EmitSet) {
681 OS << ".set ";
682 Symbol->print(OS, MAI);
683 OS << ", ";
684 Value->print(OS, MAI);
686 EmitEOL();
689 MCStreamer::emitAssignment(Symbol, Value);
692 void MCAsmStreamer::emitConditionalAssignment(MCSymbol *Symbol,
693 const MCExpr *Value) {
694 OS << ".lto_set_conditional ";
695 Symbol->print(OS, MAI);
696 OS << ", ";
697 Value->print(OS, MAI);
698 EmitEOL();
701 void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
702 OS << ".weakref ";
703 Alias->print(OS, MAI);
704 OS << ", ";
705 Symbol->print(OS, MAI);
706 EmitEOL();
709 bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
710 MCSymbolAttr Attribute) {
711 switch (Attribute) {
712 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
713 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
714 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
715 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
716 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
717 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
718 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
719 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
720 if (!MAI->hasDotTypeDotSizeDirective())
721 return false; // Symbol attribute not supported
722 OS << "\t.type\t";
723 Symbol->print(OS, MAI);
724 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
725 switch (Attribute) {
726 default: return false;
727 case MCSA_ELF_TypeFunction: OS << "function"; break;
728 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
729 case MCSA_ELF_TypeObject: OS << "object"; break;
730 case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
731 case MCSA_ELF_TypeCommon: OS << "common"; break;
732 case MCSA_ELF_TypeNoType: OS << "notype"; break;
733 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
735 EmitEOL();
736 return true;
737 case MCSA_Global: // .globl/.global
738 OS << MAI->getGlobalDirective();
739 break;
740 case MCSA_LGlobal: OS << "\t.lglobl\t"; break;
741 case MCSA_Hidden: OS << "\t.hidden\t"; break;
742 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
743 case MCSA_Internal: OS << "\t.internal\t"; break;
744 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
745 case MCSA_Local: OS << "\t.local\t"; break;
746 case MCSA_NoDeadStrip:
747 if (!MAI->hasNoDeadStrip())
748 return false;
749 OS << "\t.no_dead_strip\t";
750 break;
751 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
752 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
753 case MCSA_PrivateExtern:
754 OS << "\t.private_extern\t";
755 break;
756 case MCSA_Protected: OS << "\t.protected\t"; break;
757 case MCSA_Reference: OS << "\t.reference\t"; break;
758 case MCSA_Extern:
759 OS << "\t.extern\t";
760 break;
761 case MCSA_Weak: OS << MAI->getWeakDirective(); break;
762 case MCSA_WeakDefinition:
763 OS << "\t.weak_definition\t";
764 break;
765 // .weak_reference
766 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
767 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
768 case MCSA_Cold:
769 // Assemblers currently do not support a .cold directive.
770 case MCSA_Exported:
771 // Non-AIX assemblers currently do not support exported visibility.
772 return false;
773 case MCSA_Memtag:
774 OS << "\t.memtag\t";
775 break;
778 Symbol->print(OS, MAI);
779 EmitEOL();
781 return true;
784 void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
785 OS << ".desc" << ' ';
786 Symbol->print(OS, MAI);
787 OS << ',' << DescValue;
788 EmitEOL();
791 void MCAsmStreamer::emitSyntaxDirective() {
792 if (MAI->getAssemblerDialect() == 1) {
793 OS << "\t.intel_syntax noprefix";
794 EmitEOL();
796 // FIXME: Currently emit unprefix'ed registers.
797 // The intel_syntax directive has one optional argument
798 // with may have a value of prefix or noprefix.
801 void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
802 OS << "\t.def\t";
803 Symbol->print(OS, MAI);
804 OS << ';';
805 EmitEOL();
808 void MCAsmStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
809 OS << "\t.scl\t" << StorageClass << ';';
810 EmitEOL();
813 void MCAsmStreamer::emitCOFFSymbolType(int Type) {
814 OS << "\t.type\t" << Type << ';';
815 EmitEOL();
818 void MCAsmStreamer::endCOFFSymbolDef() {
819 OS << "\t.endef";
820 EmitEOL();
823 void MCAsmStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {
824 OS << "\t.safeseh\t";
825 Symbol->print(OS, MAI);
826 EmitEOL();
829 void MCAsmStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
830 OS << "\t.symidx\t";
831 Symbol->print(OS, MAI);
832 EmitEOL();
835 void MCAsmStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {
836 OS << "\t.secidx\t";
837 Symbol->print(OS, MAI);
838 EmitEOL();
841 void MCAsmStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
842 OS << "\t.secrel32\t";
843 Symbol->print(OS, MAI);
844 if (Offset != 0)
845 OS << '+' << Offset;
846 EmitEOL();
849 void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
850 OS << "\t.rva\t";
851 Symbol->print(OS, MAI);
852 if (Offset > 0)
853 OS << '+' << Offset;
854 else if (Offset < 0)
855 OS << '-' << -Offset;
856 EmitEOL();
859 // We need an XCOFF-specific version of this directive as the AIX syntax
860 // requires a QualName argument identifying the csect name and storage mapping
861 // class to appear before the alignment if we are specifying it.
862 void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
863 uint64_t Size,
864 MCSymbol *CsectSym,
865 Align Alignment) {
866 assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
867 "We only support writing log base-2 alignment format with XCOFF.");
869 OS << "\t.lcomm\t";
870 LabelSym->print(OS, MAI);
871 OS << ',' << Size << ',';
872 CsectSym->print(OS, MAI);
873 OS << ',' << Log2(Alignment);
875 EmitEOL();
877 // Print symbol's rename (original name contains invalid character(s)) if
878 // there is one.
879 MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
880 if (XSym->hasRename())
881 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
884 void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
885 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
887 switch (Linkage) {
888 case MCSA_Global:
889 OS << MAI->getGlobalDirective();
890 break;
891 case MCSA_Weak:
892 OS << MAI->getWeakDirective();
893 break;
894 case MCSA_Extern:
895 OS << "\t.extern\t";
896 break;
897 case MCSA_LGlobal:
898 OS << "\t.lglobl\t";
899 break;
900 default:
901 report_fatal_error("unhandled linkage type");
904 Symbol->print(OS, MAI);
906 switch (Visibility) {
907 case MCSA_Invalid:
908 // Nothing to do.
909 break;
910 case MCSA_Hidden:
911 OS << ",hidden";
912 break;
913 case MCSA_Protected:
914 OS << ",protected";
915 break;
916 case MCSA_Exported:
917 OS << ",exported";
918 break;
919 default:
920 report_fatal_error("unexpected value for Visibility type");
922 EmitEOL();
924 // Print symbol's rename (original name contains invalid character(s)) if
925 // there is one.
926 if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
927 emitXCOFFRenameDirective(Symbol,
928 cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
931 void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
932 StringRef Rename) {
933 OS << "\t.rename\t";
934 Name->print(OS, MAI);
935 const char DQ = '"';
936 OS << ',' << DQ;
937 for (char C : Rename) {
938 // To escape a double quote character, the character should be doubled.
939 if (C == DQ)
940 OS << DQ;
941 OS << C;
943 OS << DQ;
944 EmitEOL();
947 void MCAsmStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
948 OS << "\t.ref ";
949 Symbol->print(OS, MAI);
950 EmitEOL();
953 void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
954 const MCSymbol *Trap,
955 unsigned Lang,
956 unsigned Reason,
957 unsigned FunctionSize,
958 bool hasDebug) {
959 OS << "\t.except\t";
960 Symbol->print(OS, MAI);
961 OS << ", " << Lang << ", " << Reason;
962 EmitEOL();
965 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
966 assert(MAI->hasDotTypeDotSizeDirective());
967 OS << "\t.size\t";
968 Symbol->print(OS, MAI);
969 OS << ", ";
970 Value->print(OS, MAI);
971 EmitEOL();
974 void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
975 Align ByteAlignment) {
976 OS << "\t.comm\t";
977 Symbol->print(OS, MAI);
978 OS << ',' << Size;
980 if (MAI->getCOMMDirectiveAlignmentIsInBytes())
981 OS << ',' << ByteAlignment.value();
982 else
983 OS << ',' << Log2(ByteAlignment);
984 EmitEOL();
986 // Print symbol's rename (original name contains invalid character(s)) if
987 // there is one.
988 MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
989 if (XSym && XSym->hasRename())
990 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
993 void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
994 Align ByteAlign) {
995 OS << "\t.lcomm\t";
996 Symbol->print(OS, MAI);
997 OS << ',' << Size;
999 if (ByteAlign > 1) {
1000 switch (MAI->getLCOMMDirectiveAlignmentType()) {
1001 case LCOMM::NoAlignment:
1002 llvm_unreachable("alignment not supported on .lcomm!");
1003 case LCOMM::ByteAlignment:
1004 OS << ',' << ByteAlign.value();
1005 break;
1006 case LCOMM::Log2Alignment:
1007 OS << ',' << Log2(ByteAlign);
1008 break;
1011 EmitEOL();
1014 void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
1015 uint64_t Size, Align ByteAlignment,
1016 SMLoc Loc) {
1017 if (Symbol)
1018 assignFragment(Symbol, &Section->getDummyFragment());
1020 // Note: a .zerofill directive does not switch sections.
1021 OS << ".zerofill ";
1023 assert(Section->getVariant() == MCSection::SV_MachO &&
1024 ".zerofill is a Mach-O specific directive");
1025 // This is a mach-o specific directive.
1027 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
1028 OS << MOSection->getSegmentName() << "," << MOSection->getName();
1030 if (Symbol) {
1031 OS << ',';
1032 Symbol->print(OS, MAI);
1033 OS << ',' << Size;
1034 OS << ',' << Log2(ByteAlignment);
1036 EmitEOL();
1039 // .tbss sym, size, align
1040 // This depends that the symbol has already been mangled from the original,
1041 // e.g. _a.
1042 void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1043 uint64_t Size, Align ByteAlignment) {
1044 assignFragment(Symbol, &Section->getDummyFragment());
1046 assert(Symbol && "Symbol shouldn't be NULL!");
1047 // Instead of using the Section we'll just use the shortcut.
1049 assert(Section->getVariant() == MCSection::SV_MachO &&
1050 ".zerofill is a Mach-O specific directive");
1051 // This is a mach-o specific directive and section.
1053 OS << ".tbss ";
1054 Symbol->print(OS, MAI);
1055 OS << ", " << Size;
1057 // Output align if we have it. We default to 1 so don't bother printing
1058 // that.
1059 if (ByteAlignment > 1)
1060 OS << ", " << Log2(ByteAlignment);
1062 EmitEOL();
1065 static inline bool isPrintableString(StringRef Data) {
1066 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1067 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1068 if (!isPrint(C))
1069 return false;
1071 return isPrint(Data.back()) || Data.back() == 0;
1074 static inline char toOctal(int X) { return (X&7)+'0'; }
1076 static void PrintByteList(StringRef Data, raw_ostream &OS,
1077 MCAsmInfo::AsmCharLiteralSyntax ACLS) {
1078 assert(!Data.empty() && "Cannot generate an empty list.");
1079 const auto printCharacterInOctal = [&OS](unsigned char C) {
1080 OS << '0';
1081 OS << toOctal(C >> 6);
1082 OS << toOctal(C >> 3);
1083 OS << toOctal(C >> 0);
1085 const auto printOneCharacterFor = [printCharacterInOctal](
1086 auto printOnePrintingCharacter) {
1087 return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
1088 if (isPrint(C)) {
1089 printOnePrintingCharacter(static_cast<char>(C));
1090 return;
1092 printCharacterInOctal(C);
1095 const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1096 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1097 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1098 printOneCharacter(C);
1099 OS << ',';
1101 printOneCharacter(*(EndPtr - 1));
1103 switch (ACLS) {
1104 case MCAsmInfo::ACLS_Unknown:
1105 printCharacterList(printCharacterInOctal);
1106 return;
1107 case MCAsmInfo::ACLS_SingleQuotePrefix:
1108 printCharacterList(printOneCharacterFor([&OS](char C) {
1109 const char AsmCharLitBuf[2] = {'\'', C};
1110 OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1111 }));
1112 return;
1114 llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
1117 void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {
1118 OS << '"';
1120 if (MAI->hasPairedDoubleQuoteStringConstants()) {
1121 for (unsigned char C : Data) {
1122 if (C == '"')
1123 OS << "\"\"";
1124 else
1125 OS << (char)C;
1127 } else {
1128 for (unsigned char C : Data) {
1129 if (C == '"' || C == '\\') {
1130 OS << '\\' << (char)C;
1131 continue;
1134 if (isPrint((unsigned char)C)) {
1135 OS << (char)C;
1136 continue;
1139 switch (C) {
1140 case '\b':
1141 OS << "\\b";
1142 break;
1143 case '\f':
1144 OS << "\\f";
1145 break;
1146 case '\n':
1147 OS << "\\n";
1148 break;
1149 case '\r':
1150 OS << "\\r";
1151 break;
1152 case '\t':
1153 OS << "\\t";
1154 break;
1155 default:
1156 OS << '\\';
1157 OS << toOctal(C >> 6);
1158 OS << toOctal(C >> 3);
1159 OS << toOctal(C >> 0);
1160 break;
1165 OS << '"';
1168 void MCAsmStreamer::emitBytes(StringRef Data) {
1169 assert(getCurrentSectionOnly() &&
1170 "Cannot emit contents before setting section!");
1171 if (Data.empty()) return;
1173 const auto emitAsString = [this](StringRef Data) {
1174 // If the data ends with 0 and the target supports .asciz, use it, otherwise
1175 // use .ascii or a byte-list directive
1176 if (MAI->getAscizDirective() && Data.back() == 0) {
1177 OS << MAI->getAscizDirective();
1178 Data = Data.substr(0, Data.size() - 1);
1179 } else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
1180 OS << MAI->getAsciiDirective();
1181 } else if (MAI->hasPairedDoubleQuoteStringConstants() &&
1182 isPrintableString(Data)) {
1183 // For target with DoubleQuoteString constants, .string and .byte are used
1184 // as replacement of .asciz and .ascii.
1185 assert(MAI->getPlainStringDirective() &&
1186 "hasPairedDoubleQuoteStringConstants target must support "
1187 "PlainString Directive");
1188 assert(MAI->getByteListDirective() &&
1189 "hasPairedDoubleQuoteStringConstants target must support ByteList "
1190 "Directive");
1191 if (Data.back() == 0) {
1192 OS << MAI->getPlainStringDirective();
1193 Data = Data.substr(0, Data.size() - 1);
1194 } else {
1195 OS << MAI->getByteListDirective();
1197 } else if (MAI->getByteListDirective()) {
1198 OS << MAI->getByteListDirective();
1199 PrintByteList(Data, OS, MAI->characterLiteralSyntax());
1200 EmitEOL();
1201 return true;
1202 } else {
1203 return false;
1206 PrintQuotedString(Data, OS);
1207 EmitEOL();
1208 return true;
1211 if (Data.size() != 1 && emitAsString(Data))
1212 return;
1214 // Only single byte is provided or no ascii, asciz, or byte-list directives
1215 // are applicable. Emit as vector of individual 8bits data elements.
1216 if (MCTargetStreamer *TS = getTargetStreamer()) {
1217 TS->emitRawBytes(Data);
1218 return;
1220 const char *Directive = MAI->getData8bitsDirective();
1221 for (const unsigned char C : Data.bytes()) {
1222 OS << Directive << (unsigned)C;
1223 EmitEOL();
1227 void MCAsmStreamer::emitBinaryData(StringRef Data) {
1228 // This is binary data. Print it in a grid of hex bytes for readability.
1229 const size_t Cols = 4;
1230 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
1231 size_t J = I, EJ = std::min(I + Cols, Data.size());
1232 assert(EJ > 0);
1233 OS << MAI->getData8bitsDirective();
1234 for (; J < EJ - 1; ++J)
1235 OS << format("0x%02x", uint8_t(Data[J])) << ", ";
1236 OS << format("0x%02x", uint8_t(Data[J]));
1237 EmitEOL();
1241 void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1242 emitValue(MCConstantExpr::create(Value, getContext()), Size);
1245 void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
1246 emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
1249 void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
1250 unsigned Size) {
1251 emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
1254 void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1255 SMLoc Loc) {
1256 assert(Size <= 8 && "Invalid size");
1257 assert(getCurrentSectionOnly() &&
1258 "Cannot emit contents before setting section!");
1259 const char *Directive = nullptr;
1260 switch (Size) {
1261 default: break;
1262 case 1: Directive = MAI->getData8bitsDirective(); break;
1263 case 2: Directive = MAI->getData16bitsDirective(); break;
1264 case 4: Directive = MAI->getData32bitsDirective(); break;
1265 case 8: Directive = MAI->getData64bitsDirective(); break;
1268 if (!Directive) {
1269 int64_t IntValue;
1270 if (!Value->evaluateAsAbsolute(IntValue))
1271 report_fatal_error("Don't know how to emit this value.");
1273 // We couldn't handle the requested integer size so we fallback by breaking
1274 // the request down into several, smaller, integers.
1275 // Since sizes greater or equal to "Size" are invalid, we use the greatest
1276 // power of 2 that is less than "Size" as our largest piece of granularity.
1277 bool IsLittleEndian = MAI->isLittleEndian();
1278 for (unsigned Emitted = 0; Emitted != Size;) {
1279 unsigned Remaining = Size - Emitted;
1280 // The size of our partial emission must be a power of two less than
1281 // Size.
1282 unsigned EmissionSize = llvm::bit_floor(std::min(Remaining, Size - 1));
1283 // Calculate the byte offset of our partial emission taking into account
1284 // the endianness of the target.
1285 unsigned ByteOffset =
1286 IsLittleEndian ? Emitted : (Remaining - EmissionSize);
1287 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
1288 // We truncate our partial emission to fit within the bounds of the
1289 // emission domain. This produces nicer output and silences potential
1290 // truncation warnings when round tripping through another assembler.
1291 uint64_t Shift = 64 - EmissionSize * 8;
1292 assert(Shift < static_cast<uint64_t>(
1293 std::numeric_limits<unsigned long long>::digits) &&
1294 "undefined behavior");
1295 ValueToEmit &= ~0ULL >> Shift;
1296 emitIntValue(ValueToEmit, EmissionSize);
1297 Emitted += EmissionSize;
1299 return;
1302 assert(Directive && "Invalid size for machine code value!");
1303 OS << Directive;
1304 if (MCTargetStreamer *TS = getTargetStreamer()) {
1305 TS->emitValue(Value);
1306 } else {
1307 Value->print(OS, MAI);
1308 EmitEOL();
1312 void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
1313 int64_t IntValue;
1314 if (Value->evaluateAsAbsolute(IntValue)) {
1315 emitULEB128IntValue(IntValue);
1316 return;
1318 OS << "\t.uleb128 ";
1319 Value->print(OS, MAI);
1320 EmitEOL();
1323 void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
1324 int64_t IntValue;
1325 if (Value->evaluateAsAbsolute(IntValue)) {
1326 emitSLEB128IntValue(IntValue);
1327 return;
1329 OS << "\t.sleb128 ";
1330 Value->print(OS, MAI);
1331 EmitEOL();
1334 void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
1335 assert(MAI->getDTPRel64Directive() != nullptr);
1336 OS << MAI->getDTPRel64Directive();
1337 Value->print(OS, MAI);
1338 EmitEOL();
1341 void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
1342 assert(MAI->getDTPRel32Directive() != nullptr);
1343 OS << MAI->getDTPRel32Directive();
1344 Value->print(OS, MAI);
1345 EmitEOL();
1348 void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
1349 assert(MAI->getTPRel64Directive() != nullptr);
1350 OS << MAI->getTPRel64Directive();
1351 Value->print(OS, MAI);
1352 EmitEOL();
1355 void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
1356 assert(MAI->getTPRel32Directive() != nullptr);
1357 OS << MAI->getTPRel32Directive();
1358 Value->print(OS, MAI);
1359 EmitEOL();
1362 void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
1363 assert(MAI->getGPRel64Directive() != nullptr);
1364 OS << MAI->getGPRel64Directive();
1365 Value->print(OS, MAI);
1366 EmitEOL();
1369 void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
1370 assert(MAI->getGPRel32Directive() != nullptr);
1371 OS << MAI->getGPRel32Directive();
1372 Value->print(OS, MAI);
1373 EmitEOL();
1376 void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1377 SMLoc Loc) {
1378 int64_t IntNumBytes;
1379 const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
1380 if (IsAbsolute && IntNumBytes == 0)
1381 return;
1383 if (const char *ZeroDirective = MAI->getZeroDirective()) {
1384 if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
1385 // FIXME: Emit location directives
1386 OS << ZeroDirective;
1387 NumBytes.print(OS, MAI);
1388 if (FillValue != 0)
1389 OS << ',' << (int)FillValue;
1390 EmitEOL();
1391 } else {
1392 if (!IsAbsolute)
1393 report_fatal_error(
1394 "Cannot emit non-absolute expression lengths of fill.");
1395 for (int i = 0; i < IntNumBytes; ++i) {
1396 OS << MAI->getData8bitsDirective() << (int)FillValue;
1397 EmitEOL();
1400 return;
1403 MCStreamer::emitFill(NumBytes, FillValue);
1406 void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1407 int64_t Expr, SMLoc Loc) {
1408 // FIXME: Emit location directives
1409 OS << "\t.fill\t";
1410 NumValues.print(OS, MAI);
1411 OS << ", " << Size << ", 0x";
1412 OS.write_hex(truncateToSize(Expr, 4));
1413 EmitEOL();
1416 void MCAsmStreamer::emitAlignmentDirective(unsigned ByteAlignment,
1417 std::optional<int64_t> Value,
1418 unsigned ValueSize,
1419 unsigned MaxBytesToEmit) {
1420 if (MAI->useDotAlignForAlignment()) {
1421 if (!isPowerOf2_32(ByteAlignment))
1422 report_fatal_error("Only power-of-two alignments are supported "
1423 "with .align.");
1424 OS << "\t.align\t";
1425 OS << Log2_32(ByteAlignment);
1426 EmitEOL();
1427 return;
1430 // Some assemblers don't support non-power of two alignments, so we always
1431 // emit alignments as a power of two if possible.
1432 if (isPowerOf2_32(ByteAlignment)) {
1433 switch (ValueSize) {
1434 default:
1435 llvm_unreachable("Invalid size for machine code value!");
1436 case 1:
1437 OS << "\t.p2align\t";
1438 break;
1439 case 2:
1440 OS << ".p2alignw ";
1441 break;
1442 case 4:
1443 OS << ".p2alignl ";
1444 break;
1445 case 8:
1446 llvm_unreachable("Unsupported alignment size!");
1449 OS << Log2_32(ByteAlignment);
1451 if (Value.has_value() || MaxBytesToEmit) {
1452 if (Value.has_value()) {
1453 OS << ", 0x";
1454 OS.write_hex(truncateToSize(*Value, ValueSize));
1455 } else {
1456 OS << ", ";
1459 if (MaxBytesToEmit)
1460 OS << ", " << MaxBytesToEmit;
1462 EmitEOL();
1463 return;
1466 // Non-power of two alignment. This is not widely supported by assemblers.
1467 // FIXME: Parameterize this based on MAI.
1468 switch (ValueSize) {
1469 default: llvm_unreachable("Invalid size for machine code value!");
1470 case 1: OS << ".balign"; break;
1471 case 2: OS << ".balignw"; break;
1472 case 4: OS << ".balignl"; break;
1473 case 8: llvm_unreachable("Unsupported alignment size!");
1476 OS << ' ' << ByteAlignment;
1477 if (Value.has_value())
1478 OS << ", " << truncateToSize(*Value, ValueSize);
1479 else if (MaxBytesToEmit)
1480 OS << ", ";
1481 if (MaxBytesToEmit)
1482 OS << ", " << MaxBytesToEmit;
1483 EmitEOL();
1486 void MCAsmStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
1487 unsigned ValueSize,
1488 unsigned MaxBytesToEmit) {
1489 emitAlignmentDirective(Alignment.value(), Value, ValueSize, MaxBytesToEmit);
1492 void MCAsmStreamer::emitCodeAlignment(Align Alignment,
1493 const MCSubtargetInfo *STI,
1494 unsigned MaxBytesToEmit) {
1495 // Emit with a text fill value.
1496 if (MAI->getTextAlignFillValue())
1497 emitAlignmentDirective(Alignment.value(), MAI->getTextAlignFillValue(), 1,
1498 MaxBytesToEmit);
1499 else
1500 emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
1503 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1504 unsigned char Value,
1505 SMLoc Loc) {
1506 // FIXME: Verify that Offset is associated with the current section.
1507 OS << ".org ";
1508 Offset->print(OS, MAI);
1509 OS << ", " << (unsigned)Value;
1510 EmitEOL();
1513 void MCAsmStreamer::emitFileDirective(StringRef Filename) {
1514 assert(MAI->hasSingleParameterDotFile());
1515 OS << "\t.file\t";
1516 PrintQuotedString(Filename, OS);
1517 EmitEOL();
1520 void MCAsmStreamer::emitFileDirective(StringRef Filename,
1521 StringRef CompilerVerion,
1522 StringRef TimeStamp,
1523 StringRef Description) {
1524 assert(MAI->hasFourStringsDotFile());
1525 OS << "\t.file\t";
1526 PrintQuotedString(Filename, OS);
1527 OS << ",";
1528 if (!CompilerVerion.empty()) {
1529 PrintQuotedString(CompilerVerion, OS);
1531 if (!TimeStamp.empty()) {
1532 OS << ",";
1533 PrintQuotedString(TimeStamp, OS);
1535 if (!Description.empty()) {
1536 OS << ",";
1537 PrintQuotedString(Description, OS);
1539 EmitEOL();
1542 void MCAsmStreamer::printDwarfFileDirective(
1543 unsigned FileNo, StringRef Directory, StringRef Filename,
1544 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1545 bool UseDwarfDirectory, raw_svector_ostream &OS) const {
1546 SmallString<128> FullPathName;
1548 if (!UseDwarfDirectory && !Directory.empty()) {
1549 if (sys::path::is_absolute(Filename))
1550 Directory = "";
1551 else {
1552 FullPathName = Directory;
1553 sys::path::append(FullPathName, Filename);
1554 Directory = "";
1555 Filename = FullPathName;
1559 OS << "\t.file\t" << FileNo << ' ';
1560 if (!Directory.empty()) {
1561 PrintQuotedString(Directory, OS);
1562 OS << ' ';
1564 PrintQuotedString(Filename, OS);
1565 if (Checksum)
1566 OS << " md5 0x" << Checksum->digest();
1567 if (Source) {
1568 OS << " source ";
1569 PrintQuotedString(*Source, OS);
1573 Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1574 unsigned FileNo, StringRef Directory, StringRef Filename,
1575 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1576 unsigned CUID) {
1577 assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
1579 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1580 unsigned NumFiles = Table.getMCDwarfFiles().size();
1581 Expected<unsigned> FileNoOrErr =
1582 Table.tryGetFile(Directory, Filename, Checksum, Source,
1583 getContext().getDwarfVersion(), FileNo);
1584 if (!FileNoOrErr)
1585 return FileNoOrErr.takeError();
1586 FileNo = FileNoOrErr.get();
1588 // Return early if this file is already emitted before or if target doesn't
1589 // support .file directive.
1590 if (NumFiles == Table.getMCDwarfFiles().size() ||
1591 !MAI->usesDwarfFileAndLocDirectives())
1592 return FileNo;
1594 SmallString<128> Str;
1595 raw_svector_ostream OS1(Str);
1596 printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1597 UseDwarfDirectory, OS1);
1599 if (MCTargetStreamer *TS = getTargetStreamer())
1600 TS->emitDwarfFileDirective(OS1.str());
1601 else
1602 emitRawText(OS1.str());
1604 return FileNo;
1607 void MCAsmStreamer::emitDwarfFile0Directive(
1608 StringRef Directory, StringRef Filename,
1609 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1610 unsigned CUID) {
1611 assert(CUID == 0);
1612 // .file 0 is new for DWARF v5.
1613 if (getContext().getDwarfVersion() < 5)
1614 return;
1615 // Inform MCDwarf about the root file.
1616 getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1617 Source);
1619 // Target doesn't support .loc/.file directives, return early.
1620 if (!MAI->usesDwarfFileAndLocDirectives())
1621 return;
1623 SmallString<128> Str;
1624 raw_svector_ostream OS1(Str);
1625 printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1626 UseDwarfDirectory, OS1);
1628 if (MCTargetStreamer *TS = getTargetStreamer())
1629 TS->emitDwarfFileDirective(OS1.str());
1630 else
1631 emitRawText(OS1.str());
1634 void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
1635 unsigned Column, unsigned Flags,
1636 unsigned Isa, unsigned Discriminator,
1637 StringRef FileName) {
1638 // If target doesn't support .loc/.file directive, we need to record the lines
1639 // same way like we do in object mode.
1640 if (!MAI->usesDwarfFileAndLocDirectives()) {
1641 // In case we see two .loc directives in a row, make sure the
1642 // first one gets a line entry.
1643 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1644 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1645 Discriminator, FileName);
1646 return;
1649 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1650 if (MAI->supportsExtendedDwarfLocDirective()) {
1651 if (Flags & DWARF2_FLAG_BASIC_BLOCK)
1652 OS << " basic_block";
1653 if (Flags & DWARF2_FLAG_PROLOGUE_END)
1654 OS << " prologue_end";
1655 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
1656 OS << " epilogue_begin";
1658 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1659 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
1660 OS << " is_stmt ";
1662 if (Flags & DWARF2_FLAG_IS_STMT)
1663 OS << "1";
1664 else
1665 OS << "0";
1668 if (Isa)
1669 OS << " isa " << Isa;
1670 if (Discriminator)
1671 OS << " discriminator " << Discriminator;
1674 if (IsVerboseAsm) {
1675 OS.PadToColumn(MAI->getCommentColumn());
1676 OS << MAI->getCommentString() << ' ' << FileName << ':'
1677 << Line << ':' << Column;
1679 EmitEOL();
1680 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1681 Discriminator, FileName);
1684 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1685 // Always use the zeroth line table, since asm syntax only supports one line
1686 // table for now.
1687 return MCStreamer::getDwarfLineTableSymbol(0);
1690 bool MCAsmStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
1691 ArrayRef<uint8_t> Checksum,
1692 unsigned ChecksumKind) {
1693 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1694 ChecksumKind))
1695 return false;
1697 OS << "\t.cv_file\t" << FileNo << ' ';
1698 PrintQuotedString(Filename, OS);
1700 if (!ChecksumKind) {
1701 EmitEOL();
1702 return true;
1705 OS << ' ';
1706 PrintQuotedString(toHex(Checksum), OS);
1707 OS << ' ' << ChecksumKind;
1709 EmitEOL();
1710 return true;
1713 bool MCAsmStreamer::emitCVFuncIdDirective(unsigned FuncId) {
1714 OS << "\t.cv_func_id " << FuncId << '\n';
1715 return MCStreamer::emitCVFuncIdDirective(FuncId);
1718 bool MCAsmStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,
1719 unsigned IAFunc,
1720 unsigned IAFile,
1721 unsigned IALine, unsigned IACol,
1722 SMLoc Loc) {
1723 OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1724 << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1725 return MCStreamer::emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
1726 IALine, IACol, Loc);
1729 void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1730 unsigned Line, unsigned Column,
1731 bool PrologueEnd, bool IsStmt,
1732 StringRef FileName, SMLoc Loc) {
1733 // Validate the directive.
1734 if (!checkCVLocSection(FunctionId, FileNo, Loc))
1735 return;
1737 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1738 << Column;
1739 if (PrologueEnd)
1740 OS << " prologue_end";
1742 if (IsStmt)
1743 OS << " is_stmt 1";
1745 if (IsVerboseAsm) {
1746 OS.PadToColumn(MAI->getCommentColumn());
1747 OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1748 << Column;
1750 EmitEOL();
1753 void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
1754 const MCSymbol *FnStart,
1755 const MCSymbol *FnEnd) {
1756 OS << "\t.cv_linetable\t" << FunctionId << ", ";
1757 FnStart->print(OS, MAI);
1758 OS << ", ";
1759 FnEnd->print(OS, MAI);
1760 EmitEOL();
1761 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
1764 void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
1765 unsigned SourceFileId,
1766 unsigned SourceLineNum,
1767 const MCSymbol *FnStartSym,
1768 const MCSymbol *FnEndSym) {
1769 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
1770 << ' ' << SourceLineNum << ' ';
1771 FnStartSym->print(OS, MAI);
1772 OS << ' ';
1773 FnEndSym->print(OS, MAI);
1774 EmitEOL();
1775 this->MCStreamer::emitCVInlineLinetableDirective(
1776 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
1779 void MCAsmStreamer::PrintCVDefRangePrefix(
1780 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
1781 OS << "\t.cv_def_range\t";
1782 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
1783 OS << ' ';
1784 Range.first->print(OS, MAI);
1785 OS << ' ';
1786 Range.second->print(OS, MAI);
1790 void MCAsmStreamer::emitCVDefRangeDirective(
1791 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1792 codeview::DefRangeRegisterRelHeader DRHdr) {
1793 PrintCVDefRangePrefix(Ranges);
1794 OS << ", reg_rel, ";
1795 OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
1796 << DRHdr.BasePointerOffset;
1797 EmitEOL();
1800 void MCAsmStreamer::emitCVDefRangeDirective(
1801 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1802 codeview::DefRangeSubfieldRegisterHeader DRHdr) {
1803 PrintCVDefRangePrefix(Ranges);
1804 OS << ", subfield_reg, ";
1805 OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
1806 EmitEOL();
1809 void MCAsmStreamer::emitCVDefRangeDirective(
1810 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1811 codeview::DefRangeRegisterHeader DRHdr) {
1812 PrintCVDefRangePrefix(Ranges);
1813 OS << ", reg, ";
1814 OS << DRHdr.Register;
1815 EmitEOL();
1818 void MCAsmStreamer::emitCVDefRangeDirective(
1819 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1820 codeview::DefRangeFramePointerRelHeader DRHdr) {
1821 PrintCVDefRangePrefix(Ranges);
1822 OS << ", frame_ptr_rel, ";
1823 OS << DRHdr.Offset;
1824 EmitEOL();
1827 void MCAsmStreamer::emitCVStringTableDirective() {
1828 OS << "\t.cv_stringtable";
1829 EmitEOL();
1832 void MCAsmStreamer::emitCVFileChecksumsDirective() {
1833 OS << "\t.cv_filechecksums";
1834 EmitEOL();
1837 void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
1838 OS << "\t.cv_filechecksumoffset\t" << FileNo;
1839 EmitEOL();
1842 void MCAsmStreamer::emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
1843 OS << "\t.cv_fpo_data\t";
1844 ProcSym->print(OS, MAI);
1845 EmitEOL();
1848 void MCAsmStreamer::emitIdent(StringRef IdentString) {
1849 assert(MAI->hasIdentDirective() && ".ident directive not supported");
1850 OS << "\t.ident\t";
1851 PrintQuotedString(IdentString, OS);
1852 EmitEOL();
1855 void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
1856 MCStreamer::emitCFISections(EH, Debug);
1857 OS << "\t.cfi_sections ";
1858 if (EH) {
1859 OS << ".eh_frame";
1860 if (Debug)
1861 OS << ", .debug_frame";
1862 } else if (Debug) {
1863 OS << ".debug_frame";
1866 EmitEOL();
1869 void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
1870 OS << "\t.cfi_startproc";
1871 if (Frame.IsSimple)
1872 OS << " simple";
1873 EmitEOL();
1876 void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1877 MCStreamer::emitCFIEndProcImpl(Frame);
1878 OS << "\t.cfi_endproc";
1879 EmitEOL();
1882 void MCAsmStreamer::EmitRegisterName(int64_t Register) {
1883 if (!MAI->useDwarfRegNumForCFI()) {
1884 // User .cfi_* directives can use arbitrary DWARF register numbers, not
1885 // just ones that map to LLVM register numbers and have known names.
1886 // Fall back to using the original number directly if no name is known.
1887 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1888 if (std::optional<unsigned> LLVMRegister =
1889 MRI->getLLVMRegNum(Register, true)) {
1890 InstPrinter->printRegName(OS, *LLVMRegister);
1891 return;
1894 OS << Register;
1897 void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
1898 MCStreamer::emitCFIDefCfa(Register, Offset);
1899 OS << "\t.cfi_def_cfa ";
1900 EmitRegisterName(Register);
1901 OS << ", " << Offset;
1902 EmitEOL();
1905 void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
1906 MCStreamer::emitCFIDefCfaOffset(Offset);
1907 OS << "\t.cfi_def_cfa_offset " << Offset;
1908 EmitEOL();
1911 void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
1912 int64_t AddressSpace) {
1913 MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace);
1914 OS << "\t.cfi_llvm_def_aspace_cfa ";
1915 EmitRegisterName(Register);
1916 OS << ", " << Offset;
1917 OS << ", " << AddressSpace;
1918 EmitEOL();
1921 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
1922 OS << "\t.cfi_escape ";
1923 if (!Values.empty()) {
1924 size_t e = Values.size() - 1;
1925 for (size_t i = 0; i < e; ++i)
1926 OS << format("0x%02x", uint8_t(Values[i])) << ", ";
1927 OS << format("0x%02x", uint8_t(Values[e]));
1931 void MCAsmStreamer::emitCFIEscape(StringRef Values) {
1932 MCStreamer::emitCFIEscape(Values);
1933 PrintCFIEscape(OS, Values);
1934 EmitEOL();
1937 void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
1938 MCStreamer::emitCFIGnuArgsSize(Size);
1940 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
1941 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
1943 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
1944 EmitEOL();
1947 void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
1948 MCStreamer::emitCFIDefCfaRegister(Register);
1949 OS << "\t.cfi_def_cfa_register ";
1950 EmitRegisterName(Register);
1951 EmitEOL();
1954 void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
1955 this->MCStreamer::emitCFIOffset(Register, Offset);
1956 OS << "\t.cfi_offset ";
1957 EmitRegisterName(Register);
1958 OS << ", " << Offset;
1959 EmitEOL();
1962 void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
1963 unsigned Encoding) {
1964 MCStreamer::emitCFIPersonality(Sym, Encoding);
1965 OS << "\t.cfi_personality " << Encoding << ", ";
1966 Sym->print(OS, MAI);
1967 EmitEOL();
1970 void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1971 MCStreamer::emitCFILsda(Sym, Encoding);
1972 OS << "\t.cfi_lsda " << Encoding << ", ";
1973 Sym->print(OS, MAI);
1974 EmitEOL();
1977 void MCAsmStreamer::emitCFIRememberState() {
1978 MCStreamer::emitCFIRememberState();
1979 OS << "\t.cfi_remember_state";
1980 EmitEOL();
1983 void MCAsmStreamer::emitCFIRestoreState() {
1984 MCStreamer::emitCFIRestoreState();
1985 OS << "\t.cfi_restore_state";
1986 EmitEOL();
1989 void MCAsmStreamer::emitCFIRestore(int64_t Register) {
1990 MCStreamer::emitCFIRestore(Register);
1991 OS << "\t.cfi_restore ";
1992 EmitRegisterName(Register);
1993 EmitEOL();
1996 void MCAsmStreamer::emitCFISameValue(int64_t Register) {
1997 MCStreamer::emitCFISameValue(Register);
1998 OS << "\t.cfi_same_value ";
1999 EmitRegisterName(Register);
2000 EmitEOL();
2003 void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
2004 MCStreamer::emitCFIRelOffset(Register, Offset);
2005 OS << "\t.cfi_rel_offset ";
2006 EmitRegisterName(Register);
2007 OS << ", " << Offset;
2008 EmitEOL();
2011 void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
2012 MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
2013 OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
2014 EmitEOL();
2017 void MCAsmStreamer::emitCFISignalFrame() {
2018 MCStreamer::emitCFISignalFrame();
2019 OS << "\t.cfi_signal_frame";
2020 EmitEOL();
2023 void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
2024 MCStreamer::emitCFIUndefined(Register);
2025 OS << "\t.cfi_undefined ";
2026 EmitRegisterName(Register);
2027 EmitEOL();
2030 void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
2031 MCStreamer::emitCFIRegister(Register1, Register2);
2032 OS << "\t.cfi_register ";
2033 EmitRegisterName(Register1);
2034 OS << ", ";
2035 EmitRegisterName(Register2);
2036 EmitEOL();
2039 void MCAsmStreamer::emitCFIWindowSave() {
2040 MCStreamer::emitCFIWindowSave();
2041 OS << "\t.cfi_window_save";
2042 EmitEOL();
2045 void MCAsmStreamer::emitCFINegateRAState() {
2046 MCStreamer::emitCFINegateRAState();
2047 OS << "\t.cfi_negate_ra_state";
2048 EmitEOL();
2051 void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
2052 MCStreamer::emitCFIReturnColumn(Register);
2053 OS << "\t.cfi_return_column ";
2054 EmitRegisterName(Register);
2055 EmitEOL();
2058 void MCAsmStreamer::emitCFIBKeyFrame() {
2059 MCStreamer::emitCFIBKeyFrame();
2060 OS << "\t.cfi_b_key_frame";
2061 EmitEOL();
2064 void MCAsmStreamer::emitCFIMTETaggedFrame() {
2065 MCStreamer::emitCFIMTETaggedFrame();
2066 OS << "\t.cfi_mte_tagged_frame";
2067 EmitEOL();
2070 void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
2071 MCStreamer::emitWinCFIStartProc(Symbol, Loc);
2073 OS << ".seh_proc ";
2074 Symbol->print(OS, MAI);
2075 EmitEOL();
2078 void MCAsmStreamer::emitWinCFIEndProc(SMLoc Loc) {
2079 MCStreamer::emitWinCFIEndProc(Loc);
2081 OS << "\t.seh_endproc";
2082 EmitEOL();
2085 void MCAsmStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
2086 MCStreamer::emitWinCFIFuncletOrFuncEnd(Loc);
2088 OS << "\t.seh_endfunclet";
2089 EmitEOL();
2092 void MCAsmStreamer::emitWinCFIStartChained(SMLoc Loc) {
2093 MCStreamer::emitWinCFIStartChained(Loc);
2095 OS << "\t.seh_startchained";
2096 EmitEOL();
2099 void MCAsmStreamer::emitWinCFIEndChained(SMLoc Loc) {
2100 MCStreamer::emitWinCFIEndChained(Loc);
2102 OS << "\t.seh_endchained";
2103 EmitEOL();
2106 void MCAsmStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind,
2107 bool Except, SMLoc Loc) {
2108 MCStreamer::emitWinEHHandler(Sym, Unwind, Except, Loc);
2110 OS << "\t.seh_handler ";
2111 Sym->print(OS, MAI);
2112 char Marker = '@';
2113 const Triple &T = getContext().getTargetTriple();
2114 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
2115 Marker = '%';
2116 if (Unwind)
2117 OS << ", " << Marker << "unwind";
2118 if (Except)
2119 OS << ", " << Marker << "except";
2120 EmitEOL();
2123 void MCAsmStreamer::emitWinEHHandlerData(SMLoc Loc) {
2124 MCStreamer::emitWinEHHandlerData(Loc);
2126 // Switch sections. Don't call switchSection directly, because that will
2127 // cause the section switch to be visible in the emitted assembly.
2128 // We only do this so the section switch that terminates the handler
2129 // data block is visible.
2130 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
2132 // Do nothing if no frame is open. MCStreamer should've already reported an
2133 // error.
2134 if (!CurFrame)
2135 return;
2137 MCSection *TextSec = &CurFrame->Function->getSection();
2138 MCSection *XData = getAssociatedXDataSection(TextSec);
2139 switchSectionNoChange(XData);
2141 OS << "\t.seh_handlerdata";
2142 EmitEOL();
2145 void MCAsmStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
2146 MCStreamer::emitWinCFIPushReg(Register, Loc);
2148 OS << "\t.seh_pushreg ";
2149 InstPrinter->printRegName(OS, Register);
2150 EmitEOL();
2153 void MCAsmStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
2154 SMLoc Loc) {
2155 MCStreamer::emitWinCFISetFrame(Register, Offset, Loc);
2157 OS << "\t.seh_setframe ";
2158 InstPrinter->printRegName(OS, Register);
2159 OS << ", " << Offset;
2160 EmitEOL();
2163 void MCAsmStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
2164 MCStreamer::emitWinCFIAllocStack(Size, Loc);
2166 OS << "\t.seh_stackalloc " << Size;
2167 EmitEOL();
2170 void MCAsmStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
2171 SMLoc Loc) {
2172 MCStreamer::emitWinCFISaveReg(Register, Offset, Loc);
2174 OS << "\t.seh_savereg ";
2175 InstPrinter->printRegName(OS, Register);
2176 OS << ", " << Offset;
2177 EmitEOL();
2180 void MCAsmStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
2181 SMLoc Loc) {
2182 MCStreamer::emitWinCFISaveXMM(Register, Offset, Loc);
2184 OS << "\t.seh_savexmm ";
2185 InstPrinter->printRegName(OS, Register);
2186 OS << ", " << Offset;
2187 EmitEOL();
2190 void MCAsmStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
2191 MCStreamer::emitWinCFIPushFrame(Code, Loc);
2193 OS << "\t.seh_pushframe";
2194 if (Code)
2195 OS << " @code";
2196 EmitEOL();
2199 void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) {
2200 MCStreamer::emitWinCFIEndProlog(Loc);
2202 OS << "\t.seh_endprologue";
2203 EmitEOL();
2206 void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
2207 const MCSymbolRefExpr *To,
2208 uint64_t Count) {
2209 OS << "\t.cg_profile ";
2210 From->getSymbol().print(OS, MAI);
2211 OS << ", ";
2212 To->getSymbol().print(OS, MAI);
2213 OS << ", " << Count;
2214 EmitEOL();
2217 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
2218 const MCSubtargetInfo &STI) {
2219 raw_ostream &OS = getCommentOS();
2220 SmallString<256> Code;
2221 SmallVector<MCFixup, 4> Fixups;
2223 // If we have no code emitter, don't emit code.
2224 if (!getAssembler().getEmitterPtr())
2225 return;
2227 getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
2229 // If we are showing fixups, create symbolic markers in the encoded
2230 // representation. We do this by making a per-bit map to the fixup item index,
2231 // then trying to display it as nicely as possible.
2232 SmallVector<uint8_t, 64> FixupMap;
2233 FixupMap.resize(Code.size() * 8);
2234 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
2235 FixupMap[i] = 0;
2237 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2238 MCFixup &F = Fixups[i];
2239 const MCFixupKindInfo &Info =
2240 getAssembler().getBackend().getFixupKindInfo(F.getKind());
2241 for (unsigned j = 0; j != Info.TargetSize; ++j) {
2242 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
2243 assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
2244 FixupMap[Index] = 1 + i;
2248 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
2249 // high order halfword of a 32-bit Thumb2 instruction is emitted first.
2250 OS << "encoding: [";
2251 for (unsigned i = 0, e = Code.size(); i != e; ++i) {
2252 if (i)
2253 OS << ',';
2255 // See if all bits are the same map entry.
2256 uint8_t MapEntry = FixupMap[i * 8 + 0];
2257 for (unsigned j = 1; j != 8; ++j) {
2258 if (FixupMap[i * 8 + j] == MapEntry)
2259 continue;
2261 MapEntry = uint8_t(~0U);
2262 break;
2265 if (MapEntry != uint8_t(~0U)) {
2266 if (MapEntry == 0) {
2267 OS << format("0x%02x", uint8_t(Code[i]));
2268 } else {
2269 if (Code[i]) {
2270 // FIXME: Some of the 8 bits require fix up.
2271 OS << format("0x%02x", uint8_t(Code[i])) << '\''
2272 << char('A' + MapEntry - 1) << '\'';
2273 } else
2274 OS << char('A' + MapEntry - 1);
2276 } else {
2277 // Otherwise, write out in binary.
2278 OS << "0b";
2279 for (unsigned j = 8; j--;) {
2280 unsigned Bit = (Code[i] >> j) & 1;
2282 unsigned FixupBit;
2283 if (MAI->isLittleEndian())
2284 FixupBit = i * 8 + j;
2285 else
2286 FixupBit = i * 8 + (7-j);
2288 if (uint8_t MapEntry = FixupMap[FixupBit]) {
2289 assert(Bit == 0 && "Encoder wrote into fixed up bit!");
2290 OS << char('A' + MapEntry - 1);
2291 } else
2292 OS << Bit;
2296 OS << "]\n";
2298 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2299 MCFixup &F = Fixups[i];
2300 const MCFixupKindInfo &Info =
2301 getAssembler().getBackend().getFixupKindInfo(F.getKind());
2302 OS << " fixup " << char('A' + i) << " - "
2303 << "offset: " << F.getOffset() << ", value: ";
2304 F.getValue()->print(OS, MAI);
2305 OS << ", kind: " << Info.Name << "\n";
2309 void MCAsmStreamer::emitInstruction(const MCInst &Inst,
2310 const MCSubtargetInfo &STI) {
2311 assert(getCurrentSectionOnly() &&
2312 "Cannot emit contents before setting section!");
2314 if (!MAI->usesDwarfFileAndLocDirectives())
2315 // Now that a machine instruction has been assembled into this section, make
2316 // a line entry for any .loc directive that has been seen.
2317 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
2319 // Show the encoding in a comment if we have a code emitter.
2320 AddEncodingComment(Inst, STI);
2322 // Show the MCInst if enabled.
2323 if (ShowInst) {
2324 Inst.dump_pretty(getCommentOS(), InstPrinter.get(), "\n ");
2325 getCommentOS() << "\n";
2328 if(getTargetStreamer())
2329 getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
2330 else
2331 InstPrinter->printInst(&Inst, 0, "", STI, OS);
2333 StringRef Comments = CommentToEmit;
2334 if (Comments.size() && Comments.back() != '\n')
2335 getCommentOS() << "\n";
2337 EmitEOL();
2340 void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
2341 uint64_t Type, uint64_t Attr,
2342 uint64_t Discriminator,
2343 const MCPseudoProbeInlineStack &InlineStack,
2344 MCSymbol *FnSym) {
2345 OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " " << Attr;
2346 if (Discriminator)
2347 OS << " " << Discriminator;
2348 // Emit inline stack like
2349 // @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2350 for (const auto &Site : InlineStack)
2351 OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2353 OS << " " << FnSym->getName();
2355 EmitEOL();
2358 void MCAsmStreamer::emitBundleAlignMode(Align Alignment) {
2359 OS << "\t.bundle_align_mode " << Log2(Alignment);
2360 EmitEOL();
2363 void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
2364 OS << "\t.bundle_lock";
2365 if (AlignToEnd)
2366 OS << " align_to_end";
2367 EmitEOL();
2370 void MCAsmStreamer::emitBundleUnlock() {
2371 OS << "\t.bundle_unlock";
2372 EmitEOL();
2375 std::optional<std::pair<bool, std::string>>
2376 MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2377 const MCExpr *Expr, SMLoc,
2378 const MCSubtargetInfo &STI) {
2379 OS << "\t.reloc ";
2380 Offset.print(OS, MAI);
2381 OS << ", " << Name;
2382 if (Expr) {
2383 OS << ", ";
2384 Expr->print(OS, MAI);
2386 EmitEOL();
2387 return std::nullopt;
2390 void MCAsmStreamer::emitAddrsig() {
2391 OS << "\t.addrsig";
2392 EmitEOL();
2395 void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
2396 OS << "\t.addrsig_sym ";
2397 Sym->print(OS, MAI);
2398 EmitEOL();
2401 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
2402 /// the specified string in the output .s file. This capability is
2403 /// indicated by the hasRawTextSupport() predicate.
2404 void MCAsmStreamer::emitRawTextImpl(StringRef String) {
2405 if (!String.empty() && String.back() == '\n')
2406 String = String.substr(0, String.size()-1);
2407 OS << String;
2408 EmitEOL();
2411 void MCAsmStreamer::finishImpl() {
2412 // If we are generating dwarf for assembly source files dump out the sections.
2413 if (getContext().getGenDwarfForAssembly())
2414 MCGenDwarfInfo::Emit(this);
2416 // Now it is time to emit debug line sections if target doesn't support .loc
2417 // and .line directives.
2418 if (!MAI->usesDwarfFileAndLocDirectives()) {
2419 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
2420 return;
2423 // Emit the label for the line table, if requested - since the rest of the
2424 // line table will be defined by .loc/.file directives, and not emitted
2425 // directly, the label is the only work required here.
2426 const auto &Tables = getContext().getMCDwarfLineTables();
2427 if (!Tables.empty()) {
2428 assert(Tables.size() == 1 && "asm output only supports one line table");
2429 if (auto *Label = Tables.begin()->second.getLabel()) {
2430 switchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
2431 emitLabel(Label);
2436 void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
2437 // If the assembler on some target fills in the DWARF unit length, we
2438 // don't want to emit the length in the compiler. For example, the AIX
2439 // assembler requires the assembly file with the unit length omitted from
2440 // the debug section headers. In such cases, any label we placed occurs
2441 // after the implied length field. We need to adjust the reference here
2442 // to account for the offset introduced by the inserted length field.
2443 if (!MAI->needsDwarfSectionSizeInHeader())
2444 return;
2445 MCStreamer::emitDwarfUnitLength(Length, Comment);
2448 MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,
2449 const Twine &Comment) {
2450 // If the assembler on some target fills in the DWARF unit length, we
2451 // don't want to emit the length in the compiler. For example, the AIX
2452 // assembler requires the assembly file with the unit length omitted from
2453 // the debug section headers. In such cases, any label we placed occurs
2454 // after the implied length field. We need to adjust the reference here
2455 // to account for the offset introduced by the inserted length field.
2456 if (!MAI->needsDwarfSectionSizeInHeader())
2457 return getContext().createTempSymbol(Prefix + "_end");
2458 return MCStreamer::emitDwarfUnitLength(Prefix, Comment);
2461 void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
2462 // If the assembler on some target fills in the DWARF unit length, we
2463 // don't want to emit the length in the compiler. For example, the AIX
2464 // assembler requires the assembly file with the unit length omitted from
2465 // the debug section headers. In such cases, any label we placed occurs
2466 // after the implied length field. We need to adjust the reference here
2467 // to account for the offset introduced by the inserted length field.
2468 MCContext &Ctx = getContext();
2469 if (!MAI->needsDwarfSectionSizeInHeader()) {
2470 MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");
2471 // Emit the symbol which does not contain the unit length field.
2472 emitLabel(DebugLineSymTmp);
2474 // Adjust the outer reference to account for the offset introduced by the
2475 // inserted length field.
2476 unsigned LengthFieldSize =
2477 dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat());
2478 const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);
2479 const MCExpr *OuterSym = MCBinaryExpr::createSub(
2480 MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);
2482 emitAssignment(StartSym, OuterSym);
2483 return;
2485 MCStreamer::emitDwarfLineStartLabel(StartSym);
2488 void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,
2489 MCSymbol *LastLabel) {
2490 // If the targets write the raw debug line data for assembly output (We can
2491 // not switch to Section and add the end symbol there for assembly output)
2492 // we currently use the .text end label as any section end. This will not
2493 // impact the debugability as we will jump to the caller of the last function
2494 // in the section before we come into the .text end address.
2495 assert(!MAI->usesDwarfFileAndLocDirectives() &&
2496 ".loc should not be generated together with raw data!");
2498 MCContext &Ctx = getContext();
2500 // FIXME: use section end symbol as end of the Section. We need to consider
2501 // the explicit sections and -ffunction-sections when we try to generate or
2502 // find section end symbol for the Section.
2503 MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();
2504 assert(TextSection->hasEnded() && ".text section is not end!");
2506 MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx);
2507 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
2508 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
2509 AsmInfo->getCodePointerSize());
2512 // Generate DWARF line sections for assembly mode without .loc/.file
2513 void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
2514 const MCSymbol *LastLabel,
2515 const MCSymbol *Label,
2516 unsigned PointerSize) {
2517 assert(!MAI->usesDwarfFileAndLocDirectives() &&
2518 ".loc/.file don't need raw data in debug line section!");
2520 // Set to new address.
2521 AddComment("Set address to " + Label->getName());
2522 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2523 emitULEB128IntValue(PointerSize + 1);
2524 emitIntValue(dwarf::DW_LNE_set_address, 1);
2525 emitSymbolValue(Label, PointerSize);
2527 if (!LastLabel) {
2528 // Emit the sequence for the LineDelta (from 1) and a zero address delta.
2529 AddComment("Start sequence");
2530 MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);
2531 return;
2534 // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence
2535 // for the end of the section.
2536 if (LineDelta == INT64_MAX) {
2537 AddComment("End sequence");
2538 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2539 emitULEB128IntValue(1);
2540 emitIntValue(dwarf::DW_LNE_end_sequence, 1);
2541 return;
2544 // Advance line.
2545 AddComment("Advance line " + Twine(LineDelta));
2546 emitIntValue(dwarf::DW_LNS_advance_line, 1);
2547 emitSLEB128IntValue(LineDelta);
2548 emitIntValue(dwarf::DW_LNS_copy, 1);
2551 void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) {
2552 // Emit section end. This is used to tell the debug line section where the end
2553 // is for a text section if we don't use .loc to represent the debug line.
2554 if (MAI->usesDwarfFileAndLocDirectives())
2555 return;
2557 switchSectionNoChange(Section);
2559 MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext());
2561 if (!Sym->isInSection())
2562 emitLabel(Sym);
2565 MCStreamer *llvm::createAsmStreamer(MCContext &Context,
2566 std::unique_ptr<formatted_raw_ostream> OS,
2567 bool isVerboseAsm, bool useDwarfDirectory,
2568 MCInstPrinter *IP,
2569 std::unique_ptr<MCCodeEmitter> &&CE,
2570 std::unique_ptr<MCAsmBackend> &&MAB,
2571 bool ShowInst) {
2572 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
2573 useDwarfDirectory, IP, std::move(CE), std::move(MAB),
2574 ShowInst);