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