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