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