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