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