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