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