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