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