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