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