1296417Sdim//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===// 2195098Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6195098Sed// 7195098Sed//===----------------------------------------------------------------------===// 8195098Sed 9341825Sdim#include "llvm/ADT/Optional.h" 10280031Sdim#include "llvm/ADT/STLExtras.h" 11249423Sdim#include "llvm/ADT/SmallString.h" 12249423Sdim#include "llvm/ADT/StringExtras.h" 13249423Sdim#include "llvm/ADT/Twine.h" 14360784Sdim#include "llvm/DebugInfo/CodeView/SymbolRecord.h" 15249423Sdim#include "llvm/MC/MCAsmBackend.h" 16198090Srdivacky#include "llvm/MC/MCAsmInfo.h" 17341825Sdim#include "llvm/MC/MCAssembler.h" 18198090Srdivacky#include "llvm/MC/MCCodeEmitter.h" 19314564Sdim#include "llvm/MC/MCCodeView.h" 20195098Sed#include "llvm/MC/MCContext.h" 21198090Srdivacky#include "llvm/MC/MCExpr.h" 22218893Sdim#include "llvm/MC/MCFixupKindInfo.h" 23195340Sed#include "llvm/MC/MCInst.h" 24198090Srdivacky#include "llvm/MC/MCInstPrinter.h" 25226633Sdim#include "llvm/MC/MCObjectFileInfo.h" 26341825Sdim#include "llvm/MC/MCObjectWriter.h" 27360784Sdim#include "llvm/MC/MCRegister.h" 28226633Sdim#include "llvm/MC/MCRegisterInfo.h" 29198090Srdivacky#include "llvm/MC/MCSectionMachO.h" 30309124Sdim#include "llvm/MC/MCStreamer.h" 31198090Srdivacky#include "llvm/Support/ErrorHandling.h" 32198090Srdivacky#include "llvm/Support/Format.h" 33202878Srdivacky#include "llvm/Support/FormattedStream.h" 34296417Sdim#include "llvm/Support/LEB128.h" 35249423Sdim#include "llvm/Support/MathExtras.h" 36261991Sdim#include "llvm/Support/Path.h" 37341825Sdim#include "llvm/Support/TargetRegistry.h" 38218893Sdim#include <cctype> 39296417Sdim 40195098Sedusing namespace llvm; 41195098Sed 42195098Sednamespace { 43195098Sed 44288943Sdimclass MCAsmStreamer final : public MCStreamer { 45288943Sdim std::unique_ptr<formatted_raw_ostream> OSOwner; 46202878Srdivacky formatted_raw_ostream &OS; 47261991Sdim const MCAsmInfo *MAI; 48276479Sdim std::unique_ptr<MCInstPrinter> InstPrinter; 49341825Sdim std::unique_ptr<MCAssembler> Assembler; 50218893Sdim 51309124Sdim SmallString<128> ExplicitCommentToEmit; 52202878Srdivacky SmallString<128> CommentToEmit; 53202878Srdivacky raw_svector_ostream CommentStream; 54341825Sdim raw_null_ostream NullStream; 55203954Srdivacky 56203954Srdivacky unsigned IsVerboseAsm : 1; 57203954Srdivacky unsigned ShowInst : 1; 58234353Sdim unsigned UseDwarfDirectory : 1; 59203954Srdivacky 60223017Sdim void EmitRegisterName(int64_t Register); 61276479Sdim void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; 62276479Sdim void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; 63223017Sdim 64198090Srdivackypublic: 65288943Sdim MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, 66276479Sdim bool isVerboseAsm, bool useDwarfDirectory, 67341825Sdim MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter, 68341825Sdim std::unique_ptr<MCAsmBackend> asmbackend, bool showInst) 69288943Sdim : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), 70341825Sdim MAI(Context.getAsmInfo()), InstPrinter(printer), 71360784Sdim Assembler(std::make_unique<MCAssembler>( 72341825Sdim Context, std::move(asmbackend), std::move(emitter), 73341825Sdim (asmbackend) ? asmbackend->createObjectWriter(NullStream) 74341825Sdim : nullptr)), 75341825Sdim CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), 76341825Sdim ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) { 77288943Sdim assert(InstPrinter); 78288943Sdim if (IsVerboseAsm) 79288943Sdim InstPrinter->setCommentStream(CommentStream); 80360784Sdim if (Assembler->getBackendPtr()) 81360784Sdim setAllowAutoPadding(Assembler->getBackend().allowAutoPadding()); 82203954Srdivacky } 83195098Sed 84341825Sdim MCAssembler &getAssembler() { return *Assembler; } 85341825Sdim MCAssembler *getAssemblerPtr() override { return nullptr; } 86341825Sdim 87202878Srdivacky inline void EmitEOL() { 88309124Sdim // Dump Explicit Comments here. 89309124Sdim emitExplicitComments(); 90202878Srdivacky // If we don't have any comments, just emit a \n. 91202878Srdivacky if (!IsVerboseAsm) { 92202878Srdivacky OS << '\n'; 93202878Srdivacky return; 94202878Srdivacky } 95202878Srdivacky EmitCommentsAndEOL(); 96202878Srdivacky } 97296417Sdim 98296417Sdim void EmitSyntaxDirective() override; 99296417Sdim 100202878Srdivacky void EmitCommentsAndEOL(); 101203954Srdivacky 102341825Sdim /// Return true if this streamer supports verbose assembly at all. 103276479Sdim bool isVerboseAsm() const override { return IsVerboseAsm; } 104218893Sdim 105341825Sdim /// Do we support EmitRawText? 106276479Sdim bool hasRawTextSupport() const override { return true; } 107203954Srdivacky 108341825Sdim /// Add a comment that can be emitted to the generated .s file to make the 109341825Sdim /// output of the compiler more readable. This only affects the MCAsmStreamer 110341825Sdim /// and only when verbose assembly output is enabled. 111314564Sdim void AddComment(const Twine &T, bool EOL = true) override; 112203954Srdivacky 113341825Sdim /// Add a comment showing the encoding of an instruction. 114353358Sdim void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); 115203954Srdivacky 116341825Sdim /// Return a raw_ostream that comments can be written to. 117202878Srdivacky /// Unlike AddComment, you are required to terminate comments with \n if you 118202878Srdivacky /// use this method. 119276479Sdim raw_ostream &GetCommentOS() override { 120202878Srdivacky if (!IsVerboseAsm) 121202878Srdivacky return nulls(); // Discard comments unless in verbose asm mode. 122202878Srdivacky return CommentStream; 123202878Srdivacky } 124203954Srdivacky 125276479Sdim void emitRawComment(const Twine &T, bool TabPrefix = true) override; 126276479Sdim 127309124Sdim void addExplicitComment(const Twine &T) override; 128309124Sdim void emitExplicitComments() override; 129309124Sdim 130341825Sdim /// Emit a blank line to a .s file to pretty it up. 131276479Sdim void AddBlankLine() override { 132202878Srdivacky EmitEOL(); 133202878Srdivacky } 134203954Srdivacky 135198090Srdivacky /// @name MCStreamer Interface 136198090Srdivacky /// @{ 137195098Sed 138288943Sdim void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; 139195098Sed 140331366Sdim void emitELFSymverDirective(StringRef AliasName, 141331366Sdim const MCSymbol *Aliasee) override; 142331366Sdim 143276479Sdim void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; 144321369Sdim void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; 145249423Sdim 146276479Sdim void EmitAssemblerFlag(MCAssemblerFlag Flag) override; 147276479Sdim void EmitLinkerOptions(ArrayRef<std::string> Options) override; 148276479Sdim void EmitDataRegion(MCDataRegionType Kind) override; 149276479Sdim void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, 150344779Sdim unsigned Update, VersionTuple SDKVersion) override; 151327952Sdim void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, 152344779Sdim unsigned Update, VersionTuple SDKVersion) override; 153276479Sdim void EmitThumbFunc(MCSymbol *Func) override; 154218893Sdim 155276479Sdim void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; 156276479Sdim void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; 157276479Sdim bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; 158249423Sdim 159276479Sdim void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; 160276479Sdim void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; 161276479Sdim void EmitCOFFSymbolStorageClass(int StorageClass) override; 162276479Sdim void EmitCOFFSymbolType(int Type) override; 163276479Sdim void EndCOFFSymbolDef() override; 164288943Sdim void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; 165341825Sdim void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; 166276479Sdim void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; 167314564Sdim void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; 168341825Sdim void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; 169360784Sdim void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size, 170360784Sdim MCSymbol *CsectSym, 171360784Sdim unsigned ByteAlign) override; 172314564Sdim void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; 173276479Sdim void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 174276479Sdim unsigned ByteAlignment) override; 175195098Sed 176341825Sdim /// Emit a local common (.lcomm) symbol. 177202878Srdivacky /// 178202878Srdivacky /// @param Symbol - The common symbol to emit. 179202878Srdivacky /// @param Size - The size of the common symbol. 180243830Sdim /// @param ByteAlignment - The alignment of the common symbol in bytes. 181276479Sdim void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 182276479Sdim unsigned ByteAlignment) override; 183218893Sdim 184288943Sdim void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, 185341825Sdim uint64_t Size = 0, unsigned ByteAlignment = 0, 186341825Sdim SMLoc Loc = SMLoc()) override; 187195098Sed 188288943Sdim void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, 189288943Sdim unsigned ByteAlignment = 0) override; 190218893Sdim 191309124Sdim void EmitBinaryData(StringRef Data) override; 192309124Sdim 193276479Sdim void EmitBytes(StringRef Data) override; 194195098Sed 195276479Sdim void EmitValueImpl(const MCExpr *Value, unsigned Size, 196296417Sdim SMLoc Loc = SMLoc()) override; 197276479Sdim void EmitIntValue(uint64_t Value, unsigned Size) override; 198353358Sdim void EmitIntValueInHex(uint64_t Value, unsigned Size) override; 199218893Sdim 200276479Sdim void EmitULEB128Value(const MCExpr *Value) override; 201218893Sdim 202276479Sdim void EmitSLEB128Value(const MCExpr *Value) override; 203218893Sdim 204314564Sdim void EmitDTPRel32Value(const MCExpr *Value) override; 205314564Sdim void EmitDTPRel64Value(const MCExpr *Value) override; 206314564Sdim void EmitTPRel32Value(const MCExpr *Value) override; 207314564Sdim void EmitTPRel64Value(const MCExpr *Value) override; 208314564Sdim 209276479Sdim void EmitGPRel64Value(const MCExpr *Value) override; 210234353Sdim 211276479Sdim void EmitGPRel32Value(const MCExpr *Value) override; 212195098Sed 213309124Sdim void emitFill(const MCExpr &NumBytes, uint64_t FillValue, 214309124Sdim SMLoc Loc = SMLoc()) override; 215309124Sdim 216309124Sdim void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, 217309124Sdim SMLoc Loc = SMLoc()) override; 218309124Sdim 219276479Sdim void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 220276479Sdim unsigned ValueSize = 1, 221276479Sdim unsigned MaxBytesToEmit = 0) override; 222195098Sed 223276479Sdim void EmitCodeAlignment(unsigned ByteAlignment, 224276479Sdim unsigned MaxBytesToEmit = 0) override; 225204642Srdivacky 226296417Sdim void emitValueToOffset(const MCExpr *Offset, 227314564Sdim unsigned char Value, 228314564Sdim SMLoc Loc) override; 229203954Srdivacky 230276479Sdim void EmitFileDirective(StringRef Filename) override; 231341825Sdim Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo, 232341825Sdim StringRef Directory, 233341825Sdim StringRef Filename, 234353358Sdim Optional<MD5::MD5Result> Checksum = None, 235341825Sdim Optional<StringRef> Source = None, 236341825Sdim unsigned CUID = 0) override; 237341825Sdim void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, 238353358Sdim Optional<MD5::MD5Result> Checksum, 239341825Sdim Optional<StringRef> Source, 240341825Sdim unsigned CUID = 0) override; 241276479Sdim void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 242276479Sdim unsigned Column, unsigned Flags, 243276479Sdim unsigned Isa, unsigned Discriminator, 244276479Sdim StringRef FileName) override; 245276479Sdim MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; 246203954Srdivacky 247327952Sdim bool EmitCVFileDirective(unsigned FileNo, StringRef Filename, 248327952Sdim ArrayRef<uint8_t> Checksum, 249327952Sdim unsigned ChecksumKind) override; 250314564Sdim bool EmitCVFuncIdDirective(unsigned FuncId) override; 251314564Sdim bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, 252314564Sdim unsigned IAFile, unsigned IALine, 253314564Sdim unsigned IACol, SMLoc Loc) override; 254309124Sdim void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, 255309124Sdim unsigned Column, bool PrologueEnd, bool IsStmt, 256314564Sdim StringRef FileName, SMLoc Loc) override; 257309124Sdim void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, 258309124Sdim const MCSymbol *FnEnd) override; 259314564Sdim void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 260314564Sdim unsigned SourceFileId, 261314564Sdim unsigned SourceLineNum, 262314564Sdim const MCSymbol *FnStartSym, 263314564Sdim const MCSymbol *FnEndSym) override; 264360784Sdim 265360784Sdim void PrintCVDefRangePrefix( 266360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges); 267360784Sdim 268309124Sdim void EmitCVDefRangeDirective( 269309124Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 270360784Sdim codeview::DefRangeRegisterRelHeader DRHdr) override; 271360784Sdim 272360784Sdim void EmitCVDefRangeDirective( 273360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 274360784Sdim codeview::DefRangeSubfieldRegisterHeader DRHdr) override; 275360784Sdim 276360784Sdim void EmitCVDefRangeDirective( 277360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 278360784Sdim codeview::DefRangeRegisterHeader DRHdr) override; 279360784Sdim 280360784Sdim void EmitCVDefRangeDirective( 281360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 282360784Sdim codeview::DefRangeFramePointerRelHeader DRHdr) override; 283360784Sdim 284309124Sdim void EmitCVStringTableDirective() override; 285309124Sdim void EmitCVFileChecksumsDirective() override; 286327952Sdim void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override; 287327952Sdim void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override; 288309124Sdim 289276479Sdim void EmitIdent(StringRef IdentString) override; 290344779Sdim void EmitCFIBKeyFrame() override; 291276479Sdim void EmitCFISections(bool EH, bool Debug) override; 292276479Sdim void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; 293276479Sdim void EmitCFIDefCfaOffset(int64_t Offset) override; 294276479Sdim void EmitCFIDefCfaRegister(int64_t Register) override; 295276479Sdim void EmitCFIOffset(int64_t Register, int64_t Offset) override; 296276479Sdim void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; 297276479Sdim void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; 298276479Sdim void EmitCFIRememberState() override; 299276479Sdim void EmitCFIRestoreState() override; 300327952Sdim void EmitCFIRestore(int64_t Register) override; 301276479Sdim void EmitCFISameValue(int64_t Register) override; 302276479Sdim void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; 303276479Sdim void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; 304296417Sdim void EmitCFIEscape(StringRef Values) override; 305296417Sdim void EmitCFIGnuArgsSize(int64_t Size) override; 306276479Sdim void EmitCFISignalFrame() override; 307276479Sdim void EmitCFIUndefined(int64_t Register) override; 308276479Sdim void EmitCFIRegister(int64_t Register1, int64_t Register2) override; 309276479Sdim void EmitCFIWindowSave() override; 310344779Sdim void EmitCFINegateRAState() override; 311327952Sdim void EmitCFIReturnColumn(int64_t Register) override; 312218893Sdim 313327952Sdim void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; 314327952Sdim void EmitWinCFIEndProc(SMLoc Loc) override; 315344779Sdim void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override; 316327952Sdim void EmitWinCFIStartChained(SMLoc Loc) override; 317327952Sdim void EmitWinCFIEndChained(SMLoc Loc) override; 318360784Sdim void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override; 319360784Sdim void EmitWinCFISetFrame(MCRegister Register, unsigned Offset, 320327952Sdim SMLoc Loc) override; 321327952Sdim void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override; 322360784Sdim void EmitWinCFISaveReg(MCRegister Register, unsigned Offset, 323327952Sdim SMLoc Loc) override; 324360784Sdim void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset, 325327952Sdim SMLoc Loc) override; 326327952Sdim void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override; 327327952Sdim void EmitWinCFIEndProlog(SMLoc Loc) override; 328223017Sdim 329327952Sdim void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, 330327952Sdim SMLoc Loc) override; 331327952Sdim void EmitWinEHHandlerData(SMLoc Loc) override; 332218893Sdim 333341825Sdim void emitCGProfileEntry(const MCSymbolRefExpr *From, 334341825Sdim const MCSymbolRefExpr *To, uint64_t Count) override; 335341825Sdim 336353358Sdim void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; 337249423Sdim 338276479Sdim void EmitBundleAlignMode(unsigned AlignPow2) override; 339276479Sdim void EmitBundleLock(bool AlignToEnd) override; 340276479Sdim void EmitBundleUnlock() override; 341276479Sdim 342296417Sdim bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, 343341825Sdim const MCExpr *Expr, SMLoc Loc, 344341825Sdim const MCSubtargetInfo &STI) override; 345296417Sdim 346341825Sdim void EmitAddrsig() override; 347341825Sdim void EmitAddrsigSym(const MCSymbol *Sym) override; 348341825Sdim 349341825Sdim /// If this file is backed by an assembly streamer, this dumps the specified 350341825Sdim /// string in the output .s file. This capability is indicated by the 351341825Sdim /// hasRawTextSupport() predicate. 352276479Sdim void EmitRawTextImpl(StringRef String) override; 353218893Sdim 354276479Sdim void FinishImpl() override; 355198090Srdivacky}; 356195098Sed 357198090Srdivacky} // end anonymous namespace. 358195098Sed 359314564Sdimvoid MCAsmStreamer::AddComment(const Twine &T, bool EOL) { 360202878Srdivacky if (!IsVerboseAsm) return; 361218893Sdim 362202878Srdivacky T.toVector(CommentToEmit); 363341825Sdim 364314564Sdim if (EOL) 365314564Sdim CommentToEmit.push_back('\n'); // Place comment in a new line. 366202878Srdivacky} 367202878Srdivacky 368202878Srdivackyvoid MCAsmStreamer::EmitCommentsAndEOL() { 369202878Srdivacky if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 370202878Srdivacky OS << '\n'; 371202878Srdivacky return; 372202878Srdivacky } 373218893Sdim 374288943Sdim StringRef Comments = CommentToEmit; 375218893Sdim 376202878Srdivacky assert(Comments.back() == '\n' && 377202878Srdivacky "Comment array not newline terminated"); 378202878Srdivacky do { 379202878Srdivacky // Emit a line of comments. 380261991Sdim OS.PadToColumn(MAI->getCommentColumn()); 381202878Srdivacky size_t Position = Comments.find('\n'); 382261991Sdim OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; 383218893Sdim 384202878Srdivacky Comments = Comments.substr(Position+1); 385202878Srdivacky } while (!Comments.empty()); 386218893Sdim 387202878Srdivacky CommentToEmit.clear(); 388202878Srdivacky} 389202878Srdivacky 390195098Sedstatic inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 391309124Sdim assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); 392195098Sed return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 393195098Sed} 394195098Sed 395276479Sdimvoid MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { 396276479Sdim if (TabPrefix) 397276479Sdim OS << '\t'; 398276479Sdim OS << MAI->getCommentString() << T; 399276479Sdim EmitEOL(); 400276479Sdim} 401276479Sdim 402309124Sdimvoid MCAsmStreamer::addExplicitComment(const Twine &T) { 403309124Sdim StringRef c = T.getSingleStringRef(); 404309124Sdim if (c.equals(StringRef(MAI->getSeparatorString()))) 405309124Sdim return; 406309124Sdim if (c.startswith(StringRef("//"))) { 407309124Sdim ExplicitCommentToEmit.append("\t"); 408309124Sdim ExplicitCommentToEmit.append(MAI->getCommentString()); 409309124Sdim // drop // 410309124Sdim ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); 411309124Sdim } else if (c.startswith(StringRef("/*"))) { 412309124Sdim size_t p = 2, len = c.size() - 2; 413309124Sdim // emit each line in comment as separate newline. 414309124Sdim do { 415309124Sdim size_t newp = std::min(len, c.find_first_of("\r\n", p)); 416309124Sdim ExplicitCommentToEmit.append("\t"); 417309124Sdim ExplicitCommentToEmit.append(MAI->getCommentString()); 418309124Sdim ExplicitCommentToEmit.append(c.slice(p, newp).str()); 419309124Sdim // If we have another line in this comment add line 420309124Sdim if (newp < len) 421309124Sdim ExplicitCommentToEmit.append("\n"); 422309124Sdim p = newp + 1; 423309124Sdim } while (p < len); 424309124Sdim } else if (c.startswith(StringRef(MAI->getCommentString()))) { 425309124Sdim ExplicitCommentToEmit.append("\t"); 426309124Sdim ExplicitCommentToEmit.append(c.str()); 427309124Sdim } else if (c.front() == '#') { 428314564Sdim 429314564Sdim ExplicitCommentToEmit.append("\t"); 430314564Sdim ExplicitCommentToEmit.append(MAI->getCommentString()); 431314564Sdim ExplicitCommentToEmit.append(c.slice(1, c.size()).str()); 432309124Sdim } else 433309124Sdim assert(false && "Unexpected Assembly Comment"); 434309124Sdim // full line comments immediately output 435309124Sdim if (c.back() == '\n') 436309124Sdim emitExplicitComments(); 437309124Sdim} 438309124Sdim 439309124Sdimvoid MCAsmStreamer::emitExplicitComments() { 440309124Sdim StringRef Comments = ExplicitCommentToEmit; 441309124Sdim if (!Comments.empty()) 442309124Sdim OS << Comments; 443309124Sdim ExplicitCommentToEmit.clear(); 444309124Sdim} 445309124Sdim 446288943Sdimvoid MCAsmStreamer::ChangeSection(MCSection *Section, 447251662Sdim const MCExpr *Subsection) { 448198090Srdivacky assert(Section && "Cannot switch to a null section!"); 449327952Sdim if (MCTargetStreamer *TS = getTargetStreamer()) { 450327952Sdim TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS); 451327952Sdim } else { 452327952Sdim Section->PrintSwitchToSection( 453327952Sdim *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS, 454327952Sdim Subsection); 455327952Sdim } 456195098Sed} 457195098Sed 458331366Sdimvoid MCAsmStreamer::emitELFSymverDirective(StringRef AliasName, 459331366Sdim const MCSymbol *Aliasee) { 460331366Sdim OS << ".symver "; 461331366Sdim Aliasee->print(OS, MAI); 462331366Sdim OS << ", " << AliasName; 463331366Sdim EmitEOL(); 464331366Sdim} 465331366Sdim 466321369Sdimvoid MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { 467321369Sdim MCStreamer::EmitLabel(Symbol, Loc); 468195098Sed 469288943Sdim Symbol->print(OS, MAI); 470288943Sdim OS << MAI->getLabelSuffix(); 471288943Sdim 472202878Srdivacky EmitEOL(); 473195098Sed} 474195098Sed 475276479Sdimvoid MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { 476276479Sdim StringRef str = MCLOHIdToName(Kind); 477249423Sdim 478276479Sdim#ifndef NDEBUG 479276479Sdim int NbArgs = MCLOHIdToNbArgs(Kind); 480276479Sdim assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); 481276479Sdim assert(str != "" && "Invalid LOH name"); 482276479Sdim#endif 483276479Sdim 484276479Sdim OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; 485276479Sdim bool IsFirst = true; 486309124Sdim for (const MCSymbol *Arg : Args) { 487276479Sdim if (!IsFirst) 488276479Sdim OS << ", "; 489276479Sdim IsFirst = false; 490309124Sdim Arg->print(OS, MAI); 491276479Sdim } 492249423Sdim EmitEOL(); 493249423Sdim} 494249423Sdim 495202878Srdivackyvoid MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 496198090Srdivacky switch (Flag) { 497218893Sdim case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; 498202878Srdivacky case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 499261991Sdim case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; 500261991Sdim case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; 501261991Sdim case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; 502195098Sed } 503202878Srdivacky EmitEOL(); 504198090Srdivacky} 505195098Sed 506249423Sdimvoid MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { 507249423Sdim assert(!Options.empty() && "At least one option is required!"); 508249423Sdim OS << "\t.linker_option \"" << Options[0] << '"'; 509249423Sdim for (ArrayRef<std::string>::iterator it = Options.begin() + 1, 510249423Sdim ie = Options.end(); it != ie; ++it) { 511249423Sdim OS << ", " << '"' << *it << '"'; 512249423Sdim } 513309124Sdim EmitEOL(); 514249423Sdim} 515249423Sdim 516239462Sdimvoid MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { 517261991Sdim if (!MAI->doesSupportDataRegionDirectives()) 518239462Sdim return; 519239462Sdim switch (Kind) { 520239462Sdim case MCDR_DataRegion: OS << "\t.data_region"; break; 521239462Sdim case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; 522239462Sdim case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; 523239462Sdim case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; 524239462Sdim case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; 525239462Sdim } 526239462Sdim EmitEOL(); 527239462Sdim} 528239462Sdim 529327952Sdimstatic const char *getVersionMinDirective(MCVersionMinType Type) { 530327952Sdim switch (Type) { 531327952Sdim case MCVM_WatchOSVersionMin: return ".watchos_version_min"; 532327952Sdim case MCVM_TvOSVersionMin: return ".tvos_version_min"; 533327952Sdim case MCVM_IOSVersionMin: return ".ios_version_min"; 534327952Sdim case MCVM_OSXVersionMin: return ".macosx_version_min"; 535327952Sdim } 536327952Sdim llvm_unreachable("Invalid MC version min type"); 537327952Sdim} 538327952Sdim 539344779Sdimstatic void EmitSDKVersionSuffix(raw_ostream &OS, 540344779Sdim const VersionTuple &SDKVersion) { 541344779Sdim if (SDKVersion.empty()) 542344779Sdim return; 543344779Sdim OS << '\t' << "sdk_version " << SDKVersion.getMajor(); 544344779Sdim if (auto Minor = SDKVersion.getMinor()) { 545344779Sdim OS << ", " << *Minor; 546344779Sdim if (auto Subminor = SDKVersion.getSubminor()) { 547344779Sdim OS << ", " << *Subminor; 548344779Sdim } 549344779Sdim } 550344779Sdim} 551344779Sdim 552327952Sdimvoid MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major, 553344779Sdim unsigned Minor, unsigned Update, 554344779Sdim VersionTuple SDKVersion) { 555327952Sdim OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor; 556327952Sdim if (Update) 557327952Sdim OS << ", " << Update; 558344779Sdim EmitSDKVersionSuffix(OS, SDKVersion); 559327952Sdim EmitEOL(); 560327952Sdim} 561327952Sdim 562327952Sdimstatic const char *getPlatformName(MachO::PlatformType Type) { 563327952Sdim switch (Type) { 564344779Sdim case MachO::PLATFORM_MACOS: return "macos"; 565344779Sdim case MachO::PLATFORM_IOS: return "ios"; 566344779Sdim case MachO::PLATFORM_TVOS: return "tvos"; 567344779Sdim case MachO::PLATFORM_WATCHOS: return "watchos"; 568344779Sdim case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; 569353358Sdim case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; 570344779Sdim case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; 571344779Sdim case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; 572344779Sdim case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; 573276479Sdim } 574327952Sdim llvm_unreachable("Invalid Mach-O platform type"); 575327952Sdim} 576327952Sdim 577327952Sdimvoid MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, 578344779Sdim unsigned Minor, unsigned Update, 579344779Sdim VersionTuple SDKVersion) { 580327952Sdim const char *PlatformName = getPlatformName((MachO::PlatformType)Platform); 581327952Sdim OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor; 582276479Sdim if (Update) 583276479Sdim OS << ", " << Update; 584344779Sdim EmitSDKVersionSuffix(OS, SDKVersion); 585276479Sdim EmitEOL(); 586276479Sdim} 587276479Sdim 588218893Sdimvoid MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { 589218893Sdim // This needs to emit to a temporary string to get properly quoted 590218893Sdim // MCSymbols when they have spaces in them. 591218893Sdim OS << "\t.thumb_func"; 592223017Sdim // Only Mach-O hasSubsectionsViaSymbols() 593288943Sdim if (MAI->hasSubsectionsViaSymbols()) { 594288943Sdim OS << '\t'; 595288943Sdim Func->print(OS, MAI); 596288943Sdim } 597218893Sdim EmitEOL(); 598218893Sdim} 599218893Sdim 600198090Srdivackyvoid MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 601341825Sdim // Do not emit a .set on inlined target assignments. 602341825Sdim bool EmitSet = true; 603341825Sdim if (auto *E = dyn_cast<MCTargetExpr>(Value)) 604341825Sdim if (E->inlineAssignedExpr()) 605341825Sdim EmitSet = false; 606341825Sdim if (EmitSet) { 607341825Sdim OS << ".set "; 608341825Sdim Symbol->print(OS, MAI); 609341825Sdim OS << ", "; 610341825Sdim Value->print(OS, MAI); 611288943Sdim 612341825Sdim EmitEOL(); 613341825Sdim } 614198396Srdivacky 615276479Sdim MCStreamer::EmitAssignment(Symbol, Value); 616195098Sed} 617195098Sed 618218893Sdimvoid MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 619288943Sdim OS << ".weakref "; 620288943Sdim Alias->print(OS, MAI); 621288943Sdim OS << ", "; 622288943Sdim Symbol->print(OS, MAI); 623218893Sdim EmitEOL(); 624218893Sdim} 625218893Sdim 626261991Sdimbool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 627202878Srdivacky MCSymbolAttr Attribute) { 628195098Sed switch (Attribute) { 629234353Sdim case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); 630203954Srdivacky case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 631203954Srdivacky case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 632203954Srdivacky case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 633203954Srdivacky case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 634203954Srdivacky case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 635203954Srdivacky case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 636218893Sdim case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object 637261991Sdim if (!MAI->hasDotTypeDotSizeDirective()) 638261991Sdim return false; // Symbol attribute not supported 639288943Sdim OS << "\t.type\t"; 640288943Sdim Symbol->print(OS, MAI); 641288943Sdim OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); 642203954Srdivacky switch (Attribute) { 643261991Sdim default: return false; 644203954Srdivacky case MCSA_ELF_TypeFunction: OS << "function"; break; 645203954Srdivacky case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 646203954Srdivacky case MCSA_ELF_TypeObject: OS << "object"; break; 647203954Srdivacky case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 648203954Srdivacky case MCSA_ELF_TypeCommon: OS << "common"; break; 649341825Sdim case MCSA_ELF_TypeNoType: OS << "notype"; break; 650218893Sdim case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; 651203954Srdivacky } 652203954Srdivacky EmitEOL(); 653261991Sdim return true; 654203954Srdivacky case MCSA_Global: // .globl/.global 655261991Sdim OS << MAI->getGlobalDirective(); 656203954Srdivacky break; 657360784Sdim case MCSA_LGlobal: OS << "\t.lglobl\t"; break; 658210299Sed case MCSA_Hidden: OS << "\t.hidden\t"; break; 659210299Sed case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; 660210299Sed case MCSA_Internal: OS << "\t.internal\t"; break; 661210299Sed case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; 662210299Sed case MCSA_Local: OS << "\t.local\t"; break; 663280031Sdim case MCSA_NoDeadStrip: 664280031Sdim if (!MAI->hasNoDeadStrip()) 665280031Sdim return false; 666280031Sdim OS << "\t.no_dead_strip\t"; 667280031Sdim break; 668218893Sdim case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; 669309124Sdim case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; 670221345Sdim case MCSA_PrivateExtern: 671221345Sdim OS << "\t.private_extern\t"; 672221345Sdim break; 673210299Sed case MCSA_Protected: OS << "\t.protected\t"; break; 674210299Sed case MCSA_Reference: OS << "\t.reference\t"; break; 675280031Sdim case MCSA_Weak: OS << MAI->getWeakDirective(); break; 676221345Sdim case MCSA_WeakDefinition: 677221345Sdim OS << "\t.weak_definition\t"; 678221345Sdim break; 679202878Srdivacky // .weak_reference 680261991Sdim case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; 681210299Sed case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 682353358Sdim case MCSA_Cold: 683353358Sdim // Assemblers currently do not support a .cold directive. 684353358Sdim return false; 685195098Sed } 686195098Sed 687288943Sdim Symbol->print(OS, MAI); 688202878Srdivacky EmitEOL(); 689261991Sdim 690261991Sdim return true; 691195098Sed} 692195098Sed 693198090Srdivackyvoid MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 694288943Sdim OS << ".desc" << ' '; 695288943Sdim Symbol->print(OS, MAI); 696288943Sdim OS << ',' << DescValue; 697202878Srdivacky EmitEOL(); 698198090Srdivacky} 699198090Srdivacky 700296417Sdimvoid MCAsmStreamer::EmitSyntaxDirective() { 701309124Sdim if (MAI->getAssemblerDialect() == 1) { 702309124Sdim OS << "\t.intel_syntax noprefix"; 703309124Sdim EmitEOL(); 704309124Sdim } 705296417Sdim // FIXME: Currently emit unprefix'ed registers. 706341825Sdim // The intel_syntax directive has one optional argument 707296417Sdim // with may have a value of prefix or noprefix. 708296417Sdim} 709296417Sdim 710208599Srdivackyvoid MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { 711288943Sdim OS << "\t.def\t "; 712288943Sdim Symbol->print(OS, MAI); 713288943Sdim OS << ';'; 714208599Srdivacky EmitEOL(); 715208599Srdivacky} 716208599Srdivacky 717208599Srdivackyvoid MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { 718208599Srdivacky OS << "\t.scl\t" << StorageClass << ';'; 719208599Srdivacky EmitEOL(); 720208599Srdivacky} 721208599Srdivacky 722208599Srdivackyvoid MCAsmStreamer::EmitCOFFSymbolType (int Type) { 723208599Srdivacky OS << "\t.type\t" << Type << ';'; 724208599Srdivacky EmitEOL(); 725208599Srdivacky} 726208599Srdivacky 727208599Srdivackyvoid MCAsmStreamer::EndCOFFSymbolDef() { 728208599Srdivacky OS << "\t.endef"; 729208599Srdivacky EmitEOL(); 730208599Srdivacky} 731208599Srdivacky 732288943Sdimvoid MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { 733288943Sdim OS << "\t.safeseh\t"; 734288943Sdim Symbol->print(OS, MAI); 735288943Sdim EmitEOL(); 736288943Sdim} 737288943Sdim 738341825Sdimvoid MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { 739341825Sdim OS << "\t.symidx\t"; 740341825Sdim Symbol->print(OS, MAI); 741341825Sdim EmitEOL(); 742341825Sdim} 743341825Sdim 744276479Sdimvoid MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { 745288943Sdim OS << "\t.secidx\t"; 746288943Sdim Symbol->print(OS, MAI); 747276479Sdim EmitEOL(); 748276479Sdim} 749276479Sdim 750314564Sdimvoid MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { 751288943Sdim OS << "\t.secrel32\t"; 752288943Sdim Symbol->print(OS, MAI); 753314564Sdim if (Offset != 0) 754314564Sdim OS << '+' << Offset; 755234353Sdim EmitEOL(); 756234353Sdim} 757234353Sdim 758341825Sdimvoid MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) { 759341825Sdim OS << "\t.rva\t"; 760341825Sdim Symbol->print(OS, MAI); 761341825Sdim if (Offset > 0) 762341825Sdim OS << '+' << Offset; 763341825Sdim else if (Offset < 0) 764341825Sdim OS << '-' << -Offset; 765341825Sdim EmitEOL(); 766341825Sdim} 767341825Sdim 768360784Sdim// We need an XCOFF-specific version of this directive as the AIX syntax 769360784Sdim// requires a QualName argument identifying the csect name and storage mapping 770360784Sdim// class to appear before the alignment if we are specifying it. 771360784Sdimvoid MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, 772360784Sdim uint64_t Size, 773360784Sdim MCSymbol *CsectSym, 774360784Sdim unsigned ByteAlignment) { 775360784Sdim assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment && 776360784Sdim "We only support writing log base-2 alignment format with XCOFF."); 777360784Sdim assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2."); 778360784Sdim 779360784Sdim OS << "\t.lcomm\t"; 780360784Sdim LabelSym->print(OS, MAI); 781360784Sdim OS << ',' << Size << ','; 782360784Sdim CsectSym->print(OS, MAI); 783360784Sdim OS << ',' << Log2_32(ByteAlignment); 784360784Sdim 785360784Sdim EmitEOL(); 786360784Sdim} 787360784Sdim 788314564Sdimvoid MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 789261991Sdim assert(MAI->hasDotTypeDotSizeDirective()); 790288943Sdim OS << "\t.size\t"; 791288943Sdim Symbol->print(OS, MAI); 792288943Sdim OS << ", "; 793288943Sdim Value->print(OS, MAI); 794309124Sdim EmitEOL(); 795203954Srdivacky} 796203954Srdivacky 797202878Srdivackyvoid MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 798198090Srdivacky unsigned ByteAlignment) { 799288943Sdim OS << "\t.comm\t"; 800288943Sdim Symbol->print(OS, MAI); 801288943Sdim OS << ',' << Size; 802288943Sdim 803203954Srdivacky if (ByteAlignment != 0) { 804261991Sdim if (MAI->getCOMMDirectiveAlignmentIsInBytes()) 805202878Srdivacky OS << ',' << ByteAlignment; 806202878Srdivacky else 807202878Srdivacky OS << ',' << Log2_32(ByteAlignment); 808202878Srdivacky } 809202878Srdivacky EmitEOL(); 810198090Srdivacky} 811198090Srdivacky 812226633Sdimvoid MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 813226633Sdim unsigned ByteAlign) { 814288943Sdim OS << "\t.lcomm\t"; 815288943Sdim Symbol->print(OS, MAI); 816288943Sdim OS << ',' << Size; 817288943Sdim 818226633Sdim if (ByteAlign > 1) { 819261991Sdim switch (MAI->getLCOMMDirectiveAlignmentType()) { 820243830Sdim case LCOMM::NoAlignment: 821243830Sdim llvm_unreachable("alignment not supported on .lcomm!"); 822243830Sdim case LCOMM::ByteAlignment: 823243830Sdim OS << ',' << ByteAlign; 824243830Sdim break; 825243830Sdim case LCOMM::Log2Alignment: 826243830Sdim assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); 827243830Sdim OS << ',' << Log2_32(ByteAlign); 828243830Sdim break; 829243830Sdim } 830226633Sdim } 831202878Srdivacky EmitEOL(); 832202878Srdivacky} 833202878Srdivacky 834288943Sdimvoid MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 835341825Sdim uint64_t Size, unsigned ByteAlignment, 836341825Sdim SMLoc Loc) { 837261991Sdim if (Symbol) 838296417Sdim AssignFragment(Symbol, &Section->getDummyFragment()); 839261991Sdim 840198090Srdivacky // Note: a .zerofill directive does not switch sections. 841198090Srdivacky OS << ".zerofill "; 842218893Sdim 843341825Sdim assert(Section->getVariant() == MCSection::SV_MachO && 844341825Sdim ".zerofill is a Mach-O specific directive"); 845198090Srdivacky // This is a mach-o specific directive. 846341825Sdim 847198090Srdivacky const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 848198090Srdivacky OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 849218893Sdim 850276479Sdim if (Symbol) { 851288943Sdim OS << ','; 852288943Sdim Symbol->print(OS, MAI); 853288943Sdim OS << ',' << Size; 854198090Srdivacky if (ByteAlignment != 0) 855198090Srdivacky OS << ',' << Log2_32(ByteAlignment); 856198090Srdivacky } 857202878Srdivacky EmitEOL(); 858198090Srdivacky} 859198090Srdivacky 860208599Srdivacky// .tbss sym, size, align 861208599Srdivacky// This depends that the symbol has already been mangled from the original, 862208599Srdivacky// e.g. _a. 863288943Sdimvoid MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 864208599Srdivacky uint64_t Size, unsigned ByteAlignment) { 865296417Sdim AssignFragment(Symbol, &Section->getDummyFragment()); 866261991Sdim 867276479Sdim assert(Symbol && "Symbol shouldn't be NULL!"); 868208599Srdivacky // Instead of using the Section we'll just use the shortcut. 869341825Sdim 870341825Sdim assert(Section->getVariant() == MCSection::SV_MachO && 871341825Sdim ".zerofill is a Mach-O specific directive"); 872208599Srdivacky // This is a mach-o specific directive and section. 873341825Sdim 874288943Sdim OS << ".tbss "; 875288943Sdim Symbol->print(OS, MAI); 876288943Sdim OS << ", " << Size; 877218893Sdim 878208599Srdivacky // Output align if we have it. We default to 1 so don't bother printing 879208599Srdivacky // that. 880208599Srdivacky if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); 881218893Sdim 882208599Srdivacky EmitEOL(); 883208599Srdivacky} 884208599Srdivacky 885202878Srdivackystatic inline char toOctal(int X) { return (X&7)+'0'; } 886202878Srdivacky 887203954Srdivackystatic void PrintQuotedString(StringRef Data, raw_ostream &OS) { 888203954Srdivacky OS << '"'; 889218893Sdim 890203954Srdivacky for (unsigned i = 0, e = Data.size(); i != e; ++i) { 891203954Srdivacky unsigned char C = Data[i]; 892203954Srdivacky if (C == '"' || C == '\\') { 893203954Srdivacky OS << '\\' << (char)C; 894203954Srdivacky continue; 895203954Srdivacky } 896218893Sdim 897341825Sdim if (isPrint((unsigned char)C)) { 898203954Srdivacky OS << (char)C; 899203954Srdivacky continue; 900203954Srdivacky } 901218893Sdim 902203954Srdivacky switch (C) { 903203954Srdivacky case '\b': OS << "\\b"; break; 904203954Srdivacky case '\f': OS << "\\f"; break; 905203954Srdivacky case '\n': OS << "\\n"; break; 906203954Srdivacky case '\r': OS << "\\r"; break; 907203954Srdivacky case '\t': OS << "\\t"; break; 908203954Srdivacky default: 909203954Srdivacky OS << '\\'; 910203954Srdivacky OS << toOctal(C >> 6); 911203954Srdivacky OS << toOctal(C >> 3); 912203954Srdivacky OS << toOctal(C >> 0); 913203954Srdivacky break; 914203954Srdivacky } 915203954Srdivacky } 916218893Sdim 917203954Srdivacky OS << '"'; 918203954Srdivacky} 919203954Srdivacky 920261991Sdimvoid MCAsmStreamer::EmitBytes(StringRef Data) { 921314564Sdim assert(getCurrentSectionOnly() && 922251662Sdim "Cannot emit contents before setting section!"); 923202878Srdivacky if (Data.empty()) return; 924218893Sdim 925327952Sdim // If only single byte is provided or no ascii or asciz directives is 926327952Sdim // supported, emit as vector of 8bits data. 927327952Sdim if (Data.size() == 1 || 928327952Sdim !(MAI->getAscizDirective() || MAI->getAsciiDirective())) { 929344779Sdim if (MCTargetStreamer *TS = getTargetStreamer()) { 930344779Sdim TS->emitRawBytes(Data); 931344779Sdim } else { 932344779Sdim const char *Directive = MAI->getData8bitsDirective(); 933344779Sdim for (const unsigned char C : Data.bytes()) { 934344779Sdim OS << Directive << (unsigned)C; 935344779Sdim EmitEOL(); 936344779Sdim } 937327952Sdim } 938202878Srdivacky return; 939202878Srdivacky } 940202878Srdivacky 941202878Srdivacky // If the data ends with 0 and the target supports .asciz, use it, otherwise 942202878Srdivacky // use .ascii 943261991Sdim if (MAI->getAscizDirective() && Data.back() == 0) { 944261991Sdim OS << MAI->getAscizDirective(); 945202878Srdivacky Data = Data.substr(0, Data.size()-1); 946202878Srdivacky } else { 947261991Sdim OS << MAI->getAsciiDirective(); 948202878Srdivacky } 949202878Srdivacky 950203954Srdivacky PrintQuotedString(Data, OS); 951202878Srdivacky EmitEOL(); 952195098Sed} 953195098Sed 954309124Sdimvoid MCAsmStreamer::EmitBinaryData(StringRef Data) { 955309124Sdim // This is binary data. Print it in a grid of hex bytes for readability. 956309124Sdim const size_t Cols = 4; 957309124Sdim for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { 958309124Sdim size_t J = I, EJ = std::min(I + Cols, Data.size()); 959309124Sdim assert(EJ > 0); 960309124Sdim OS << MAI->getData8bitsDirective(); 961309124Sdim for (; J < EJ - 1; ++J) 962309124Sdim OS << format("0x%02x", uint8_t(Data[J])) << ", "; 963309124Sdim OS << format("0x%02x", uint8_t(Data[J])); 964309124Sdim EmitEOL(); 965309124Sdim } 966309124Sdim} 967309124Sdim 968261991Sdimvoid MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { 969288943Sdim EmitValue(MCConstantExpr::create(Value, getContext()), Size); 970218893Sdim} 971218893Sdim 972353358Sdimvoid MCAsmStreamer::EmitIntValueInHex(uint64_t Value, unsigned Size) { 973353358Sdim EmitValue(MCConstantExpr::create(Value, getContext(), true), Size); 974353358Sdim} 975353358Sdim 976276479Sdimvoid MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, 977296417Sdim SMLoc Loc) { 978276479Sdim assert(Size <= 8 && "Invalid size"); 979314564Sdim assert(getCurrentSectionOnly() && 980251662Sdim "Cannot emit contents before setting section!"); 981276479Sdim const char *Directive = nullptr; 982195098Sed switch (Size) { 983202878Srdivacky default: break; 984261991Sdim case 1: Directive = MAI->getData8bitsDirective(); break; 985261991Sdim case 2: Directive = MAI->getData16bitsDirective(); break; 986261991Sdim case 4: Directive = MAI->getData32bitsDirective(); break; 987276479Sdim case 8: Directive = MAI->getData64bitsDirective(); break; 988276479Sdim } 989276479Sdim 990276479Sdim if (!Directive) { 991218893Sdim int64_t IntValue; 992288943Sdim if (!Value->evaluateAsAbsolute(IntValue)) 993218893Sdim report_fatal_error("Don't know how to emit this value."); 994276479Sdim 995276479Sdim // We couldn't handle the requested integer size so we fallback by breaking 996309124Sdim // the request down into several, smaller, integers. 997309124Sdim // Since sizes greater or equal to "Size" are invalid, we use the greatest 998309124Sdim // power of 2 that is less than "Size" as our largest piece of granularity. 999276479Sdim bool IsLittleEndian = MAI->isLittleEndian(); 1000276479Sdim for (unsigned Emitted = 0; Emitted != Size;) { 1001276479Sdim unsigned Remaining = Size - Emitted; 1002276479Sdim // The size of our partial emission must be a power of two less than 1003309124Sdim // Size. 1004309124Sdim unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); 1005276479Sdim // Calculate the byte offset of our partial emission taking into account 1006276479Sdim // the endianness of the target. 1007276479Sdim unsigned ByteOffset = 1008276479Sdim IsLittleEndian ? Emitted : (Remaining - EmissionSize); 1009276479Sdim uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); 1010276479Sdim // We truncate our partial emission to fit within the bounds of the 1011276479Sdim // emission domain. This produces nicer output and silences potential 1012276479Sdim // truncation warnings when round tripping through another assembler. 1013280031Sdim uint64_t Shift = 64 - EmissionSize * 8; 1014280031Sdim assert(Shift < static_cast<uint64_t>( 1015280031Sdim std::numeric_limits<unsigned long long>::digits) && 1016280031Sdim "undefined behavior"); 1017280031Sdim ValueToEmit &= ~0ULL >> Shift; 1018276479Sdim EmitIntValue(ValueToEmit, EmissionSize); 1019276479Sdim Emitted += EmissionSize; 1020202878Srdivacky } 1021202878Srdivacky return; 1022195098Sed } 1023218893Sdim 1024202878Srdivacky assert(Directive && "Invalid size for machine code value!"); 1025288943Sdim OS << Directive; 1026327952Sdim if (MCTargetStreamer *TS = getTargetStreamer()) { 1027327952Sdim TS->emitValue(Value); 1028327952Sdim } else { 1029327952Sdim Value->print(OS, MAI); 1030327952Sdim EmitEOL(); 1031327952Sdim } 1032202878Srdivacky} 1033195098Sed 1034221345Sdimvoid MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { 1035218893Sdim int64_t IntValue; 1036288943Sdim if (Value->evaluateAsAbsolute(IntValue)) { 1037221345Sdim EmitULEB128IntValue(IntValue); 1038218893Sdim return; 1039202878Srdivacky } 1040341825Sdim OS << "\t.uleb128 "; 1041288943Sdim Value->print(OS, MAI); 1042202878Srdivacky EmitEOL(); 1043195098Sed} 1044195098Sed 1045221345Sdimvoid MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { 1046218893Sdim int64_t IntValue; 1047288943Sdim if (Value->evaluateAsAbsolute(IntValue)) { 1048221345Sdim EmitSLEB128IntValue(IntValue); 1049218893Sdim return; 1050218893Sdim } 1051341825Sdim OS << "\t.sleb128 "; 1052288943Sdim Value->print(OS, MAI); 1053218893Sdim EmitEOL(); 1054218893Sdim} 1055218893Sdim 1056314564Sdimvoid MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) { 1057314564Sdim assert(MAI->getDTPRel64Directive() != nullptr); 1058314564Sdim OS << MAI->getDTPRel64Directive(); 1059314564Sdim Value->print(OS, MAI); 1060314564Sdim EmitEOL(); 1061314564Sdim} 1062314564Sdim 1063314564Sdimvoid MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) { 1064314564Sdim assert(MAI->getDTPRel32Directive() != nullptr); 1065314564Sdim OS << MAI->getDTPRel32Directive(); 1066314564Sdim Value->print(OS, MAI); 1067314564Sdim EmitEOL(); 1068314564Sdim} 1069314564Sdim 1070314564Sdimvoid MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) { 1071314564Sdim assert(MAI->getTPRel64Directive() != nullptr); 1072314564Sdim OS << MAI->getTPRel64Directive(); 1073314564Sdim Value->print(OS, MAI); 1074314564Sdim EmitEOL(); 1075314564Sdim} 1076314564Sdim 1077314564Sdimvoid MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) { 1078314564Sdim assert(MAI->getTPRel32Directive() != nullptr); 1079314564Sdim OS << MAI->getTPRel32Directive(); 1080314564Sdim Value->print(OS, MAI); 1081314564Sdim EmitEOL(); 1082314564Sdim} 1083314564Sdim 1084234353Sdimvoid MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { 1085276479Sdim assert(MAI->getGPRel64Directive() != nullptr); 1086288943Sdim OS << MAI->getGPRel64Directive(); 1087288943Sdim Value->print(OS, MAI); 1088234353Sdim EmitEOL(); 1089234353Sdim} 1090234353Sdim 1091203954Srdivackyvoid MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 1092276479Sdim assert(MAI->getGPRel32Directive() != nullptr); 1093288943Sdim OS << MAI->getGPRel32Directive(); 1094288943Sdim Value->print(OS, MAI); 1095203954Srdivacky EmitEOL(); 1096203954Srdivacky} 1097203954Srdivacky 1098309124Sdimvoid MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, 1099309124Sdim SMLoc Loc) { 1100328594Semaste int64_t IntNumBytes; 1101328594Semaste if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0) 1102328594Semaste return; 1103328594Semaste 1104261991Sdim if (const char *ZeroDirective = MAI->getZeroDirective()) { 1105309124Sdim // FIXME: Emit location directives 1106309124Sdim OS << ZeroDirective; 1107309124Sdim NumBytes.print(OS, MAI); 1108261991Sdim if (FillValue != 0) 1109261991Sdim OS << ',' << (int)FillValue; 1110261991Sdim EmitEOL(); 1111261991Sdim return; 1112261991Sdim } 1113202878Srdivacky 1114309124Sdim MCStreamer::emitFill(NumBytes, FillValue); 1115202878Srdivacky} 1116202878Srdivacky 1117309124Sdimvoid MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, 1118309124Sdim int64_t Expr, SMLoc Loc) { 1119309124Sdim // FIXME: Emit location directives 1120309124Sdim OS << "\t.fill\t"; 1121309124Sdim NumValues.print(OS, MAI); 1122309124Sdim OS << ", " << Size << ", 0x"; 1123309124Sdim OS.write_hex(truncateToSize(Expr, 4)); 1124309124Sdim EmitEOL(); 1125309124Sdim} 1126309124Sdim 1127195098Sedvoid MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 1128195098Sed unsigned ValueSize, 1129195098Sed unsigned MaxBytesToEmit) { 1130360784Sdim if (MAI->useDotAlignForAlignment()) { 1131360784Sdim if (!isPowerOf2_32(ByteAlignment)) 1132360784Sdim report_fatal_error("Only power-of-two alignments are supported " 1133360784Sdim "with .align."); 1134360784Sdim OS << "\t.align\t"; 1135360784Sdim OS << Log2_32(ByteAlignment); 1136360784Sdim EmitEOL(); 1137360784Sdim return; 1138360784Sdim } 1139360784Sdim 1140198090Srdivacky // Some assemblers don't support non-power of two alignments, so we always 1141198090Srdivacky // emit alignments as a power of two if possible. 1142198090Srdivacky if (isPowerOf2_32(ByteAlignment)) { 1143198090Srdivacky switch (ValueSize) { 1144276479Sdim default: 1145276479Sdim llvm_unreachable("Invalid size for machine code value!"); 1146276479Sdim case 1: 1147309124Sdim OS << "\t.p2align\t"; 1148276479Sdim break; 1149276479Sdim case 2: 1150276479Sdim OS << ".p2alignw "; 1151276479Sdim break; 1152276479Sdim case 4: 1153276479Sdim OS << ".p2alignl "; 1154276479Sdim break; 1155276479Sdim case 8: 1156276479Sdim llvm_unreachable("Unsupported alignment size!"); 1157198090Srdivacky } 1158218893Sdim 1159309124Sdim OS << Log2_32(ByteAlignment); 1160195098Sed 1161198090Srdivacky if (Value || MaxBytesToEmit) { 1162198090Srdivacky OS << ", 0x"; 1163198090Srdivacky OS.write_hex(truncateToSize(Value, ValueSize)); 1164198090Srdivacky 1165218893Sdim if (MaxBytesToEmit) 1166198090Srdivacky OS << ", " << MaxBytesToEmit; 1167198090Srdivacky } 1168202878Srdivacky EmitEOL(); 1169198090Srdivacky return; 1170198090Srdivacky } 1171218893Sdim 1172198090Srdivacky // Non-power of two alignment. This is not widely supported by assemblers. 1173198090Srdivacky // FIXME: Parameterize this based on MAI. 1174195098Sed switch (ValueSize) { 1175198090Srdivacky default: llvm_unreachable("Invalid size for machine code value!"); 1176198090Srdivacky case 1: OS << ".balign"; break; 1177198090Srdivacky case 2: OS << ".balignw"; break; 1178198090Srdivacky case 4: OS << ".balignl"; break; 1179198090Srdivacky case 8: llvm_unreachable("Unsupported alignment size!"); 1180195098Sed } 1181195098Sed 1182198090Srdivacky OS << ' ' << ByteAlignment; 1183195098Sed OS << ", " << truncateToSize(Value, ValueSize); 1184218893Sdim if (MaxBytesToEmit) 1185195098Sed OS << ", " << MaxBytesToEmit; 1186202878Srdivacky EmitEOL(); 1187195098Sed} 1188195098Sed 1189204642Srdivackyvoid MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 1190204642Srdivacky unsigned MaxBytesToEmit) { 1191204642Srdivacky // Emit with a text fill value. 1192261991Sdim EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), 1193204642Srdivacky 1, MaxBytesToEmit); 1194204642Srdivacky} 1195204642Srdivacky 1196296417Sdimvoid MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, 1197314564Sdim unsigned char Value, 1198314564Sdim SMLoc Loc) { 1199195098Sed // FIXME: Verify that Offset is associated with the current section. 1200288943Sdim OS << ".org "; 1201288943Sdim Offset->print(OS, MAI); 1202288943Sdim OS << ", " << (unsigned)Value; 1203202878Srdivacky EmitEOL(); 1204195098Sed} 1205195098Sed 1206203954Srdivackyvoid MCAsmStreamer::EmitFileDirective(StringRef Filename) { 1207261991Sdim assert(MAI->hasSingleParameterDotFile()); 1208203954Srdivacky OS << "\t.file\t"; 1209203954Srdivacky PrintQuotedString(Filename, OS); 1210203954Srdivacky EmitEOL(); 1211203954Srdivacky} 1212198090Srdivacky 1213341825Sdimstatic void printDwarfFileDirective(unsigned FileNo, StringRef Directory, 1214341825Sdim StringRef Filename, 1215353358Sdim Optional<MD5::MD5Result> Checksum, 1216341825Sdim Optional<StringRef> Source, 1217341825Sdim bool UseDwarfDirectory, 1218341825Sdim raw_svector_ostream &OS) { 1219276479Sdim SmallString<128> FullPathName; 1220276479Sdim 1221234353Sdim if (!UseDwarfDirectory && !Directory.empty()) { 1222234353Sdim if (sys::path::is_absolute(Filename)) 1223276479Sdim Directory = ""; 1224276479Sdim else { 1225276479Sdim FullPathName = Directory; 1226276479Sdim sys::path::append(FullPathName, Filename); 1227276479Sdim Directory = ""; 1228276479Sdim Filename = FullPathName; 1229276479Sdim } 1230276479Sdim } 1231234353Sdim 1232341825Sdim OS << "\t.file\t" << FileNo << ' '; 1233341825Sdim if (!Directory.empty()) { 1234341825Sdim PrintQuotedString(Directory, OS); 1235341825Sdim OS << ' '; 1236341825Sdim } 1237341825Sdim PrintQuotedString(Filename, OS); 1238341825Sdim if (Checksum) 1239341825Sdim OS << " md5 0x" << Checksum->digest(); 1240341825Sdim if (Source) { 1241341825Sdim OS << " source "; 1242341825Sdim PrintQuotedString(*Source, OS); 1243341825Sdim } 1244341825Sdim} 1245341825Sdim 1246341825SdimExpected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective( 1247341825Sdim unsigned FileNo, StringRef Directory, StringRef Filename, 1248353358Sdim Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) { 1249341825Sdim assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer"); 1250341825Sdim 1251341825Sdim MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); 1252341825Sdim unsigned NumFiles = Table.getMCDwarfFiles().size(); 1253341825Sdim Expected<unsigned> FileNoOrErr = 1254353358Sdim Table.tryGetFile(Directory, Filename, Checksum, Source, 1255353358Sdim getContext().getDwarfVersion(), FileNo); 1256341825Sdim if (!FileNoOrErr) 1257341825Sdim return FileNoOrErr.takeError(); 1258341825Sdim FileNo = FileNoOrErr.get(); 1259341825Sdim if (NumFiles == Table.getMCDwarfFiles().size()) 1260341825Sdim return FileNo; 1261341825Sdim 1262327952Sdim SmallString<128> Str; 1263327952Sdim raw_svector_ostream OS1(Str); 1264341825Sdim printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source, 1265341825Sdim UseDwarfDirectory, OS1); 1266341825Sdim 1267341825Sdim if (MCTargetStreamer *TS = getTargetStreamer()) 1268327952Sdim TS->emitDwarfFileDirective(OS1.str()); 1269341825Sdim else 1270327952Sdim EmitRawText(OS1.str()); 1271234353Sdim 1272276479Sdim return FileNo; 1273218893Sdim} 1274218893Sdim 1275341825Sdimvoid MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory, 1276341825Sdim StringRef Filename, 1277353358Sdim Optional<MD5::MD5Result> Checksum, 1278341825Sdim Optional<StringRef> Source, 1279341825Sdim unsigned CUID) { 1280341825Sdim assert(CUID == 0); 1281341825Sdim // .file 0 is new for DWARF v5. 1282341825Sdim if (getContext().getDwarfVersion() < 5) 1283341825Sdim return; 1284341825Sdim // Inform MCDwarf about the root file. 1285341825Sdim getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, 1286341825Sdim Source); 1287341825Sdim 1288341825Sdim SmallString<128> Str; 1289341825Sdim raw_svector_ostream OS1(Str); 1290341825Sdim printDwarfFileDirective(0, Directory, Filename, Checksum, Source, 1291341825Sdim UseDwarfDirectory, OS1); 1292341825Sdim 1293341825Sdim if (MCTargetStreamer *TS = getTargetStreamer()) 1294341825Sdim TS->emitDwarfFileDirective(OS1.str()); 1295341825Sdim else 1296341825Sdim EmitRawText(OS1.str()); 1297341825Sdim} 1298341825Sdim 1299218893Sdimvoid MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 1300218893Sdim unsigned Column, unsigned Flags, 1301218893Sdim unsigned Isa, 1302221345Sdim unsigned Discriminator, 1303221345Sdim StringRef FileName) { 1304218893Sdim OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 1305341825Sdim if (MAI->supportsExtendedDwarfLocDirective()) { 1306341825Sdim if (Flags & DWARF2_FLAG_BASIC_BLOCK) 1307341825Sdim OS << " basic_block"; 1308341825Sdim if (Flags & DWARF2_FLAG_PROLOGUE_END) 1309341825Sdim OS << " prologue_end"; 1310341825Sdim if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 1311341825Sdim OS << " epilogue_begin"; 1312218893Sdim 1313341825Sdim unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 1314341825Sdim if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 1315341825Sdim OS << " is_stmt "; 1316218893Sdim 1317341825Sdim if (Flags & DWARF2_FLAG_IS_STMT) 1318341825Sdim OS << "1"; 1319341825Sdim else 1320341825Sdim OS << "0"; 1321341825Sdim } 1322341825Sdim 1323341825Sdim if (Isa) 1324341825Sdim OS << " isa " << Isa; 1325341825Sdim if (Discriminator) 1326341825Sdim OS << " discriminator " << Discriminator; 1327218893Sdim } 1328218893Sdim 1329221345Sdim if (IsVerboseAsm) { 1330261991Sdim OS.PadToColumn(MAI->getCommentColumn()); 1331261991Sdim OS << MAI->getCommentString() << ' ' << FileName << ':' 1332221345Sdim << Line << ':' << Column; 1333221345Sdim } 1334203954Srdivacky EmitEOL(); 1335280031Sdim this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, 1336280031Sdim Isa, Discriminator, FileName); 1337203954Srdivacky} 1338203954Srdivacky 1339276479SdimMCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 1340276479Sdim // Always use the zeroth line table, since asm syntax only supports one line 1341276479Sdim // table for now. 1342276479Sdim return MCStreamer::getDwarfLineTableSymbol(0); 1343276479Sdim} 1344276479Sdim 1345327952Sdimbool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename, 1346327952Sdim ArrayRef<uint8_t> Checksum, 1347327952Sdim unsigned ChecksumKind) { 1348327952Sdim if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum, 1349327952Sdim ChecksumKind)) 1350314564Sdim return false; 1351309124Sdim 1352309124Sdim OS << "\t.cv_file\t" << FileNo << ' '; 1353327952Sdim PrintQuotedString(Filename, OS); 1354309124Sdim 1355327952Sdim if (!ChecksumKind) { 1356327952Sdim EmitEOL(); 1357327952Sdim return true; 1358327952Sdim } 1359327952Sdim 1360327952Sdim OS << ' '; 1361327952Sdim PrintQuotedString(toHex(Checksum), OS); 1362327952Sdim OS << ' ' << ChecksumKind; 1363327952Sdim 1364309124Sdim EmitEOL(); 1365314564Sdim return true; 1366314564Sdim} 1367309124Sdim 1368314564Sdimbool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) { 1369314564Sdim OS << "\t.cv_func_id " << FuncId << '\n'; 1370314564Sdim return MCStreamer::EmitCVFuncIdDirective(FuncId); 1371309124Sdim} 1372309124Sdim 1373314564Sdimbool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId, 1374314564Sdim unsigned IAFunc, 1375314564Sdim unsigned IAFile, 1376314564Sdim unsigned IALine, unsigned IACol, 1377314564Sdim SMLoc Loc) { 1378314564Sdim OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc 1379314564Sdim << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n'; 1380314564Sdim return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 1381314564Sdim IALine, IACol, Loc); 1382314564Sdim} 1383314564Sdim 1384309124Sdimvoid MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, 1385309124Sdim unsigned Line, unsigned Column, 1386309124Sdim bool PrologueEnd, bool IsStmt, 1387314564Sdim StringRef FileName, SMLoc Loc) { 1388344779Sdim // Validate the directive. 1389344779Sdim if (!checkCVLocSection(FunctionId, FileNo, Loc)) 1390344779Sdim return; 1391344779Sdim 1392309124Sdim OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " 1393309124Sdim << Column; 1394309124Sdim if (PrologueEnd) 1395309124Sdim OS << " prologue_end"; 1396309124Sdim 1397344779Sdim if (IsStmt) 1398344779Sdim OS << " is_stmt 1"; 1399309124Sdim 1400309124Sdim if (IsVerboseAsm) { 1401309124Sdim OS.PadToColumn(MAI->getCommentColumn()); 1402314564Sdim OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':' 1403314564Sdim << Column; 1404309124Sdim } 1405309124Sdim EmitEOL(); 1406309124Sdim} 1407309124Sdim 1408309124Sdimvoid MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, 1409309124Sdim const MCSymbol *FnStart, 1410309124Sdim const MCSymbol *FnEnd) { 1411309124Sdim OS << "\t.cv_linetable\t" << FunctionId << ", "; 1412309124Sdim FnStart->print(OS, MAI); 1413309124Sdim OS << ", "; 1414309124Sdim FnEnd->print(OS, MAI); 1415309124Sdim EmitEOL(); 1416309124Sdim this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); 1417309124Sdim} 1418309124Sdim 1419314564Sdimvoid MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 1420314564Sdim unsigned SourceFileId, 1421314564Sdim unsigned SourceLineNum, 1422314564Sdim const MCSymbol *FnStartSym, 1423314564Sdim const MCSymbol *FnEndSym) { 1424309124Sdim OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId 1425309124Sdim << ' ' << SourceLineNum << ' '; 1426309124Sdim FnStartSym->print(OS, MAI); 1427309124Sdim OS << ' '; 1428309124Sdim FnEndSym->print(OS, MAI); 1429309124Sdim EmitEOL(); 1430309124Sdim this->MCStreamer::EmitCVInlineLinetableDirective( 1431314564Sdim PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); 1432309124Sdim} 1433309124Sdim 1434360784Sdimvoid MCAsmStreamer::PrintCVDefRangePrefix( 1435360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) { 1436309124Sdim OS << "\t.cv_def_range\t"; 1437309124Sdim for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { 1438309124Sdim OS << ' '; 1439309124Sdim Range.first->print(OS, MAI); 1440309124Sdim OS << ' '; 1441309124Sdim Range.second->print(OS, MAI); 1442309124Sdim } 1443360784Sdim} 1444360784Sdim 1445360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective( 1446360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1447360784Sdim codeview::DefRangeRegisterRelHeader DRHdr) { 1448360784Sdim PrintCVDefRangePrefix(Ranges); 1449360784Sdim OS << ", reg_rel, "; 1450360784Sdim OS << DRHdr.Register << ", " << DRHdr.Flags << ", " 1451360784Sdim << DRHdr.BasePointerOffset; 1452309124Sdim EmitEOL(); 1453309124Sdim} 1454309124Sdim 1455360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective( 1456360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1457360784Sdim codeview::DefRangeSubfieldRegisterHeader DRHdr) { 1458360784Sdim PrintCVDefRangePrefix(Ranges); 1459360784Sdim OS << ", subfield_reg, "; 1460360784Sdim OS << DRHdr.Register << ", " << DRHdr.OffsetInParent; 1461360784Sdim EmitEOL(); 1462360784Sdim} 1463360784Sdim 1464360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective( 1465360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1466360784Sdim codeview::DefRangeRegisterHeader DRHdr) { 1467360784Sdim PrintCVDefRangePrefix(Ranges); 1468360784Sdim OS << ", reg, "; 1469360784Sdim OS << DRHdr.Register; 1470360784Sdim EmitEOL(); 1471360784Sdim} 1472360784Sdim 1473360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective( 1474360784Sdim ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1475360784Sdim codeview::DefRangeFramePointerRelHeader DRHdr) { 1476360784Sdim PrintCVDefRangePrefix(Ranges); 1477360784Sdim OS << ", frame_ptr_rel, "; 1478360784Sdim OS << DRHdr.Offset; 1479360784Sdim EmitEOL(); 1480360784Sdim} 1481360784Sdim 1482309124Sdimvoid MCAsmStreamer::EmitCVStringTableDirective() { 1483309124Sdim OS << "\t.cv_stringtable"; 1484309124Sdim EmitEOL(); 1485309124Sdim} 1486309124Sdim 1487309124Sdimvoid MCAsmStreamer::EmitCVFileChecksumsDirective() { 1488309124Sdim OS << "\t.cv_filechecksums"; 1489309124Sdim EmitEOL(); 1490309124Sdim} 1491309124Sdim 1492327952Sdimvoid MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) { 1493327952Sdim OS << "\t.cv_filechecksumoffset\t" << FileNo; 1494327952Sdim EmitEOL(); 1495327952Sdim} 1496327952Sdim 1497327952Sdimvoid MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) { 1498327952Sdim OS << "\t.cv_fpo_data\t"; 1499327952Sdim ProcSym->print(OS, MAI); 1500327952Sdim EmitEOL(); 1501327952Sdim} 1502327952Sdim 1503261991Sdimvoid MCAsmStreamer::EmitIdent(StringRef IdentString) { 1504261991Sdim assert(MAI->hasIdentDirective() && ".ident directive not supported"); 1505261991Sdim OS << "\t.ident\t"; 1506261991Sdim PrintQuotedString(IdentString, OS); 1507261991Sdim EmitEOL(); 1508261991Sdim} 1509261991Sdim 1510223017Sdimvoid MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { 1511223017Sdim MCStreamer::EmitCFISections(EH, Debug); 1512223017Sdim OS << "\t.cfi_sections "; 1513223017Sdim if (EH) { 1514223017Sdim OS << ".eh_frame"; 1515223017Sdim if (Debug) 1516223017Sdim OS << ", .debug_frame"; 1517223017Sdim } else if (Debug) { 1518223017Sdim OS << ".debug_frame"; 1519223017Sdim } 1520223017Sdim 1521223017Sdim EmitEOL(); 1522223017Sdim} 1523223017Sdim 1524234353Sdimvoid MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 1525218893Sdim OS << "\t.cfi_startproc"; 1526276479Sdim if (Frame.IsSimple) 1527276479Sdim OS << " simple"; 1528218893Sdim EmitEOL(); 1529218893Sdim} 1530218893Sdim 1531234353Sdimvoid MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 1532276479Sdim MCStreamer::EmitCFIEndProcImpl(Frame); 1533218893Sdim OS << "\t.cfi_endproc"; 1534218893Sdim EmitEOL(); 1535221345Sdim} 1536218893Sdim 1537223017Sdimvoid MCAsmStreamer::EmitRegisterName(int64_t Register) { 1538288943Sdim if (!MAI->useDwarfRegNumForCFI()) { 1539327952Sdim // User .cfi_* directives can use arbitrary DWARF register numbers, not 1540327952Sdim // just ones that map to LLVM register numbers and have known names. 1541327952Sdim // Fall back to using the original number directly if no name is known. 1542261991Sdim const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 1543360784Sdim if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) { 1544360784Sdim InstPrinter->printRegName(OS, *LLVMRegister); 1545327952Sdim return; 1546327952Sdim } 1547223017Sdim } 1548327952Sdim OS << Register; 1549223017Sdim} 1550223017Sdim 1551221345Sdimvoid MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { 1552221345Sdim MCStreamer::EmitCFIDefCfa(Register, Offset); 1553223017Sdim OS << "\t.cfi_def_cfa "; 1554223017Sdim EmitRegisterName(Register); 1555223017Sdim OS << ", " << Offset; 1556221345Sdim EmitEOL(); 1557218893Sdim} 1558218893Sdim 1559221345Sdimvoid MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 1560221345Sdim MCStreamer::EmitCFIDefCfaOffset(Offset); 1561218893Sdim OS << "\t.cfi_def_cfa_offset " << Offset; 1562218893Sdim EmitEOL(); 1563218893Sdim} 1564218893Sdim 1565296417Sdimstatic void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { 1566296417Sdim OS << "\t.cfi_escape "; 1567296417Sdim if (!Values.empty()) { 1568296417Sdim size_t e = Values.size() - 1; 1569296417Sdim for (size_t i = 0; i < e; ++i) 1570296417Sdim OS << format("0x%02x", uint8_t(Values[i])) << ", "; 1571296417Sdim OS << format("0x%02x", uint8_t(Values[e])); 1572296417Sdim } 1573296417Sdim} 1574296417Sdim 1575296417Sdimvoid MCAsmStreamer::EmitCFIEscape(StringRef Values) { 1576296417Sdim MCStreamer::EmitCFIEscape(Values); 1577296417Sdim PrintCFIEscape(OS, Values); 1578296417Sdim EmitEOL(); 1579296417Sdim} 1580296417Sdim 1581296417Sdimvoid MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { 1582296417Sdim MCStreamer::EmitCFIGnuArgsSize(Size); 1583309124Sdim 1584296417Sdim uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; 1585296417Sdim unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; 1586309124Sdim 1587296417Sdim PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); 1588296417Sdim EmitEOL(); 1589296417Sdim} 1590296417Sdim 1591221345Sdimvoid MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { 1592221345Sdim MCStreamer::EmitCFIDefCfaRegister(Register); 1593223017Sdim OS << "\t.cfi_def_cfa_register "; 1594223017Sdim EmitRegisterName(Register); 1595218893Sdim EmitEOL(); 1596218893Sdim} 1597218893Sdim 1598221345Sdimvoid MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 1599221345Sdim this->MCStreamer::EmitCFIOffset(Register, Offset); 1600223017Sdim OS << "\t.cfi_offset "; 1601223017Sdim EmitRegisterName(Register); 1602223017Sdim OS << ", " << Offset; 1603218893Sdim EmitEOL(); 1604218893Sdim} 1605218893Sdim 1606221345Sdimvoid MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, 1607218893Sdim unsigned Encoding) { 1608221345Sdim MCStreamer::EmitCFIPersonality(Sym, Encoding); 1609288943Sdim OS << "\t.cfi_personality " << Encoding << ", "; 1610288943Sdim Sym->print(OS, MAI); 1611218893Sdim EmitEOL(); 1612218893Sdim} 1613218893Sdim 1614221345Sdimvoid MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 1615221345Sdim MCStreamer::EmitCFILsda(Sym, Encoding); 1616288943Sdim OS << "\t.cfi_lsda " << Encoding << ", "; 1617288943Sdim Sym->print(OS, MAI); 1618218893Sdim EmitEOL(); 1619221345Sdim} 1620218893Sdim 1621221345Sdimvoid MCAsmStreamer::EmitCFIRememberState() { 1622221345Sdim MCStreamer::EmitCFIRememberState(); 1623221345Sdim OS << "\t.cfi_remember_state"; 1624221345Sdim EmitEOL(); 1625218893Sdim} 1626218893Sdim 1627221345Sdimvoid MCAsmStreamer::EmitCFIRestoreState() { 1628221345Sdim MCStreamer::EmitCFIRestoreState(); 1629221345Sdim OS << "\t.cfi_restore_state"; 1630221345Sdim EmitEOL(); 1631221345Sdim} 1632221345Sdim 1633327952Sdimvoid MCAsmStreamer::EmitCFIRestore(int64_t Register) { 1634327952Sdim MCStreamer::EmitCFIRestore(Register); 1635327952Sdim OS << "\t.cfi_restore "; 1636327952Sdim EmitRegisterName(Register); 1637327952Sdim EmitEOL(); 1638327952Sdim} 1639327952Sdim 1640221345Sdimvoid MCAsmStreamer::EmitCFISameValue(int64_t Register) { 1641221345Sdim MCStreamer::EmitCFISameValue(Register); 1642223017Sdim OS << "\t.cfi_same_value "; 1643223017Sdim EmitRegisterName(Register); 1644221345Sdim EmitEOL(); 1645221345Sdim} 1646221345Sdim 1647221345Sdimvoid MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { 1648221345Sdim MCStreamer::EmitCFIRelOffset(Register, Offset); 1649223017Sdim OS << "\t.cfi_rel_offset "; 1650223017Sdim EmitRegisterName(Register); 1651223017Sdim OS << ", " << Offset; 1652221345Sdim EmitEOL(); 1653221345Sdim} 1654221345Sdim 1655221345Sdimvoid MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { 1656221345Sdim MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); 1657221345Sdim OS << "\t.cfi_adjust_cfa_offset " << Adjustment; 1658221345Sdim EmitEOL(); 1659221345Sdim} 1660221345Sdim 1661234353Sdimvoid MCAsmStreamer::EmitCFISignalFrame() { 1662234353Sdim MCStreamer::EmitCFISignalFrame(); 1663239462Sdim OS << "\t.cfi_signal_frame"; 1664234353Sdim EmitEOL(); 1665234353Sdim} 1666234353Sdim 1667249423Sdimvoid MCAsmStreamer::EmitCFIUndefined(int64_t Register) { 1668249423Sdim MCStreamer::EmitCFIUndefined(Register); 1669249423Sdim OS << "\t.cfi_undefined " << Register; 1670249423Sdim EmitEOL(); 1671249423Sdim} 1672249423Sdim 1673249423Sdimvoid MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { 1674249423Sdim MCStreamer::EmitCFIRegister(Register1, Register2); 1675249423Sdim OS << "\t.cfi_register " << Register1 << ", " << Register2; 1676249423Sdim EmitEOL(); 1677249423Sdim} 1678249423Sdim 1679261991Sdimvoid MCAsmStreamer::EmitCFIWindowSave() { 1680261991Sdim MCStreamer::EmitCFIWindowSave(); 1681261991Sdim OS << "\t.cfi_window_save"; 1682261991Sdim EmitEOL(); 1683261991Sdim} 1684261991Sdim 1685344779Sdimvoid MCAsmStreamer::EmitCFINegateRAState() { 1686344779Sdim MCStreamer::EmitCFINegateRAState(); 1687344779Sdim OS << "\t.cfi_negate_ra_state"; 1688344779Sdim EmitEOL(); 1689344779Sdim} 1690344779Sdim 1691327952Sdimvoid MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) { 1692327952Sdim MCStreamer::EmitCFIReturnColumn(Register); 1693327952Sdim OS << "\t.cfi_return_column " << Register; 1694327952Sdim EmitEOL(); 1695327952Sdim} 1696223017Sdim 1697344779Sdimvoid MCAsmStreamer::EmitCFIBKeyFrame() { 1698344779Sdim MCStreamer::EmitCFIBKeyFrame(); 1699344779Sdim OS << "\t.cfi_b_key_frame"; 1700344779Sdim EmitEOL(); 1701344779Sdim} 1702344779Sdim 1703327952Sdimvoid MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { 1704327952Sdim MCStreamer::EmitWinCFIStartProc(Symbol, Loc); 1705327952Sdim 1706288943Sdim OS << ".seh_proc "; 1707288943Sdim Symbol->print(OS, MAI); 1708223017Sdim EmitEOL(); 1709223017Sdim} 1710223017Sdim 1711327952Sdimvoid MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) { 1712327952Sdim MCStreamer::EmitWinCFIEndProc(Loc); 1713223017Sdim 1714223017Sdim OS << "\t.seh_endproc"; 1715223017Sdim EmitEOL(); 1716223017Sdim} 1717223017Sdim 1718344779Sdim// TODO: Implement 1719344779Sdimvoid MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) { 1720344779Sdim} 1721344779Sdim 1722327952Sdimvoid MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) { 1723327952Sdim MCStreamer::EmitWinCFIStartChained(Loc); 1724223017Sdim 1725223017Sdim OS << "\t.seh_startchained"; 1726223017Sdim EmitEOL(); 1727223017Sdim} 1728223017Sdim 1729327952Sdimvoid MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) { 1730327952Sdim MCStreamer::EmitWinCFIEndChained(Loc); 1731223017Sdim 1732223017Sdim OS << "\t.seh_endchained"; 1733223017Sdim EmitEOL(); 1734223017Sdim} 1735223017Sdim 1736276479Sdimvoid MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, 1737327952Sdim bool Except, SMLoc Loc) { 1738327952Sdim MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc); 1739223017Sdim 1740288943Sdim OS << "\t.seh_handler "; 1741288943Sdim Sym->print(OS, MAI); 1742223017Sdim if (Unwind) 1743223017Sdim OS << ", @unwind"; 1744223017Sdim if (Except) 1745223017Sdim OS << ", @except"; 1746223017Sdim EmitEOL(); 1747223017Sdim} 1748223017Sdim 1749327952Sdimvoid MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) { 1750327952Sdim MCStreamer::EmitWinEHHandlerData(Loc); 1751223017Sdim 1752223017Sdim // Switch sections. Don't call SwitchSection directly, because that will 1753223017Sdim // cause the section switch to be visible in the emitted assembly. 1754223017Sdim // We only do this so the section switch that terminates the handler 1755223017Sdim // data block is visible. 1756280031Sdim WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); 1757360784Sdim 1758360784Sdim // Do nothing if no frame is open. MCStreamer should've already reported an 1759360784Sdim // error. 1760360784Sdim if (!CurFrame) 1761360784Sdim return; 1762360784Sdim 1763309124Sdim MCSection *TextSec = &CurFrame->Function->getSection(); 1764309124Sdim MCSection *XData = getAssociatedXDataSection(TextSec); 1765288943Sdim SwitchSectionNoChange(XData); 1766223017Sdim 1767223017Sdim OS << "\t.seh_handlerdata"; 1768223017Sdim EmitEOL(); 1769223017Sdim} 1770223017Sdim 1771360784Sdimvoid MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) { 1772327952Sdim MCStreamer::EmitWinCFIPushReg(Register, Loc); 1773223017Sdim 1774360784Sdim OS << "\t.seh_pushreg "; 1775360784Sdim InstPrinter->printRegName(OS, Register); 1776223017Sdim EmitEOL(); 1777223017Sdim} 1778223017Sdim 1779360784Sdimvoid MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset, 1780327952Sdim SMLoc Loc) { 1781327952Sdim MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc); 1782223017Sdim 1783360784Sdim OS << "\t.seh_setframe "; 1784360784Sdim InstPrinter->printRegName(OS, Register); 1785360784Sdim OS << ", " << Offset; 1786223017Sdim EmitEOL(); 1787223017Sdim} 1788223017Sdim 1789327952Sdimvoid MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) { 1790327952Sdim MCStreamer::EmitWinCFIAllocStack(Size, Loc); 1791223017Sdim 1792223017Sdim OS << "\t.seh_stackalloc " << Size; 1793223017Sdim EmitEOL(); 1794223017Sdim} 1795223017Sdim 1796360784Sdimvoid MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset, 1797327952Sdim SMLoc Loc) { 1798327952Sdim MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc); 1799223017Sdim 1800360784Sdim OS << "\t.seh_savereg "; 1801360784Sdim InstPrinter->printRegName(OS, Register); 1802360784Sdim OS << ", " << Offset; 1803223017Sdim EmitEOL(); 1804223017Sdim} 1805223017Sdim 1806360784Sdimvoid MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset, 1807327952Sdim SMLoc Loc) { 1808327952Sdim MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc); 1809223017Sdim 1810360784Sdim OS << "\t.seh_savexmm "; 1811360784Sdim InstPrinter->printRegName(OS, Register); 1812360784Sdim OS << ", " << Offset; 1813223017Sdim EmitEOL(); 1814223017Sdim} 1815223017Sdim 1816327952Sdimvoid MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) { 1817327952Sdim MCStreamer::EmitWinCFIPushFrame(Code, Loc); 1818223017Sdim 1819223017Sdim OS << "\t.seh_pushframe"; 1820223017Sdim if (Code) 1821223017Sdim OS << " @code"; 1822223017Sdim EmitEOL(); 1823223017Sdim} 1824223017Sdim 1825327952Sdimvoid MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) { 1826327952Sdim MCStreamer::EmitWinCFIEndProlog(Loc); 1827223017Sdim 1828223017Sdim OS << "\t.seh_endprologue"; 1829223017Sdim EmitEOL(); 1830223017Sdim} 1831223017Sdim 1832341825Sdimvoid MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, 1833341825Sdim const MCSymbolRefExpr *To, 1834341825Sdim uint64_t Count) { 1835341825Sdim OS << "\t.cg_profile "; 1836341825Sdim From->getSymbol().print(OS, MAI); 1837341825Sdim OS << ", "; 1838341825Sdim To->getSymbol().print(OS, MAI); 1839341825Sdim OS << ", " << Count; 1840341825Sdim EmitEOL(); 1841341825Sdim} 1842341825Sdim 1843276479Sdimvoid MCAsmStreamer::AddEncodingComment(const MCInst &Inst, 1844353358Sdim const MCSubtargetInfo &STI) { 1845203954Srdivacky raw_ostream &OS = GetCommentOS(); 1846203954Srdivacky SmallString<256> Code; 1847203954Srdivacky SmallVector<MCFixup, 4> Fixups; 1848203954Srdivacky raw_svector_ostream VecOS(Code); 1849203954Srdivacky 1850341825Sdim // If we have no code emitter, don't emit code. 1851341825Sdim if (!getAssembler().getEmitterPtr()) 1852341825Sdim return; 1853341825Sdim 1854341825Sdim getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); 1855341825Sdim 1856203954Srdivacky // If we are showing fixups, create symbolic markers in the encoded 1857203954Srdivacky // representation. We do this by making a per-bit map to the fixup item index, 1858203954Srdivacky // then trying to display it as nicely as possible. 1859203954Srdivacky SmallVector<uint8_t, 64> FixupMap; 1860203954Srdivacky FixupMap.resize(Code.size() * 8); 1861203954Srdivacky for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 1862203954Srdivacky FixupMap[i] = 0; 1863203954Srdivacky 1864203954Srdivacky for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1865203954Srdivacky MCFixup &F = Fixups[i]; 1866341825Sdim const MCFixupKindInfo &Info = 1867341825Sdim getAssembler().getBackend().getFixupKindInfo(F.getKind()); 1868203954Srdivacky for (unsigned j = 0; j != Info.TargetSize; ++j) { 1869203954Srdivacky unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 1870203954Srdivacky assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 1871203954Srdivacky FixupMap[Index] = 1 + i; 1872203954Srdivacky } 1873203954Srdivacky } 1874203954Srdivacky 1875224145Sdim // FIXME: Note the fixup comments for Thumb2 are completely bogus since the 1876218893Sdim // high order halfword of a 32-bit Thumb2 instruction is emitted first. 1877203954Srdivacky OS << "encoding: ["; 1878203954Srdivacky for (unsigned i = 0, e = Code.size(); i != e; ++i) { 1879203954Srdivacky if (i) 1880203954Srdivacky OS << ','; 1881203954Srdivacky 1882203954Srdivacky // See if all bits are the same map entry. 1883203954Srdivacky uint8_t MapEntry = FixupMap[i * 8 + 0]; 1884203954Srdivacky for (unsigned j = 1; j != 8; ++j) { 1885203954Srdivacky if (FixupMap[i * 8 + j] == MapEntry) 1886203954Srdivacky continue; 1887203954Srdivacky 1888203954Srdivacky MapEntry = uint8_t(~0U); 1889203954Srdivacky break; 1890203954Srdivacky } 1891203954Srdivacky 1892203954Srdivacky if (MapEntry != uint8_t(~0U)) { 1893203954Srdivacky if (MapEntry == 0) { 1894203954Srdivacky OS << format("0x%02x", uint8_t(Code[i])); 1895203954Srdivacky } else { 1896218893Sdim if (Code[i]) { 1897218893Sdim // FIXME: Some of the 8 bits require fix up. 1898218893Sdim OS << format("0x%02x", uint8_t(Code[i])) << '\'' 1899218893Sdim << char('A' + MapEntry - 1) << '\''; 1900218893Sdim } else 1901218893Sdim OS << char('A' + MapEntry - 1); 1902198090Srdivacky } 1903203954Srdivacky } else { 1904203954Srdivacky // Otherwise, write out in binary. 1905203954Srdivacky OS << "0b"; 1906203954Srdivacky for (unsigned j = 8; j--;) { 1907203954Srdivacky unsigned Bit = (Code[i] >> j) & 1; 1908221345Sdim 1909218893Sdim unsigned FixupBit; 1910261991Sdim if (MAI->isLittleEndian()) 1911218893Sdim FixupBit = i * 8 + j; 1912218893Sdim else 1913218893Sdim FixupBit = i * 8 + (7-j); 1914221345Sdim 1915218893Sdim if (uint8_t MapEntry = FixupMap[FixupBit]) { 1916203954Srdivacky assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 1917203954Srdivacky OS << char('A' + MapEntry - 1); 1918203954Srdivacky } else 1919203954Srdivacky OS << Bit; 1920203954Srdivacky } 1921198090Srdivacky } 1922203954Srdivacky } 1923353358Sdim OS << "]\n"; 1924198090Srdivacky 1925203954Srdivacky for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1926203954Srdivacky MCFixup &F = Fixups[i]; 1927341825Sdim const MCFixupKindInfo &Info = 1928341825Sdim getAssembler().getBackend().getFixupKindInfo(F.getKind()); 1929203954Srdivacky OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 1930203954Srdivacky << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 1931195340Sed } 1932203954Srdivacky} 1933198090Srdivacky 1934314564Sdimvoid MCAsmStreamer::EmitInstruction(const MCInst &Inst, 1935353358Sdim const MCSubtargetInfo &STI) { 1936314564Sdim assert(getCurrentSectionOnly() && 1937251662Sdim "Cannot emit contents before setting section!"); 1938203954Srdivacky 1939203954Srdivacky // Show the encoding in a comment if we have a code emitter. 1940353358Sdim AddEncodingComment(Inst, STI); 1941203954Srdivacky 1942203954Srdivacky // Show the MCInst if enabled. 1943208599Srdivacky if (ShowInst) { 1944288943Sdim Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); 1945208599Srdivacky GetCommentOS() << "\n"; 1946208599Srdivacky } 1947208599Srdivacky 1948288943Sdim if(getTargetStreamer()) 1949360784Sdim getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS); 1950203954Srdivacky else 1951360784Sdim InstPrinter->printInst(&Inst, 0, "", STI, OS); 1952288943Sdim 1953321369Sdim StringRef Comments = CommentToEmit; 1954321369Sdim if (Comments.size() && Comments.back() != '\n') 1955321369Sdim GetCommentOS() << "\n"; 1956321369Sdim 1957202878Srdivacky EmitEOL(); 1958195098Sed} 1959195098Sed 1960249423Sdimvoid MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) { 1961249423Sdim OS << "\t.bundle_align_mode " << AlignPow2; 1962249423Sdim EmitEOL(); 1963249423Sdim} 1964249423Sdim 1965249423Sdimvoid MCAsmStreamer::EmitBundleLock(bool AlignToEnd) { 1966249423Sdim OS << "\t.bundle_lock"; 1967249423Sdim if (AlignToEnd) 1968249423Sdim OS << " align_to_end"; 1969249423Sdim EmitEOL(); 1970249423Sdim} 1971249423Sdim 1972249423Sdimvoid MCAsmStreamer::EmitBundleUnlock() { 1973249423Sdim OS << "\t.bundle_unlock"; 1974249423Sdim EmitEOL(); 1975249423Sdim} 1976249423Sdim 1977296417Sdimbool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, 1978341825Sdim const MCExpr *Expr, SMLoc, 1979341825Sdim const MCSubtargetInfo &STI) { 1980296417Sdim OS << "\t.reloc "; 1981296417Sdim Offset.print(OS, MAI); 1982296417Sdim OS << ", " << Name; 1983296417Sdim if (Expr) { 1984296417Sdim OS << ", "; 1985296417Sdim Expr->print(OS, MAI); 1986296417Sdim } 1987296417Sdim EmitEOL(); 1988296417Sdim return false; 1989296417Sdim} 1990296417Sdim 1991341825Sdimvoid MCAsmStreamer::EmitAddrsig() { 1992341825Sdim OS << "\t.addrsig"; 1993341825Sdim EmitEOL(); 1994341825Sdim} 1995341825Sdim 1996341825Sdimvoid MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) { 1997341825Sdim OS << "\t.addrsig_sym "; 1998341825Sdim Sym->print(OS, MAI); 1999341825Sdim EmitEOL(); 2000341825Sdim} 2001341825Sdim 2002218893Sdim/// EmitRawText - If this file is backed by an assembly streamer, this dumps 2003206274Srdivacky/// the specified string in the output .s file. This capability is 2004206274Srdivacky/// indicated by the hasRawTextSupport() predicate. 2005261991Sdimvoid MCAsmStreamer::EmitRawTextImpl(StringRef String) { 2006206274Srdivacky if (!String.empty() && String.back() == '\n') 2007206274Srdivacky String = String.substr(0, String.size()-1); 2008206274Srdivacky OS << String; 2009206274Srdivacky EmitEOL(); 2010206274Srdivacky} 2011206274Srdivacky 2012234353Sdimvoid MCAsmStreamer::FinishImpl() { 2013234353Sdim // If we are generating dwarf for assembly source files dump out the sections. 2014234353Sdim if (getContext().getGenDwarfForAssembly()) 2015276479Sdim MCGenDwarfInfo::Emit(this); 2016234353Sdim 2017276479Sdim // Emit the label for the line table, if requested - since the rest of the 2018276479Sdim // line table will be defined by .loc/.file directives, and not emitted 2019276479Sdim // directly, the label is the only work required here. 2020353358Sdim const auto &Tables = getContext().getMCDwarfLineTables(); 2021276479Sdim if (!Tables.empty()) { 2022276479Sdim assert(Tables.size() == 1 && "asm output only supports one line table"); 2023276479Sdim if (auto *Label = Tables.begin()->second.getLabel()) { 2024276479Sdim SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); 2025276479Sdim EmitLabel(Label); 2026276479Sdim } 2027276479Sdim } 2028195098Sed} 2029261991Sdim 2030202878SrdivackyMCStreamer *llvm::createAsmStreamer(MCContext &Context, 2031288943Sdim std::unique_ptr<formatted_raw_ostream> OS, 2032276479Sdim bool isVerboseAsm, bool useDwarfDirectory, 2033341825Sdim MCInstPrinter *IP, 2034341825Sdim std::unique_ptr<MCCodeEmitter> &&CE, 2035341825Sdim std::unique_ptr<MCAsmBackend> &&MAB, 2036341825Sdim bool ShowInst) { 2037288943Sdim return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, 2038341825Sdim useDwarfDirectory, IP, std::move(CE), std::move(MAB), 2039341825Sdim ShowInst); 2040195098Sed} 2041