Line data Source code
1 : //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ADT/Optional.h"
11 : #include "llvm/ADT/STLExtras.h"
12 : #include "llvm/ADT/SmallString.h"
13 : #include "llvm/ADT/StringExtras.h"
14 : #include "llvm/ADT/Twine.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/MCRegisterInfo.h"
28 : #include "llvm/MC/MCSectionMachO.h"
29 : #include "llvm/MC/MCStreamer.h"
30 : #include "llvm/Support/ErrorHandling.h"
31 : #include "llvm/Support/Format.h"
32 : #include "llvm/Support/FormattedStream.h"
33 : #include "llvm/Support/LEB128.h"
34 : #include "llvm/Support/MathExtras.h"
35 : #include "llvm/Support/Path.h"
36 : #include "llvm/Support/TargetRegistry.h"
37 : #include <cctype>
38 :
39 : using namespace llvm;
40 :
41 : namespace {
42 :
43 : class MCAsmStreamer final : public MCStreamer {
44 : std::unique_ptr<formatted_raw_ostream> OSOwner;
45 : formatted_raw_ostream &OS;
46 : const MCAsmInfo *MAI;
47 : std::unique_ptr<MCInstPrinter> InstPrinter;
48 : std::unique_ptr<MCAssembler> Assembler;
49 :
50 : SmallString<128> ExplicitCommentToEmit;
51 : SmallString<128> CommentToEmit;
52 : raw_svector_ostream CommentStream;
53 : raw_null_ostream NullStream;
54 :
55 : unsigned IsVerboseAsm : 1;
56 : unsigned ShowInst : 1;
57 : unsigned UseDwarfDirectory : 1;
58 :
59 : void EmitRegisterName(int64_t Register);
60 : void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
61 : void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
62 :
63 : public:
64 23058 : MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
65 : bool isVerboseAsm, bool useDwarfDirectory,
66 : MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
67 : std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
68 23058 : : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
69 23058 : MAI(Context.getAsmInfo()), InstPrinter(printer),
70 : Assembler(llvm::make_unique<MCAssembler>(
71 : Context, std::move(asmbackend), std::move(emitter),
72 46116 : (asmbackend) ? asmbackend->createObjectWriter(NullStream)
73 : : nullptr)),
74 : CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
75 69174 : ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
76 : assert(InstPrinter);
77 23058 : if (IsVerboseAsm)
78 : InstPrinter->setCommentStream(CommentStream);
79 23058 : }
80 :
81 : MCAssembler &getAssembler() { return *Assembler; }
82 332735 : MCAssembler *getAssemblerPtr() override { return nullptr; }
83 :
84 5473732 : inline void EmitEOL() {
85 : // Dump Explicit Comments here.
86 : emitExplicitComments();
87 : // If we don't have any comments, just emit a \n.
88 5473732 : if (!IsVerboseAsm) {
89 91886 : OS << '\n';
90 91886 : return;
91 : }
92 5381846 : EmitCommentsAndEOL();
93 : }
94 :
95 : void EmitSyntaxDirective() override;
96 :
97 : void EmitCommentsAndEOL();
98 :
99 : /// Return true if this streamer supports verbose assembly at all.
100 62423 : bool isVerboseAsm() const override { return IsVerboseAsm; }
101 :
102 : /// Do we support EmitRawText?
103 4119 : bool hasRawTextSupport() const override { return true; }
104 :
105 : /// Add a comment that can be emitted to the generated .s file to make the
106 : /// output of the compiler more readable. This only affects the MCAsmStreamer
107 : /// and only when verbose assembly output is enabled.
108 : void AddComment(const Twine &T, bool EOL = true) override;
109 :
110 : /// Add a comment showing the encoding of an instruction.
111 : /// If PrintSchedInfo is true, then the comment sched:[x:y] will be added to
112 : /// the output if supported by the target.
113 : void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &,
114 : bool PrintSchedInfo);
115 :
116 : /// Return a raw_ostream that comments can be written to.
117 : /// Unlike AddComment, you are required to terminate comments with \n if you
118 : /// use this method.
119 2789592 : raw_ostream &GetCommentOS() override {
120 2980927 : if (!IsVerboseAsm)
121 43448 : return nulls(); // Discard comments unless in verbose asm mode.
122 5010560 : return CommentStream;
123 : }
124 :
125 : void emitRawComment(const Twine &T, bool TabPrefix = true) override;
126 :
127 : void addExplicitComment(const Twine &T) override;
128 : void emitExplicitComments() override;
129 :
130 : /// Emit a blank line to a .s file to pretty it up.
131 697588 : void AddBlankLine() override {
132 697588 : EmitEOL();
133 697588 : }
134 :
135 : /// @name MCStreamer Interface
136 : /// @{
137 :
138 : void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
139 :
140 : void emitELFSymverDirective(StringRef AliasName,
141 : const MCSymbol *Aliasee) override;
142 :
143 : void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
144 : void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
145 :
146 : void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
147 : void EmitLinkerOptions(ArrayRef<std::string> Options) override;
148 : void EmitDataRegion(MCDataRegionType Kind) override;
149 : void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
150 : unsigned Update) override;
151 : void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
152 : unsigned Update) override;
153 : void EmitThumbFunc(MCSymbol *Func) override;
154 :
155 : void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
156 : void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
157 : bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
158 :
159 : void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
160 : void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
161 : void EmitCOFFSymbolStorageClass(int StorageClass) override;
162 : void EmitCOFFSymbolType(int Type) override;
163 : void EndCOFFSymbolDef() override;
164 : void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
165 : void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
166 : void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
167 : void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
168 : void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
169 : void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
170 : void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
171 : unsigned ByteAlignment) override;
172 :
173 : /// Emit a local common (.lcomm) symbol.
174 : ///
175 : /// @param Symbol - The common symbol to emit.
176 : /// @param Size - The size of the common symbol.
177 : /// @param ByteAlignment - The alignment of the common symbol in bytes.
178 : void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
179 : unsigned ByteAlignment) override;
180 :
181 : void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
182 : uint64_t Size = 0, unsigned ByteAlignment = 0,
183 : SMLoc Loc = SMLoc()) override;
184 :
185 : void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
186 : unsigned ByteAlignment = 0) override;
187 :
188 : void EmitBinaryData(StringRef Data) override;
189 :
190 : void EmitBytes(StringRef Data) override;
191 :
192 : void EmitValueImpl(const MCExpr *Value, unsigned Size,
193 : SMLoc Loc = SMLoc()) override;
194 : void EmitIntValue(uint64_t Value, unsigned Size) override;
195 :
196 : void EmitULEB128Value(const MCExpr *Value) override;
197 :
198 : void EmitSLEB128Value(const MCExpr *Value) override;
199 :
200 : void EmitDTPRel32Value(const MCExpr *Value) override;
201 : void EmitDTPRel64Value(const MCExpr *Value) override;
202 : void EmitTPRel32Value(const MCExpr *Value) override;
203 : void EmitTPRel64Value(const MCExpr *Value) override;
204 :
205 : void EmitGPRel64Value(const MCExpr *Value) override;
206 :
207 : void EmitGPRel32Value(const MCExpr *Value) override;
208 :
209 : void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
210 : SMLoc Loc = SMLoc()) override;
211 :
212 : void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
213 : SMLoc Loc = SMLoc()) override;
214 :
215 : void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
216 : unsigned ValueSize = 1,
217 : unsigned MaxBytesToEmit = 0) override;
218 :
219 : void EmitCodeAlignment(unsigned ByteAlignment,
220 : unsigned MaxBytesToEmit = 0) override;
221 :
222 : void emitValueToOffset(const MCExpr *Offset,
223 : unsigned char Value,
224 : SMLoc Loc) override;
225 :
226 : void EmitFileDirective(StringRef Filename) override;
227 : Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
228 : StringRef Directory,
229 : StringRef Filename,
230 : MD5::MD5Result *Checksum = 0,
231 : Optional<StringRef> Source = None,
232 : unsigned CUID = 0) override;
233 : void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
234 : MD5::MD5Result *Checksum,
235 : Optional<StringRef> Source,
236 : unsigned CUID = 0) override;
237 : void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
238 : unsigned Column, unsigned Flags,
239 : unsigned Isa, unsigned Discriminator,
240 : StringRef FileName) override;
241 : MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
242 :
243 : bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
244 : ArrayRef<uint8_t> Checksum,
245 : unsigned ChecksumKind) override;
246 : bool EmitCVFuncIdDirective(unsigned FuncId) override;
247 : bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
248 : unsigned IAFile, unsigned IALine,
249 : unsigned IACol, SMLoc Loc) override;
250 : void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
251 : unsigned Column, bool PrologueEnd, bool IsStmt,
252 : StringRef FileName, SMLoc Loc) override;
253 : void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
254 : const MCSymbol *FnEnd) override;
255 : void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
256 : unsigned SourceFileId,
257 : unsigned SourceLineNum,
258 : const MCSymbol *FnStartSym,
259 : const MCSymbol *FnEndSym) override;
260 : void EmitCVDefRangeDirective(
261 : ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
262 : StringRef FixedSizePortion) override;
263 : void EmitCVStringTableDirective() override;
264 : void EmitCVFileChecksumsDirective() override;
265 : void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
266 : void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
267 :
268 : void EmitIdent(StringRef IdentString) override;
269 : void EmitCFISections(bool EH, bool Debug) override;
270 : void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
271 : void EmitCFIDefCfaOffset(int64_t Offset) override;
272 : void EmitCFIDefCfaRegister(int64_t Register) override;
273 : void EmitCFIOffset(int64_t Register, int64_t Offset) override;
274 : void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
275 : void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
276 : void EmitCFIRememberState() override;
277 : void EmitCFIRestoreState() override;
278 : void EmitCFIRestore(int64_t Register) override;
279 : void EmitCFISameValue(int64_t Register) override;
280 : void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
281 : void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
282 : void EmitCFIEscape(StringRef Values) override;
283 : void EmitCFIGnuArgsSize(int64_t Size) override;
284 : void EmitCFISignalFrame() override;
285 : void EmitCFIUndefined(int64_t Register) override;
286 : void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
287 : void EmitCFIWindowSave() override;
288 : void EmitCFIReturnColumn(int64_t Register) override;
289 :
290 : void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
291 : void EmitWinCFIEndProc(SMLoc Loc) override;
292 : void EmitWinCFIStartChained(SMLoc Loc) override;
293 : void EmitWinCFIEndChained(SMLoc Loc) override;
294 : void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override;
295 : void EmitWinCFISetFrame(unsigned Register, unsigned Offset,
296 : SMLoc Loc) override;
297 : void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
298 : void EmitWinCFISaveReg(unsigned Register, unsigned Offset,
299 : SMLoc Loc) override;
300 : void EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
301 : SMLoc Loc) override;
302 : void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
303 : void EmitWinCFIEndProlog(SMLoc Loc) override;
304 :
305 : void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
306 : SMLoc Loc) override;
307 : void EmitWinEHHandlerData(SMLoc Loc) override;
308 :
309 : void emitCGProfileEntry(const MCSymbolRefExpr *From,
310 : const MCSymbolRefExpr *To, uint64_t Count) override;
311 :
312 : void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
313 : bool PrintSchedInfo) override;
314 :
315 : void EmitBundleAlignMode(unsigned AlignPow2) override;
316 : void EmitBundleLock(bool AlignToEnd) override;
317 : void EmitBundleUnlock() override;
318 :
319 : bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
320 : const MCExpr *Expr, SMLoc Loc,
321 : const MCSubtargetInfo &STI) override;
322 :
323 : void EmitAddrsig() override;
324 : void EmitAddrsigSym(const MCSymbol *Sym) override;
325 :
326 : /// If this file is backed by an assembly streamer, this dumps the specified
327 : /// string in the output .s file. This capability is indicated by the
328 : /// hasRawTextSupport() predicate.
329 : void EmitRawTextImpl(StringRef String) override;
330 :
331 : void FinishImpl() override;
332 : };
333 :
334 : } // end anonymous namespace.
335 :
336 108522 : void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
337 108522 : if (!IsVerboseAsm) return;
338 :
339 107549 : T.toVector(CommentToEmit);
340 :
341 107549 : if (EOL)
342 100872 : CommentToEmit.push_back('\n'); // Place comment in a new line.
343 : }
344 :
345 5381846 : void MCAsmStreamer::EmitCommentsAndEOL() {
346 5381846 : if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
347 3809247 : OS << '\n';
348 3809247 : return;
349 : }
350 :
351 1572599 : StringRef Comments = CommentToEmit;
352 :
353 : assert(Comments.back() == '\n' &&
354 : "Comment array not newline terminated");
355 : do {
356 : // Emit a line of comments.
357 1636679 : OS.PadToColumn(MAI->getCommentColumn());
358 1636679 : size_t Position = Comments.find('\n');
359 3273358 : OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
360 :
361 1636679 : Comments = Comments.substr(Position+1);
362 1636679 : } while (!Comments.empty());
363 :
364 : CommentToEmit.clear();
365 : }
366 :
367 : static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
368 : assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
369 99792 : return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
370 : }
371 :
372 605387 : void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
373 605387 : if (TabPrefix)
374 38231 : OS << '\t';
375 605387 : OS << MAI->getCommentString() << T;
376 605387 : EmitEOL();
377 605387 : }
378 :
379 208 : void MCAsmStreamer::addExplicitComment(const Twine &T) {
380 208 : StringRef c = T.getSingleStringRef();
381 208 : if (c.equals(StringRef(MAI->getSeparatorString())))
382 52 : return;
383 : if (c.startswith(StringRef("//"))) {
384 : ExplicitCommentToEmit.append("\t");
385 19 : ExplicitCommentToEmit.append(MAI->getCommentString());
386 : // drop //
387 38 : ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
388 : } else if (c.startswith(StringRef("/*"))) {
389 12 : size_t p = 2, len = c.size() - 2;
390 : // emit each line in comment as separate newline.
391 : do {
392 14 : size_t newp = std::min(len, c.find_first_of("\r\n", p));
393 : ExplicitCommentToEmit.append("\t");
394 13 : ExplicitCommentToEmit.append(MAI->getCommentString());
395 13 : ExplicitCommentToEmit.append(c.slice(p, newp).str());
396 : // If we have another line in this comment add line
397 13 : if (newp < len)
398 : ExplicitCommentToEmit.append("\n");
399 13 : p = newp + 1;
400 13 : } while (p < len);
401 : } else if (c.startswith(StringRef(MAI->getCommentString()))) {
402 : ExplicitCommentToEmit.append("\t");
403 218 : ExplicitCommentToEmit.append(c.str());
404 32 : } else if (c.front() == '#') {
405 :
406 : ExplicitCommentToEmit.append("\t");
407 16 : ExplicitCommentToEmit.append(MAI->getCommentString());
408 32 : ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
409 : } else
410 : assert(false && "Unexpected Assembly Comment");
411 : // full line comments immediately output
412 312 : if (c.back() == '\n')
413 : emitExplicitComments();
414 : }
415 :
416 0 : void MCAsmStreamer::emitExplicitComments() {
417 5473861 : StringRef Comments = ExplicitCommentToEmit;
418 5473861 : if (!Comments.empty())
419 152 : OS << Comments;
420 : ExplicitCommentToEmit.clear();
421 0 : }
422 :
423 160539 : void MCAsmStreamer::ChangeSection(MCSection *Section,
424 : const MCExpr *Subsection) {
425 : assert(Section && "Cannot switch to a null section!");
426 160539 : if (MCTargetStreamer *TS = getTargetStreamer()) {
427 301218 : TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
428 : } else {
429 29790 : Section->PrintSwitchToSection(
430 9930 : *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
431 9930 : Subsection);
432 : }
433 160538 : }
434 :
435 6 : void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
436 : const MCSymbol *Aliasee) {
437 6 : OS << ".symver ";
438 6 : Aliasee->print(OS, MAI);
439 6 : OS << ", " << AliasName;
440 6 : EmitEOL();
441 6 : }
442 :
443 452971 : void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
444 452971 : MCStreamer::EmitLabel(Symbol, Loc);
445 :
446 452970 : Symbol->print(OS, MAI);
447 452970 : OS << MAI->getLabelSuffix();
448 :
449 452970 : EmitEOL();
450 452970 : }
451 :
452 237 : void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
453 237 : StringRef str = MCLOHIdToName(Kind);
454 :
455 : #ifndef NDEBUG
456 : int NbArgs = MCLOHIdToNbArgs(Kind);
457 : assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
458 : assert(str != "" && "Invalid LOH name");
459 : #endif
460 :
461 237 : OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
462 : bool IsFirst = true;
463 774 : for (const MCSymbol *Arg : Args) {
464 537 : if (!IsFirst)
465 300 : OS << ", ";
466 : IsFirst = false;
467 537 : Arg->print(OS, MAI);
468 : }
469 237 : EmitEOL();
470 237 : }
471 :
472 19282 : void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
473 19282 : switch (Flag) {
474 2681 : case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
475 2175 : case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
476 12092 : case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
477 16756 : case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
478 4 : case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
479 : }
480 19282 : EmitEOL();
481 19282 : }
482 :
483 5 : void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
484 : assert(!Options.empty() && "At least one option is required!");
485 5 : OS << "\t.linker_option \"" << Options[0] << '"';
486 2 : for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
487 7 : ie = Options.end(); it != ie; ++it) {
488 2 : OS << ", " << '"' << *it << '"';
489 : }
490 5 : EmitEOL();
491 5 : }
492 :
493 3374 : void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
494 3374 : if (!MAI->doesSupportDataRegionDirectives())
495 : return;
496 848 : switch (Kind) {
497 374 : case MCDR_DataRegion: OS << "\t.data_region"; break;
498 17 : case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
499 0 : case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
500 33 : case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
501 424 : case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
502 : }
503 848 : EmitEOL();
504 : }
505 :
506 : static const char *getVersionMinDirective(MCVersionMinType Type) {
507 787 : switch (Type) {
508 : case MCVM_WatchOSVersionMin: return ".watchos_version_min";
509 18 : case MCVM_TvOSVersionMin: return ".tvos_version_min";
510 186 : case MCVM_IOSVersionMin: return ".ios_version_min";
511 557 : case MCVM_OSXVersionMin: return ".macosx_version_min";
512 : }
513 0 : llvm_unreachable("Invalid MC version min type");
514 : }
515 :
516 787 : void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
517 : unsigned Minor, unsigned Update) {
518 2361 : OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
519 787 : if (Update)
520 43 : OS << ", " << Update;
521 787 : EmitEOL();
522 787 : }
523 :
524 : static const char *getPlatformName(MachO::PlatformType Type) {
525 8 : switch (Type) {
526 : case MachO::PLATFORM_MACOS: return "macos";
527 1 : case MachO::PLATFORM_IOS: return "ios";
528 2 : case MachO::PLATFORM_TVOS: return "tvos";
529 1 : case MachO::PLATFORM_WATCHOS: return "watchos";
530 0 : case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
531 : }
532 0 : llvm_unreachable("Invalid Mach-O platform type");
533 : }
534 :
535 8 : void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
536 : unsigned Minor, unsigned Update) {
537 : const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
538 16 : OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
539 8 : if (Update)
540 3 : OS << ", " << Update;
541 8 : EmitEOL();
542 8 : }
543 :
544 5858 : void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
545 : // This needs to emit to a temporary string to get properly quoted
546 : // MCSymbols when they have spaces in them.
547 5858 : OS << "\t.thumb_func";
548 : // Only Mach-O hasSubsectionsViaSymbols()
549 5858 : if (MAI->hasSubsectionsViaSymbols()) {
550 1301 : OS << '\t';
551 1301 : Func->print(OS, MAI);
552 : }
553 5858 : EmitEOL();
554 5858 : }
555 :
556 2098 : void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
557 : // Do not emit a .set on inlined target assignments.
558 : bool EmitSet = true;
559 1 : if (auto *E = dyn_cast<MCTargetExpr>(Value))
560 1 : if (E->inlineAssignedExpr())
561 : EmitSet = false;
562 : if (EmitSet) {
563 2097 : OS << ".set ";
564 2097 : Symbol->print(OS, MAI);
565 2097 : OS << ", ";
566 2097 : Value->print(OS, MAI);
567 :
568 2097 : EmitEOL();
569 : }
570 :
571 2098 : MCStreamer::EmitAssignment(Symbol, Value);
572 2098 : }
573 :
574 0 : void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
575 0 : OS << ".weakref ";
576 0 : Alias->print(OS, MAI);
577 0 : OS << ", ";
578 0 : Symbol->print(OS, MAI);
579 0 : EmitEOL();
580 0 : }
581 :
582 386568 : bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
583 : MCSymbolAttr Attribute) {
584 386568 : switch (Attribute) {
585 : case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
586 182414 : case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
587 : case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
588 : case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
589 : case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
590 : case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
591 : case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
592 : case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
593 182414 : if (!MAI->hasDotTypeDotSizeDirective())
594 : return false; // Symbol attribute not supported
595 182346 : OS << "\t.type\t";
596 182346 : Symbol->print(OS, MAI);
597 547038 : OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
598 : switch (Attribute) {
599 : default: return false;
600 171351 : case MCSA_ELF_TypeFunction: OS << "function"; break;
601 6 : case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
602 10983 : case MCSA_ELF_TypeObject: OS << "object"; break;
603 1 : case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
604 1 : case MCSA_ELF_TypeCommon: OS << "common"; break;
605 1 : case MCSA_ELF_TypeNoType: OS << "notype"; break;
606 3 : case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
607 : }
608 182346 : EmitEOL();
609 182346 : return true;
610 201783 : case MCSA_Global: // .globl/.global
611 201783 : OS << MAI->getGlobalDirective();
612 201783 : break;
613 527 : case MCSA_Hidden: OS << "\t.hidden\t"; break;
614 583 : case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
615 0 : case MCSA_Internal: OS << "\t.internal\t"; break;
616 9 : case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
617 240 : case MCSA_Local: OS << "\t.local\t"; break;
618 107 : case MCSA_NoDeadStrip:
619 107 : if (!MAI->hasNoDeadStrip())
620 : return false;
621 59 : OS << "\t.no_dead_strip\t";
622 59 : break;
623 4 : case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
624 8 : case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
625 69 : case MCSA_PrivateExtern:
626 69 : OS << "\t.private_extern\t";
627 69 : break;
628 47 : case MCSA_Protected: OS << "\t.protected\t"; break;
629 4 : case MCSA_Reference: OS << "\t.reference\t"; break;
630 444 : case MCSA_Weak: OS << MAI->getWeakDirective(); break;
631 164 : case MCSA_WeakDefinition:
632 164 : OS << "\t.weak_definition\t";
633 164 : break;
634 : // .weak_reference
635 150 : case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
636 15 : case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
637 : }
638 :
639 204106 : Symbol->print(OS, MAI);
640 204106 : EmitEOL();
641 :
642 204106 : return true;
643 : }
644 :
645 3 : void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
646 3 : OS << ".desc" << ' ';
647 3 : Symbol->print(OS, MAI);
648 3 : OS << ',' << DescValue;
649 3 : EmitEOL();
650 3 : }
651 :
652 7152 : void MCAsmStreamer::EmitSyntaxDirective() {
653 7152 : if (MAI->getAssemblerDialect() == 1) {
654 23 : OS << "\t.intel_syntax noprefix";
655 23 : EmitEOL();
656 : }
657 : // FIXME: Currently emit unprefix'ed registers.
658 : // The intel_syntax directive has one optional argument
659 : // with may have a value of prefix or noprefix.
660 7152 : }
661 :
662 3189 : void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
663 3189 : OS << "\t.def\t ";
664 3189 : Symbol->print(OS, MAI);
665 3189 : OS << ';';
666 3189 : EmitEOL();
667 3189 : }
668 :
669 3189 : void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
670 3189 : OS << "\t.scl\t" << StorageClass << ';';
671 3189 : EmitEOL();
672 3189 : }
673 :
674 3189 : void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
675 3189 : OS << "\t.type\t" << Type << ';';
676 3189 : EmitEOL();
677 3189 : }
678 :
679 3189 : void MCAsmStreamer::EndCOFFSymbolDef() {
680 3189 : OS << "\t.endef";
681 3189 : EmitEOL();
682 3189 : }
683 :
684 30 : void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
685 30 : OS << "\t.safeseh\t";
686 30 : Symbol->print(OS, MAI);
687 30 : EmitEOL();
688 30 : }
689 :
690 4 : void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
691 4 : OS << "\t.symidx\t";
692 4 : Symbol->print(OS, MAI);
693 4 : EmitEOL();
694 4 : }
695 :
696 119 : void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
697 119 : OS << "\t.secidx\t";
698 119 : Symbol->print(OS, MAI);
699 119 : EmitEOL();
700 119 : }
701 :
702 312 : void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
703 312 : OS << "\t.secrel32\t";
704 312 : Symbol->print(OS, MAI);
705 312 : if (Offset != 0)
706 4 : OS << '+' << Offset;
707 312 : EmitEOL();
708 312 : }
709 :
710 0 : void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
711 0 : OS << "\t.rva\t";
712 0 : Symbol->print(OS, MAI);
713 0 : if (Offset > 0)
714 0 : OS << '+' << Offset;
715 0 : else if (Offset < 0)
716 0 : OS << '-' << -Offset;
717 0 : EmitEOL();
718 0 : }
719 :
720 179606 : void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
721 : assert(MAI->hasDotTypeDotSizeDirective());
722 179606 : OS << "\t.size\t";
723 179606 : Symbol->print(OS, MAI);
724 179606 : OS << ", ";
725 179606 : Value->print(OS, MAI);
726 179606 : EmitEOL();
727 179606 : }
728 :
729 2776 : void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
730 : unsigned ByteAlignment) {
731 2776 : OS << "\t.comm\t";
732 2776 : Symbol->print(OS, MAI);
733 5552 : OS << ',' << Size;
734 :
735 2776 : if (ByteAlignment != 0) {
736 2666 : if (MAI->getCOMMDirectiveAlignmentIsInBytes())
737 2454 : OS << ',' << ByteAlignment;
738 : else
739 212 : OS << ',' << Log2_32(ByteAlignment);
740 : }
741 2776 : EmitEOL();
742 2776 : }
743 :
744 42 : void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
745 : unsigned ByteAlign) {
746 42 : OS << "\t.lcomm\t";
747 42 : Symbol->print(OS, MAI);
748 84 : OS << ',' << Size;
749 :
750 42 : if (ByteAlign > 1) {
751 32 : switch (MAI->getLCOMMDirectiveAlignmentType()) {
752 : case LCOMM::NoAlignment:
753 : llvm_unreachable("alignment not supported on .lcomm!");
754 31 : case LCOMM::ByteAlignment:
755 31 : OS << ',' << ByteAlign;
756 : break;
757 1 : case LCOMM::Log2Alignment:
758 : assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
759 1 : OS << ',' << Log2_32(ByteAlign);
760 : break;
761 : }
762 : }
763 42 : EmitEOL();
764 42 : }
765 :
766 279 : void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
767 : uint64_t Size, unsigned ByteAlignment,
768 : SMLoc Loc) {
769 279 : if (Symbol)
770 556 : AssignFragment(Symbol, &Section->getDummyFragment());
771 :
772 : // Note: a .zerofill directive does not switch sections.
773 279 : OS << ".zerofill ";
774 :
775 : assert(Section->getVariant() == MCSection::SV_MachO &&
776 : ".zerofill is a Mach-O specific directive");
777 : // This is a mach-o specific directive.
778 :
779 : const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
780 837 : OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
781 :
782 279 : if (Symbol) {
783 278 : OS << ',';
784 278 : Symbol->print(OS, MAI);
785 556 : OS << ',' << Size;
786 278 : if (ByteAlignment != 0)
787 278 : OS << ',' << Log2_32(ByteAlignment);
788 : }
789 279 : EmitEOL();
790 279 : }
791 :
792 : // .tbss sym, size, align
793 : // This depends that the symbol has already been mangled from the original,
794 : // e.g. _a.
795 73 : void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
796 : uint64_t Size, unsigned ByteAlignment) {
797 146 : AssignFragment(Symbol, &Section->getDummyFragment());
798 :
799 : assert(Symbol && "Symbol shouldn't be NULL!");
800 : // Instead of using the Section we'll just use the shortcut.
801 :
802 : assert(Section->getVariant() == MCSection::SV_MachO &&
803 : ".zerofill is a Mach-O specific directive");
804 : // This is a mach-o specific directive and section.
805 :
806 73 : OS << ".tbss ";
807 73 : Symbol->print(OS, MAI);
808 73 : OS << ", " << Size;
809 :
810 : // Output align if we have it. We default to 1 so don't bother printing
811 : // that.
812 73 : if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
813 :
814 73 : EmitEOL();
815 73 : }
816 :
817 2962 : static inline char toOctal(int X) { return (X&7)+'0'; }
818 :
819 21150 : static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
820 : OS << '"';
821 :
822 234983 : for (unsigned i = 0, e = Data.size(); i != e; ++i) {
823 213833 : unsigned char C = Data[i];
824 213833 : if (C == '"' || C == '\\') {
825 : OS << '\\' << (char)C;
826 269 : continue;
827 : }
828 :
829 213564 : if (isPrint((unsigned char)C)) {
830 : OS << (char)C;
831 210056 : continue;
832 : }
833 :
834 3508 : switch (C) {
835 44 : case '\b': OS << "\\b"; break;
836 8 : case '\f': OS << "\\f"; break;
837 421 : case '\n': OS << "\\n"; break;
838 5 : case '\r': OS << "\\r"; break;
839 68 : case '\t': OS << "\\t"; break;
840 : default:
841 : OS << '\\';
842 2962 : OS << toOctal(C >> 6);
843 2962 : OS << toOctal(C >> 3);
844 : OS << toOctal(C >> 0);
845 : break;
846 : }
847 : }
848 :
849 : OS << '"';
850 21150 : }
851 :
852 40937 : void MCAsmStreamer::EmitBytes(StringRef Data) {
853 : assert(getCurrentSectionOnly() &&
854 : "Cannot emit contents before setting section!");
855 40937 : if (Data.empty()) return;
856 :
857 : // If only single byte is provided or no ascii or asciz directives is
858 : // supported, emit as vector of 8bits data.
859 40936 : if (Data.size() == 1 ||
860 6083 : !(MAI->getAscizDirective() || MAI->getAsciiDirective())) {
861 34866 : const char *Directive = MAI->getData8bitsDirective();
862 69745 : for (const unsigned char C : Data.bytes()) {
863 34879 : OS << Directive << (unsigned)C;
864 34879 : EmitEOL();
865 : }
866 : return;
867 : }
868 :
869 : // If the data ends with 0 and the target supports .asciz, use it, otherwise
870 : // use .ascii
871 6070 : if (MAI->getAscizDirective() && Data.back() == 0) {
872 4981 : OS << MAI->getAscizDirective();
873 4981 : Data = Data.substr(0, Data.size()-1);
874 : } else {
875 1089 : OS << MAI->getAsciiDirective();
876 : }
877 :
878 6070 : PrintQuotedString(Data, OS);
879 6070 : EmitEOL();
880 : }
881 :
882 978 : void MCAsmStreamer::EmitBinaryData(StringRef Data) {
883 : // This is binary data. Print it in a grid of hex bytes for readability.
884 : const size_t Cols = 4;
885 4343 : for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
886 3365 : size_t J = I, EJ = std::min(I + Cols, Data.size());
887 : assert(EJ > 0);
888 3365 : OS << MAI->getData8bitsDirective();
889 12273 : for (; J < EJ - 1; ++J)
890 26724 : OS << format("0x%02x", uint8_t(Data[J])) << ", ";
891 10095 : OS << format("0x%02x", uint8_t(Data[J]));
892 3365 : EmitEOL();
893 : }
894 978 : }
895 :
896 444507 : void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
897 444507 : EmitValue(MCConstantExpr::create(Value, getContext()), Size);
898 444507 : }
899 :
900 469285 : void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
901 : SMLoc Loc) {
902 : assert(Size <= 8 && "Invalid size");
903 : assert(getCurrentSectionOnly() &&
904 : "Cannot emit contents before setting section!");
905 : const char *Directive = nullptr;
906 469285 : switch (Size) {
907 : default: break;
908 128467 : case 1: Directive = MAI->getData8bitsDirective(); break;
909 43875 : case 2: Directive = MAI->getData16bitsDirective(); break;
910 256796 : case 4: Directive = MAI->getData32bitsDirective(); break;
911 40147 : case 8: Directive = MAI->getData64bitsDirective(); break;
912 : }
913 :
914 469285 : if (!Directive) {
915 : int64_t IntValue;
916 768 : if (!Value->evaluateAsAbsolute(IntValue))
917 0 : report_fatal_error("Don't know how to emit this value.");
918 :
919 : // We couldn't handle the requested integer size so we fallback by breaking
920 : // the request down into several, smaller, integers.
921 : // Since sizes greater or equal to "Size" are invalid, we use the greatest
922 : // power of 2 that is less than "Size" as our largest piece of granularity.
923 768 : bool IsLittleEndian = MAI->isLittleEndian();
924 2304 : for (unsigned Emitted = 0; Emitted != Size;) {
925 1536 : unsigned Remaining = Size - Emitted;
926 : // The size of our partial emission must be a power of two less than
927 : // Size.
928 2304 : unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
929 : // Calculate the byte offset of our partial emission taking into account
930 : // the endianness of the target.
931 : unsigned ByteOffset =
932 1536 : IsLittleEndian ? Emitted : (Remaining - EmissionSize);
933 1536 : uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
934 : // We truncate our partial emission to fit within the bounds of the
935 : // emission domain. This produces nicer output and silences potential
936 : // truncation warnings when round tripping through another assembler.
937 1536 : uint64_t Shift = 64 - EmissionSize * 8;
938 : assert(Shift < static_cast<uint64_t>(
939 : std::numeric_limits<unsigned long long>::digits) &&
940 : "undefined behavior");
941 1536 : ValueToEmit &= ~0ULL >> Shift;
942 1536 : EmitIntValue(ValueToEmit, EmissionSize);
943 1536 : Emitted += EmissionSize;
944 : }
945 : return;
946 : }
947 :
948 : assert(Directive && "Invalid size for machine code value!");
949 468517 : OS << Directive;
950 468517 : if (MCTargetStreamer *TS = getTargetStreamer()) {
951 452235 : TS->emitValue(Value);
952 : } else {
953 16282 : Value->print(OS, MAI);
954 16282 : EmitEOL();
955 : }
956 : }
957 :
958 2118 : void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
959 : int64_t IntValue;
960 2118 : if (Value->evaluateAsAbsolute(IntValue)) {
961 4 : EmitULEB128IntValue(IntValue);
962 4 : return;
963 : }
964 2114 : OS << "\t.uleb128 ";
965 2114 : Value->print(OS, MAI);
966 2114 : EmitEOL();
967 : }
968 :
969 4 : void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
970 : int64_t IntValue;
971 4 : if (Value->evaluateAsAbsolute(IntValue)) {
972 4 : EmitSLEB128IntValue(IntValue);
973 4 : return;
974 : }
975 0 : OS << "\t.sleb128 ";
976 0 : Value->print(OS, MAI);
977 0 : EmitEOL();
978 : }
979 :
980 3 : void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
981 : assert(MAI->getDTPRel64Directive() != nullptr);
982 3 : OS << MAI->getDTPRel64Directive();
983 3 : Value->print(OS, MAI);
984 3 : EmitEOL();
985 3 : }
986 :
987 3 : void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
988 : assert(MAI->getDTPRel32Directive() != nullptr);
989 3 : OS << MAI->getDTPRel32Directive();
990 3 : Value->print(OS, MAI);
991 3 : EmitEOL();
992 3 : }
993 :
994 2 : void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
995 : assert(MAI->getTPRel64Directive() != nullptr);
996 2 : OS << MAI->getTPRel64Directive();
997 2 : Value->print(OS, MAI);
998 2 : EmitEOL();
999 2 : }
1000 :
1001 2 : void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
1002 : assert(MAI->getTPRel32Directive() != nullptr);
1003 2 : OS << MAI->getTPRel32Directive();
1004 2 : Value->print(OS, MAI);
1005 2 : EmitEOL();
1006 2 : }
1007 :
1008 33 : void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
1009 : assert(MAI->getGPRel64Directive() != nullptr);
1010 33 : OS << MAI->getGPRel64Directive();
1011 33 : Value->print(OS, MAI);
1012 33 : EmitEOL();
1013 33 : }
1014 :
1015 19 : void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
1016 : assert(MAI->getGPRel32Directive() != nullptr);
1017 19 : OS << MAI->getGPRel32Directive();
1018 19 : Value->print(OS, MAI);
1019 19 : EmitEOL();
1020 19 : }
1021 :
1022 53380 : void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1023 : SMLoc Loc) {
1024 : int64_t IntNumBytes;
1025 53380 : if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0)
1026 53380 : return;
1027 :
1028 16716 : if (const char *ZeroDirective = MAI->getZeroDirective()) {
1029 : // FIXME: Emit location directives
1030 16716 : OS << ZeroDirective;
1031 16716 : NumBytes.print(OS, MAI);
1032 16716 : if (FillValue != 0)
1033 3736 : OS << ',' << (int)FillValue;
1034 16716 : EmitEOL();
1035 16716 : return;
1036 : }
1037 :
1038 0 : MCStreamer::emitFill(NumBytes, FillValue);
1039 : }
1040 :
1041 19 : void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1042 : int64_t Expr, SMLoc Loc) {
1043 : // FIXME: Emit location directives
1044 19 : OS << "\t.fill\t";
1045 19 : NumValues.print(OS, MAI);
1046 19 : OS << ", " << Size << ", 0x";
1047 19 : OS.write_hex(truncateToSize(Expr, 4));
1048 19 : EmitEOL();
1049 19 : }
1050 :
1051 220290 : void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
1052 : unsigned ValueSize,
1053 : unsigned MaxBytesToEmit) {
1054 : // Some assemblers don't support non-power of two alignments, so we always
1055 : // emit alignments as a power of two if possible.
1056 : if (isPowerOf2_32(ByteAlignment)) {
1057 220288 : switch (ValueSize) {
1058 0 : default:
1059 0 : llvm_unreachable("Invalid size for machine code value!");
1060 220277 : case 1:
1061 220277 : OS << "\t.p2align\t";
1062 220277 : break;
1063 4 : case 2:
1064 4 : OS << ".p2alignw ";
1065 4 : break;
1066 7 : case 4:
1067 7 : OS << ".p2alignl ";
1068 7 : break;
1069 : case 8:
1070 : llvm_unreachable("Unsupported alignment size!");
1071 : }
1072 :
1073 220288 : OS << Log2_32(ByteAlignment);
1074 :
1075 220288 : if (Value || MaxBytesToEmit) {
1076 99771 : OS << ", 0x";
1077 99771 : OS.write_hex(truncateToSize(Value, ValueSize));
1078 :
1079 99771 : if (MaxBytesToEmit)
1080 1 : OS << ", " << MaxBytesToEmit;
1081 : }
1082 220288 : EmitEOL();
1083 220288 : return;
1084 : }
1085 :
1086 : // Non-power of two alignment. This is not widely supported by assemblers.
1087 : // FIXME: Parameterize this based on MAI.
1088 2 : switch (ValueSize) {
1089 0 : default: llvm_unreachable("Invalid size for machine code value!");
1090 2 : case 1: OS << ".balign"; break;
1091 0 : case 2: OS << ".balignw"; break;
1092 0 : case 4: OS << ".balignl"; break;
1093 : case 8: llvm_unreachable("Unsupported alignment size!");
1094 : }
1095 :
1096 2 : OS << ' ' << ByteAlignment;
1097 2 : OS << ", " << truncateToSize(Value, ValueSize);
1098 2 : if (MaxBytesToEmit)
1099 0 : OS << ", " << MaxBytesToEmit;
1100 2 : EmitEOL();
1101 : }
1102 :
1103 189572 : void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
1104 : unsigned MaxBytesToEmit) {
1105 : // Emit with a text fill value.
1106 189572 : EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
1107 : 1, MaxBytesToEmit);
1108 189572 : }
1109 :
1110 9 : void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1111 : unsigned char Value,
1112 : SMLoc Loc) {
1113 : // FIXME: Verify that Offset is associated with the current section.
1114 9 : OS << ".org ";
1115 9 : Offset->print(OS, MAI);
1116 9 : OS << ", " << (unsigned)Value;
1117 9 : EmitEOL();
1118 9 : }
1119 :
1120 14045 : void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
1121 : assert(MAI->hasSingleParameterDotFile());
1122 14045 : OS << "\t.file\t";
1123 14045 : PrintQuotedString(Filename, OS);
1124 14045 : EmitEOL();
1125 14045 : }
1126 :
1127 392 : static void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
1128 : StringRef Filename,
1129 : MD5::MD5Result *Checksum,
1130 : Optional<StringRef> Source,
1131 : bool UseDwarfDirectory,
1132 : raw_svector_ostream &OS) {
1133 : SmallString<128> FullPathName;
1134 :
1135 392 : if (!UseDwarfDirectory && !Directory.empty()) {
1136 307 : if (sys::path::is_absolute(Filename))
1137 : Directory = "";
1138 : else {
1139 : FullPathName = Directory;
1140 259 : sys::path::append(FullPathName, Filename);
1141 : Directory = "";
1142 259 : Filename = FullPathName;
1143 : }
1144 : }
1145 :
1146 392 : OS << "\t.file\t" << FileNo << ' ';
1147 392 : if (!Directory.empty()) {
1148 43 : PrintQuotedString(Directory, OS);
1149 : OS << ' ';
1150 : }
1151 392 : PrintQuotedString(Filename, OS);
1152 392 : if (Checksum)
1153 16 : OS << " md5 0x" << Checksum->digest();
1154 392 : if (Source) {
1155 6 : OS << " source ";
1156 6 : PrintQuotedString(*Source, OS);
1157 : }
1158 392 : }
1159 :
1160 3393 : Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1161 : unsigned FileNo, StringRef Directory, StringRef Filename,
1162 : MD5::MD5Result *Checksum, Optional<StringRef> Source, unsigned CUID) {
1163 : assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
1164 :
1165 3393 : MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1166 3393 : unsigned NumFiles = Table.getMCDwarfFiles().size();
1167 : Expected<unsigned> FileNoOrErr =
1168 3393 : Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo);
1169 3393 : if (!FileNoOrErr)
1170 : return FileNoOrErr.takeError();
1171 3393 : FileNo = FileNoOrErr.get();
1172 3393 : if (NumFiles == Table.getMCDwarfFiles().size())
1173 : return FileNo;
1174 :
1175 : SmallString<128> Str;
1176 : raw_svector_ostream OS1(Str);
1177 385 : printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1178 385 : UseDwarfDirectory, OS1);
1179 :
1180 385 : if (MCTargetStreamer *TS = getTargetStreamer())
1181 762 : TS->emitDwarfFileDirective(OS1.str());
1182 : else
1183 12 : EmitRawText(OS1.str());
1184 :
1185 : return FileNo;
1186 : }
1187 :
1188 295 : void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
1189 : StringRef Filename,
1190 : MD5::MD5Result *Checksum,
1191 : Optional<StringRef> Source,
1192 : unsigned CUID) {
1193 : assert(CUID == 0);
1194 : // .file 0 is new for DWARF v5.
1195 295 : if (getContext().getDwarfVersion() < 5)
1196 288 : return;
1197 : // Inform MCDwarf about the root file.
1198 7 : getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1199 : Source);
1200 :
1201 : SmallString<128> Str;
1202 : raw_svector_ostream OS1(Str);
1203 7 : printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1204 7 : UseDwarfDirectory, OS1);
1205 :
1206 7 : if (MCTargetStreamer *TS = getTargetStreamer())
1207 14 : TS->emitDwarfFileDirective(OS1.str());
1208 : else
1209 0 : EmitRawText(OS1.str());
1210 : }
1211 :
1212 1523 : void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
1213 : unsigned Column, unsigned Flags,
1214 : unsigned Isa,
1215 : unsigned Discriminator,
1216 : StringRef FileName) {
1217 4569 : OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1218 1523 : if (MAI->supportsExtendedDwarfLocDirective()) {
1219 1486 : if (Flags & DWARF2_FLAG_BASIC_BLOCK)
1220 0 : OS << " basic_block";
1221 1486 : if (Flags & DWARF2_FLAG_PROLOGUE_END)
1222 332 : OS << " prologue_end";
1223 1486 : if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
1224 0 : OS << " epilogue_begin";
1225 :
1226 1486 : unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1227 1486 : if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
1228 348 : OS << " is_stmt ";
1229 :
1230 348 : if (Flags & DWARF2_FLAG_IS_STMT)
1231 150 : OS << "1";
1232 : else
1233 198 : OS << "0";
1234 : }
1235 :
1236 1486 : if (Isa)
1237 1 : OS << " isa " << Isa;
1238 1486 : if (Discriminator)
1239 6 : OS << " discriminator " << Discriminator;
1240 : }
1241 :
1242 1523 : if (IsVerboseAsm) {
1243 1377 : OS.PadToColumn(MAI->getCommentColumn());
1244 2754 : OS << MAI->getCommentString() << ' ' << FileName << ':'
1245 : << Line << ':' << Column;
1246 : }
1247 1523 : EmitEOL();
1248 1523 : this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
1249 : Isa, Discriminator, FileName);
1250 1523 : }
1251 :
1252 313 : MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1253 : // Always use the zeroth line table, since asm syntax only supports one line
1254 : // table for now.
1255 313 : return MCStreamer::getDwarfLineTableSymbol(0);
1256 : }
1257 :
1258 68 : bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1259 : ArrayRef<uint8_t> Checksum,
1260 : unsigned ChecksumKind) {
1261 68 : if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1262 : ChecksumKind))
1263 : return false;
1264 :
1265 68 : OS << "\t.cv_file\t" << FileNo << ' ';
1266 68 : PrintQuotedString(Filename, OS);
1267 :
1268 68 : if (!ChecksumKind) {
1269 27 : EmitEOL();
1270 27 : return true;
1271 : }
1272 :
1273 41 : OS << ' ';
1274 41 : PrintQuotedString(toHex(Checksum), OS);
1275 41 : OS << ' ' << ChecksumKind;
1276 :
1277 41 : EmitEOL();
1278 41 : return true;
1279 : }
1280 :
1281 106 : bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
1282 106 : OS << "\t.cv_func_id " << FuncId << '\n';
1283 106 : return MCStreamer::EmitCVFuncIdDirective(FuncId);
1284 : }
1285 :
1286 9 : bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
1287 : unsigned IAFunc,
1288 : unsigned IAFile,
1289 : unsigned IALine, unsigned IACol,
1290 : SMLoc Loc) {
1291 18 : OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1292 9 : << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1293 9 : return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
1294 9 : IALine, IACol, Loc);
1295 : }
1296 :
1297 433 : void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1298 : unsigned Line, unsigned Column,
1299 : bool PrologueEnd, bool IsStmt,
1300 : StringRef FileName, SMLoc Loc) {
1301 : // Validate the directive.
1302 433 : if (!checkCVLocSection(FunctionId, FileNo, Loc))
1303 : return;
1304 :
1305 1728 : OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1306 : << Column;
1307 432 : if (PrologueEnd)
1308 0 : OS << " prologue_end";
1309 :
1310 432 : if (IsStmt)
1311 0 : OS << " is_stmt 1";
1312 :
1313 432 : if (IsVerboseAsm) {
1314 432 : OS.PadToColumn(MAI->getCommentColumn());
1315 864 : OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1316 : << Column;
1317 : }
1318 432 : EmitEOL();
1319 : }
1320 :
1321 100 : void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
1322 : const MCSymbol *FnStart,
1323 : const MCSymbol *FnEnd) {
1324 200 : OS << "\t.cv_linetable\t" << FunctionId << ", ";
1325 100 : FnStart->print(OS, MAI);
1326 100 : OS << ", ";
1327 100 : FnEnd->print(OS, MAI);
1328 100 : EmitEOL();
1329 100 : this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
1330 100 : }
1331 :
1332 7 : void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
1333 : unsigned SourceFileId,
1334 : unsigned SourceLineNum,
1335 : const MCSymbol *FnStartSym,
1336 : const MCSymbol *FnEndSym) {
1337 7 : OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
1338 : << ' ' << SourceLineNum << ' ';
1339 7 : FnStartSym->print(OS, MAI);
1340 7 : OS << ' ';
1341 7 : FnEndSym->print(OS, MAI);
1342 7 : EmitEOL();
1343 7 : this->MCStreamer::EmitCVInlineLinetableDirective(
1344 : PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
1345 7 : }
1346 :
1347 119 : void MCAsmStreamer::EmitCVDefRangeDirective(
1348 : ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1349 : StringRef FixedSizePortion) {
1350 119 : OS << "\t.cv_def_range\t";
1351 240 : for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
1352 121 : OS << ' ';
1353 121 : Range.first->print(OS, MAI);
1354 121 : OS << ' ';
1355 121 : Range.second->print(OS, MAI);
1356 : }
1357 119 : OS << ", ";
1358 119 : PrintQuotedString(FixedSizePortion, OS);
1359 119 : EmitEOL();
1360 119 : this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
1361 119 : }
1362 :
1363 65 : void MCAsmStreamer::EmitCVStringTableDirective() {
1364 65 : OS << "\t.cv_stringtable";
1365 65 : EmitEOL();
1366 65 : }
1367 :
1368 63 : void MCAsmStreamer::EmitCVFileChecksumsDirective() {
1369 63 : OS << "\t.cv_filechecksums";
1370 63 : EmitEOL();
1371 63 : }
1372 :
1373 6 : void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
1374 6 : OS << "\t.cv_filechecksumoffset\t" << FileNo;
1375 6 : EmitEOL();
1376 6 : }
1377 :
1378 66 : void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
1379 66 : OS << "\t.cv_fpo_data\t";
1380 66 : ProcSym->print(OS, MAI);
1381 66 : EmitEOL();
1382 66 : }
1383 :
1384 366 : void MCAsmStreamer::EmitIdent(StringRef IdentString) {
1385 : assert(MAI->hasIdentDirective() && ".ident directive not supported");
1386 366 : OS << "\t.ident\t";
1387 366 : PrintQuotedString(IdentString, OS);
1388 366 : EmitEOL();
1389 366 : }
1390 :
1391 127 : void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
1392 127 : MCStreamer::EmitCFISections(EH, Debug);
1393 127 : OS << "\t.cfi_sections ";
1394 127 : if (EH) {
1395 0 : OS << ".eh_frame";
1396 0 : if (Debug)
1397 0 : OS << ", .debug_frame";
1398 127 : } else if (Debug) {
1399 127 : OS << ".debug_frame";
1400 : }
1401 :
1402 127 : EmitEOL();
1403 127 : }
1404 :
1405 109013 : void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
1406 109013 : OS << "\t.cfi_startproc";
1407 109013 : if (Frame.IsSimple)
1408 2 : OS << " simple";
1409 109013 : EmitEOL();
1410 109013 : }
1411 :
1412 109011 : void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1413 109011 : MCStreamer::EmitCFIEndProcImpl(Frame);
1414 109011 : OS << "\t.cfi_endproc";
1415 109011 : EmitEOL();
1416 109011 : }
1417 :
1418 22218 : void MCAsmStreamer::EmitRegisterName(int64_t Register) {
1419 22218 : if (!MAI->useDwarfRegNumForCFI()) {
1420 : // User .cfi_* directives can use arbitrary DWARF register numbers, not
1421 : // just ones that map to LLVM register numbers and have known names.
1422 : // Fall back to using the original number directly if no name is known.
1423 19264 : const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1424 19264 : int LLVMRegister = MRI->getLLVMRegNumFromEH(Register);
1425 19264 : if (LLVMRegister != -1) {
1426 19263 : InstPrinter->printRegName(OS, LLVMRegister);
1427 19263 : return;
1428 : }
1429 : }
1430 2955 : OS << Register;
1431 : }
1432 :
1433 2257 : void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
1434 2257 : MCStreamer::EmitCFIDefCfa(Register, Offset);
1435 2257 : OS << "\t.cfi_def_cfa ";
1436 2257 : EmitRegisterName(Register);
1437 2257 : OS << ", " << Offset;
1438 2257 : EmitEOL();
1439 2257 : }
1440 :
1441 15138 : void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
1442 15138 : MCStreamer::EmitCFIDefCfaOffset(Offset);
1443 15138 : OS << "\t.cfi_def_cfa_offset " << Offset;
1444 15138 : EmitEOL();
1445 15138 : }
1446 :
1447 22 : static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
1448 22 : OS << "\t.cfi_escape ";
1449 22 : if (!Values.empty()) {
1450 22 : size_t e = Values.size() - 1;
1451 44 : for (size_t i = 0; i < e; ++i)
1452 44 : OS << format("0x%02x", uint8_t(Values[i])) << ", ";
1453 44 : OS << format("0x%02x", uint8_t(Values[e]));
1454 : }
1455 22 : }
1456 :
1457 0 : void MCAsmStreamer::EmitCFIEscape(StringRef Values) {
1458 0 : MCStreamer::EmitCFIEscape(Values);
1459 0 : PrintCFIEscape(OS, Values);
1460 0 : EmitEOL();
1461 0 : }
1462 :
1463 22 : void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
1464 22 : MCStreamer::EmitCFIGnuArgsSize(Size);
1465 :
1466 22 : uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
1467 22 : unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
1468 :
1469 44 : PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
1470 22 : EmitEOL();
1471 22 : }
1472 :
1473 1457 : void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
1474 1457 : MCStreamer::EmitCFIDefCfaRegister(Register);
1475 1457 : OS << "\t.cfi_def_cfa_register ";
1476 1457 : EmitRegisterName(Register);
1477 1457 : EmitEOL();
1478 1457 : }
1479 :
1480 18477 : void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
1481 18477 : this->MCStreamer::EmitCFIOffset(Register, Offset);
1482 18477 : OS << "\t.cfi_offset ";
1483 18477 : EmitRegisterName(Register);
1484 18477 : OS << ", " << Offset;
1485 18477 : EmitEOL();
1486 18477 : }
1487 :
1488 208 : void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
1489 : unsigned Encoding) {
1490 208 : MCStreamer::EmitCFIPersonality(Sym, Encoding);
1491 416 : OS << "\t.cfi_personality " << Encoding << ", ";
1492 208 : Sym->print(OS, MAI);
1493 208 : EmitEOL();
1494 208 : }
1495 :
1496 208 : void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1497 208 : MCStreamer::EmitCFILsda(Sym, Encoding);
1498 416 : OS << "\t.cfi_lsda " << Encoding << ", ";
1499 208 : Sym->print(OS, MAI);
1500 208 : EmitEOL();
1501 208 : }
1502 :
1503 28 : void MCAsmStreamer::EmitCFIRememberState() {
1504 28 : MCStreamer::EmitCFIRememberState();
1505 28 : OS << "\t.cfi_remember_state";
1506 28 : EmitEOL();
1507 28 : }
1508 :
1509 28 : void MCAsmStreamer::EmitCFIRestoreState() {
1510 28 : MCStreamer::EmitCFIRestoreState();
1511 28 : OS << "\t.cfi_restore_state";
1512 28 : EmitEOL();
1513 28 : }
1514 :
1515 4 : void MCAsmStreamer::EmitCFIRestore(int64_t Register) {
1516 4 : MCStreamer::EmitCFIRestore(Register);
1517 4 : OS << "\t.cfi_restore ";
1518 4 : EmitRegisterName(Register);
1519 4 : EmitEOL();
1520 4 : }
1521 :
1522 2 : void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
1523 2 : MCStreamer::EmitCFISameValue(Register);
1524 2 : OS << "\t.cfi_same_value ";
1525 2 : EmitRegisterName(Register);
1526 2 : EmitEOL();
1527 2 : }
1528 :
1529 21 : void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
1530 21 : MCStreamer::EmitCFIRelOffset(Register, Offset);
1531 21 : OS << "\t.cfi_rel_offset ";
1532 21 : EmitRegisterName(Register);
1533 21 : OS << ", " << Offset;
1534 21 : EmitEOL();
1535 21 : }
1536 :
1537 1621 : void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
1538 1621 : MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
1539 1621 : OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
1540 1621 : EmitEOL();
1541 1621 : }
1542 :
1543 0 : void MCAsmStreamer::EmitCFISignalFrame() {
1544 0 : MCStreamer::EmitCFISignalFrame();
1545 0 : OS << "\t.cfi_signal_frame";
1546 0 : EmitEOL();
1547 0 : }
1548 :
1549 0 : void MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
1550 0 : MCStreamer::EmitCFIUndefined(Register);
1551 0 : OS << "\t.cfi_undefined " << Register;
1552 0 : EmitEOL();
1553 0 : }
1554 :
1555 394 : void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
1556 394 : MCStreamer::EmitCFIRegister(Register1, Register2);
1557 394 : OS << "\t.cfi_register " << Register1 << ", " << Register2;
1558 394 : EmitEOL();
1559 394 : }
1560 :
1561 392 : void MCAsmStreamer::EmitCFIWindowSave() {
1562 392 : MCStreamer::EmitCFIWindowSave();
1563 392 : OS << "\t.cfi_window_save";
1564 392 : EmitEOL();
1565 392 : }
1566 :
1567 3 : void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
1568 3 : MCStreamer::EmitCFIReturnColumn(Register);
1569 3 : OS << "\t.cfi_return_column " << Register;
1570 3 : EmitEOL();
1571 3 : }
1572 :
1573 465 : void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
1574 465 : MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
1575 :
1576 465 : OS << ".seh_proc ";
1577 465 : Symbol->print(OS, MAI);
1578 465 : EmitEOL();
1579 465 : }
1580 :
1581 464 : void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
1582 464 : MCStreamer::EmitWinCFIEndProc(Loc);
1583 :
1584 464 : OS << "\t.seh_endproc";
1585 464 : EmitEOL();
1586 464 : }
1587 :
1588 1 : void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
1589 1 : MCStreamer::EmitWinCFIStartChained(Loc);
1590 :
1591 1 : OS << "\t.seh_startchained";
1592 1 : EmitEOL();
1593 1 : }
1594 :
1595 1 : void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
1596 1 : MCStreamer::EmitWinCFIEndChained(Loc);
1597 :
1598 1 : OS << "\t.seh_endchained";
1599 1 : EmitEOL();
1600 1 : }
1601 :
1602 131 : void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
1603 : bool Except, SMLoc Loc) {
1604 131 : MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
1605 :
1606 131 : OS << "\t.seh_handler ";
1607 131 : Sym->print(OS, MAI);
1608 131 : if (Unwind)
1609 130 : OS << ", @unwind";
1610 131 : if (Except)
1611 131 : OS << ", @except";
1612 131 : EmitEOL();
1613 131 : }
1614 :
1615 464 : void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
1616 464 : MCStreamer::EmitWinEHHandlerData(Loc);
1617 :
1618 : // Switch sections. Don't call SwitchSection directly, because that will
1619 : // cause the section switch to be visible in the emitted assembly.
1620 : // We only do this so the section switch that terminates the handler
1621 : // data block is visible.
1622 464 : WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
1623 464 : MCSection *TextSec = &CurFrame->Function->getSection();
1624 464 : MCSection *XData = getAssociatedXDataSection(TextSec);
1625 : SwitchSectionNoChange(XData);
1626 :
1627 464 : OS << "\t.seh_handlerdata";
1628 464 : EmitEOL();
1629 464 : }
1630 :
1631 414 : void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
1632 414 : MCStreamer::EmitWinCFIPushReg(Register, Loc);
1633 :
1634 414 : OS << "\t.seh_pushreg " << Register;
1635 414 : EmitEOL();
1636 414 : }
1637 :
1638 92 : void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
1639 : SMLoc Loc) {
1640 92 : MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
1641 :
1642 184 : OS << "\t.seh_setframe " << Register << ", " << Offset;
1643 92 : EmitEOL();
1644 92 : }
1645 :
1646 437 : void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
1647 437 : MCStreamer::EmitWinCFIAllocStack(Size, Loc);
1648 :
1649 437 : OS << "\t.seh_stackalloc " << Size;
1650 437 : EmitEOL();
1651 437 : }
1652 :
1653 1 : void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
1654 : SMLoc Loc) {
1655 1 : MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
1656 :
1657 2 : OS << "\t.seh_savereg " << Register << ", " << Offset;
1658 1 : EmitEOL();
1659 1 : }
1660 :
1661 191 : void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
1662 : SMLoc Loc) {
1663 191 : MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
1664 :
1665 382 : OS << "\t.seh_savexmm " << Register << ", " << Offset;
1666 191 : EmitEOL();
1667 191 : }
1668 :
1669 1 : void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
1670 1 : MCStreamer::EmitWinCFIPushFrame(Code, Loc);
1671 :
1672 1 : OS << "\t.seh_pushframe";
1673 1 : if (Code)
1674 1 : OS << " @code";
1675 1 : EmitEOL();
1676 1 : }
1677 :
1678 465 : void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
1679 465 : MCStreamer::EmitWinCFIEndProlog(Loc);
1680 :
1681 465 : OS << "\t.seh_endprologue";
1682 465 : EmitEOL();
1683 465 : }
1684 :
1685 6 : void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
1686 : const MCSymbolRefExpr *To,
1687 : uint64_t Count) {
1688 6 : OS << "\t.cg_profile ";
1689 6 : From->getSymbol().print(OS, MAI);
1690 6 : OS << ", ";
1691 6 : To->getSymbol().print(OS, MAI);
1692 6 : OS << ", " << Count;
1693 6 : EmitEOL();
1694 6 : }
1695 :
1696 2064464 : void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
1697 : const MCSubtargetInfo &STI,
1698 : bool PrintSchedInfo) {
1699 : raw_ostream &OS = GetCommentOS();
1700 : SmallString<256> Code;
1701 : SmallVector<MCFixup, 4> Fixups;
1702 : raw_svector_ostream VecOS(Code);
1703 :
1704 : // If we have no code emitter, don't emit code.
1705 2064464 : if (!getAssembler().getEmitterPtr())
1706 : return;
1707 :
1708 450979 : getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
1709 :
1710 : // If we are showing fixups, create symbolic markers in the encoded
1711 : // representation. We do this by making a per-bit map to the fixup item index,
1712 : // then trying to display it as nicely as possible.
1713 : SmallVector<uint8_t, 64> FixupMap;
1714 901956 : FixupMap.resize(Code.size() * 8);
1715 22658194 : for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
1716 44414432 : FixupMap[i] = 0;
1717 :
1718 456681 : for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1719 5703 : MCFixup &F = Fixups[i];
1720 : const MCFixupKindInfo &Info =
1721 5703 : getAssembler().getBackend().getFixupKindInfo(F.getKind());
1722 108996 : for (unsigned j = 0; j != Info.TargetSize; ++j) {
1723 103293 : unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
1724 : assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
1725 206586 : FixupMap[Index] = 1 + i;
1726 : }
1727 : }
1728 :
1729 : // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
1730 : // high order halfword of a 32-bit Thumb2 instruction is emitted first.
1731 450978 : OS << "encoding: [";
1732 3226880 : for (unsigned i = 0, e = Code.size(); i != e; ++i) {
1733 2775902 : if (i)
1734 : OS << ',';
1735 :
1736 : // See if all bits are the same map entry.
1737 5551804 : uint8_t MapEntry = FixupMap[i * 8 + 0];
1738 22197593 : for (unsigned j = 1; j != 8; ++j) {
1739 38848136 : if (FixupMap[i * 8 + j] == MapEntry)
1740 : continue;
1741 :
1742 : MapEntry = uint8_t(~0U);
1743 : break;
1744 : }
1745 :
1746 2775902 : if (MapEntry != uint8_t(~0U)) {
1747 2773525 : if (MapEntry == 0) {
1748 8286288 : OS << format("0x%02x", uint8_t(Code[i]));
1749 : } else {
1750 22858 : if (Code[i]) {
1751 : // FIXME: Some of the 8 bits require fix up.
1752 1377 : OS << format("0x%02x", uint8_t(Code[i])) << '\''
1753 459 : << char('A' + MapEntry - 1) << '\'';
1754 : } else
1755 10970 : OS << char('A' + MapEntry - 1);
1756 : }
1757 : } else {
1758 : // Otherwise, write out in binary.
1759 2377 : OS << "0b";
1760 21393 : for (unsigned j = 8; j--;) {
1761 19016 : unsigned Bit = (Code[i] >> j) & 1;
1762 :
1763 : unsigned FixupBit;
1764 19016 : if (MAI->isLittleEndian())
1765 10304 : FixupBit = i * 8 + j;
1766 : else
1767 8712 : FixupBit = i * 8 + (7-j);
1768 :
1769 38032 : if (uint8_t MapEntry = FixupMap[FixupBit]) {
1770 : assert(Bit == 0 && "Encoder wrote into fixed up bit!");
1771 11861 : OS << char('A' + MapEntry - 1);
1772 : } else
1773 : OS << Bit;
1774 : }
1775 : }
1776 : }
1777 450978 : OS << "]";
1778 : // If we are not going to add fixup or schedule comments after this point
1779 : // then we have to end the current comment line with "\n".
1780 450978 : if (Fixups.size() || !PrintSchedInfo)
1781 450978 : OS << "\n";
1782 :
1783 456681 : for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1784 5703 : MCFixup &F = Fixups[i];
1785 : const MCFixupKindInfo &Info =
1786 5703 : getAssembler().getBackend().getFixupKindInfo(F.getKind());
1787 11406 : OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
1788 5703 : << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
1789 : }
1790 : }
1791 :
1792 2064464 : void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
1793 : const MCSubtargetInfo &STI,
1794 : bool PrintSchedInfo) {
1795 : assert(getCurrentSectionOnly() &&
1796 : "Cannot emit contents before setting section!");
1797 :
1798 : // Show the encoding in a comment if we have a code emitter.
1799 2064464 : AddEncodingComment(Inst, STI, PrintSchedInfo);
1800 :
1801 : // Show the MCInst if enabled.
1802 2064463 : if (ShowInst) {
1803 8617 : if (PrintSchedInfo)
1804 0 : GetCommentOS() << "\n";
1805 8617 : Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
1806 8617 : GetCommentOS() << "\n";
1807 : }
1808 :
1809 2064463 : if(getTargetStreamer())
1810 3811850 : getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI);
1811 : else
1812 317076 : InstPrinter->printInst(&Inst, OS, "", STI);
1813 :
1814 2064463 : if (PrintSchedInfo) {
1815 63580 : std::string SI = STI.getSchedInfoStr(Inst);
1816 63580 : if (!SI.empty())
1817 : GetCommentOS() << SI;
1818 : }
1819 :
1820 : StringRef Comments = CommentToEmit;
1821 2064463 : if (Comments.size() && Comments.back() != '\n')
1822 121857 : GetCommentOS() << "\n";
1823 :
1824 2064463 : EmitEOL();
1825 2064463 : }
1826 :
1827 1 : void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
1828 1 : OS << "\t.bundle_align_mode " << AlignPow2;
1829 1 : EmitEOL();
1830 1 : }
1831 :
1832 4 : void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
1833 4 : OS << "\t.bundle_lock";
1834 4 : if (AlignToEnd)
1835 3 : OS << " align_to_end";
1836 4 : EmitEOL();
1837 4 : }
1838 :
1839 2 : void MCAsmStreamer::EmitBundleUnlock() {
1840 2 : OS << "\t.bundle_unlock";
1841 2 : EmitEOL();
1842 2 : }
1843 :
1844 102 : bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
1845 : const MCExpr *Expr, SMLoc,
1846 : const MCSubtargetInfo &STI) {
1847 102 : OS << "\t.reloc ";
1848 102 : Offset.print(OS, MAI);
1849 102 : OS << ", " << Name;
1850 102 : if (Expr) {
1851 99 : OS << ", ";
1852 99 : Expr->print(OS, MAI);
1853 : }
1854 102 : EmitEOL();
1855 102 : return false;
1856 : }
1857 :
1858 50 : void MCAsmStreamer::EmitAddrsig() {
1859 50 : OS << "\t.addrsig";
1860 50 : EmitEOL();
1861 50 : }
1862 :
1863 27 : void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
1864 27 : OS << "\t.addrsig_sym ";
1865 27 : Sym->print(OS, MAI);
1866 27 : EmitEOL();
1867 27 : }
1868 :
1869 : /// EmitRawText - If this file is backed by an assembly streamer, this dumps
1870 : /// the specified string in the output .s file. This capability is
1871 : /// indicated by the hasRawTextSupport() predicate.
1872 463325 : void MCAsmStreamer::EmitRawTextImpl(StringRef String) {
1873 463325 : if (!String.empty() && String.back() == '\n')
1874 8921 : String = String.substr(0, String.size()-1);
1875 463325 : OS << String;
1876 463325 : EmitEOL();
1877 463325 : }
1878 :
1879 20706 : void MCAsmStreamer::FinishImpl() {
1880 : // If we are generating dwarf for assembly source files dump out the sections.
1881 20706 : if (getContext().getGenDwarfForAssembly())
1882 6 : MCGenDwarfInfo::Emit(this);
1883 :
1884 : // Emit the label for the line table, if requested - since the rest of the
1885 : // line table will be defined by .loc/.file directives, and not emitted
1886 : // directly, the label is the only work required here.
1887 20706 : auto &Tables = getContext().getMCDwarfLineTables();
1888 20706 : if (!Tables.empty()) {
1889 : assert(Tables.size() == 1 && "asm output only supports one line table");
1890 317 : if (auto *Label = Tables.begin()->second.getLabel()) {
1891 302 : SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
1892 302 : EmitLabel(Label);
1893 : }
1894 : }
1895 20706 : }
1896 :
1897 23058 : MCStreamer *llvm::createAsmStreamer(MCContext &Context,
1898 : std::unique_ptr<formatted_raw_ostream> OS,
1899 : bool isVerboseAsm, bool useDwarfDirectory,
1900 : MCInstPrinter *IP,
1901 : std::unique_ptr<MCCodeEmitter> &&CE,
1902 : std::unique_ptr<MCAsmBackend> &&MAB,
1903 : bool ShowInst) {
1904 : return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
1905 : useDwarfDirectory, IP, std::move(CE), std::move(MAB),
1906 46116 : ShowInst);
1907 : }
|