LCOV - code coverage report
Current view: top level - src - disasm.cpp (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 550 656 83.8 %
Date: 2022-07-16 23:42:53 Functions: 50 56 89.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 276 422 65.4 %

           Branch data     Line data    Source code
       1                 :            : //===------------- Disassembler for in-memory function --------------------===//
       2                 :            : //
       3                 :            : // Modified for use in The Julia Language from code in the  llvm-mc project:
       4                 :            : //      llvm-mc.cpp and Disassembler.cpp
       5                 :            : //
       6                 :            : // Original copyright:
       7                 :            : //
       8                 :            : // University of Illinois/NCSA
       9                 :            : // Open Source License
      10                 :            : // Copyright (c) 2003-2016 University of Illinois at Urbana-Champaign.
      11                 :            : // All rights reserved.
      12                 :            : //
      13                 :            : //  Developed by:
      14                 :            : //
      15                 :            : //    LLVM Team
      16                 :            : //
      17                 :            : //    University of Illinois at Urbana-Champaign
      18                 :            : //
      19                 :            : //    http://llvm.org
      20                 :            : //
      21                 :            : // Permission is hereby granted, free of charge, to any person obtaining a copy of
      22                 :            : // this software and associated documentation files (the "Software"), to deal with
      23                 :            : // the Software without restriction, including without limitation the rights to
      24                 :            : // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
      25                 :            : // of the Software, and to permit persons to whom the Software is furnished to do
      26                 :            : // so, subject to the following conditions:
      27                 :            : //
      28                 :            : //    * Redistributions of source code must retain the above copyright notice,
      29                 :            : //      this list of conditions and the following disclaimers.
      30                 :            : //
      31                 :            : //    * Redistributions in binary form must reproduce the above copyright notice,
      32                 :            : //      this list of conditions and the following disclaimers in the
      33                 :            : //      documentation and/or other materials provided with the distribution.
      34                 :            : //
      35                 :            : //    * Neither the names of the LLVM Team, University of Illinois at
      36                 :            : //      Urbana-Champaign, nor the names of its contributors may be used to
      37                 :            : //      endorse or promote products derived from this Software without specific
      38                 :            : //      prior written permission.
      39                 :            : //
      40                 :            : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      41                 :            : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      42                 :            : // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
      43                 :            : // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      44                 :            : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      45                 :            : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
      46                 :            : // SOFTWARE.
      47                 :            : //===----------------------------------------------------------------------===//
      48                 :            : //
      49                 :            : // This class implements a disassembler of a memory block, given a function
      50                 :            : // pointer and size.
      51                 :            : //
      52                 :            : //===----------------------------------------------------------------------===//
      53                 :            : 
      54                 :            : #include <map>
      55                 :            : #include <set>
      56                 :            : #include <string>
      57                 :            : 
      58                 :            : #include "llvm-version.h"
      59                 :            : 
      60                 :            : // for outputting disassembly
      61                 :            : #include <llvm/ADT/Triple.h>
      62                 :            : #include <llvm/AsmParser/Parser.h>
      63                 :            : #include <llvm/Analysis/TargetTransformInfo.h>
      64                 :            : #include <llvm/BinaryFormat/COFF.h>
      65                 :            : #include <llvm/BinaryFormat/MachO.h>
      66                 :            : #include <llvm/DebugInfo/DIContext.h>
      67                 :            : #include <llvm/DebugInfo/DWARF/DWARFContext.h>
      68                 :            : #include <llvm/IR/AssemblyAnnotationWriter.h>
      69                 :            : #include <llvm/IR/DebugInfo.h>
      70                 :            : #include <llvm/IR/Function.h>
      71                 :            : #include <llvm/IR/IntrinsicInst.h>
      72                 :            : #include <llvm/IR/LLVMContext.h>
      73                 :            : #include <llvm/IR/Module.h>
      74                 :            : #include <llvm/MC/MCAsmBackend.h>
      75                 :            : #include <llvm/MC/MCAsmInfo.h>
      76                 :            : #include <llvm/MC/MCCodeEmitter.h>
      77                 :            : #include <llvm/MC/MCContext.h>
      78                 :            : #include <llvm/MC/MCDisassembler/MCDisassembler.h>
      79                 :            : #include <llvm/MC/MCDisassembler/MCExternalSymbolizer.h>
      80                 :            : #include <llvm/MC/MCExpr.h>
      81                 :            : #include <llvm/MC/MCInst.h>
      82                 :            : #include <llvm/MC/MCInstPrinter.h>
      83                 :            : #include <llvm/MC/MCInstrAnalysis.h>
      84                 :            : #include <llvm/MC/MCInstrInfo.h>
      85                 :            : #include <llvm/MC/MCObjectFileInfo.h>
      86                 :            : #include <llvm/MC/MCRegisterInfo.h>
      87                 :            : #include <llvm/MC/MCStreamer.h>
      88                 :            : #include <llvm/MC/MCSubtargetInfo.h>
      89                 :            : #include <llvm/MC/MCSymbol.h>
      90                 :            : #include <llvm/Object/ObjectFile.h>
      91                 :            : #include <llvm/Support/FormattedStream.h>
      92                 :            : #include <llvm/Support/MemoryBuffer.h>
      93                 :            : #include <llvm/Support/NativeFormatting.h>
      94                 :            : #include <llvm/Support/SourceMgr.h>
      95                 :            : #if JL_LLVM_VERSION >= 140000
      96                 :            : #include <llvm/MC/TargetRegistry.h>
      97                 :            : #else
      98                 :            : #include <llvm/Support/TargetRegistry.h>
      99                 :            : #endif
     100                 :            : #include <llvm/Support/TargetSelect.h>
     101                 :            : #include <llvm/Support/raw_ostream.h>
     102                 :            : 
     103                 :            : // for outputting assembly
     104                 :            : #include <llvm/CodeGen/AsmPrinter.h>
     105                 :            : #include <llvm/CodeGen/AsmPrinterHandler.h>
     106                 :            : #include <llvm/CodeGen/MachineModuleInfo.h>
     107                 :            : #include <llvm/CodeGen/Passes.h>
     108                 :            : #include <llvm/CodeGen/TargetPassConfig.h>
     109                 :            : #include <llvm/Support/CodeGen.h>
     110                 :            : #include <llvm/IR/LegacyPassManager.h>
     111                 :            : 
     112                 :            : #include <llvm-c/Disassembler.h>
     113                 :            : 
     114                 :            : #include "julia.h"
     115                 :            : #include "julia_internal.h"
     116                 :            : #include "jitlayers.h"
     117                 :            : #include "processor.h"
     118                 :            : 
     119                 :            : using namespace llvm;
     120                 :            : #include "debuginfo.h"
     121                 :            : #include "julia_assert.h"
     122                 :            : 
     123                 :            : // helper class for tracking inlining context while printing debug info
     124                 :            : class DILineInfoPrinter {
     125                 :            :     // internal state:
     126                 :            :     std::vector<DILineInfo> context;
     127                 :            :     uint32_t inline_depth = 0;
     128                 :            :     // configuration options:
     129                 :            :     const char* LineStart = "; ";
     130                 :            :     bool bracket_outer = false;
     131                 :            :     bool collapse_recursive = true;
     132                 :            : 
     133                 :            :     enum {
     134                 :            :         output_none = 0,
     135                 :            :         output_source = 1,
     136                 :            :     } verbosity = output_source;
     137                 :            : public:
     138                 :        112 :     DILineInfoPrinter(const char *LineStart, bool bracket_outer)
     139                 :        112 :         : LineStart(LineStart),
     140                 :        112 :           bracket_outer(bracket_outer) {};
     141                 :        112 :     void SetVerbosity(const char *c)
     142                 :            :     {
     143         [ -  + ]:        112 :         if (StringRef("default") == c) {
     144                 :          0 :             verbosity = output_source;
     145                 :            :         }
     146         [ +  + ]:        112 :         else if (StringRef("source") == c) {
     147                 :        109 :             verbosity = output_source;
     148                 :            :         }
     149         [ +  - ]:          3 :         else if (StringRef("none") == c) {
     150                 :          3 :             verbosity = output_none;
     151                 :            :         }
     152                 :        112 :     }
     153                 :            : 
     154                 :            :     void emit_finish(raw_ostream &Out);
     155                 :            :     void emit_lineinfo(raw_ostream &Out, std::vector<DILineInfo> &DI);
     156                 :            : 
     157                 :            :     struct repeat {
     158                 :            :         size_t times;
     159                 :            :         const char *c;
     160                 :            :     };
     161                 :      10089 :     struct repeat inlining_indent(const char *c)
     162                 :            :     {
     163                 :            :         return repeat{
     164                 :      10089 :             std::max(inline_depth + bracket_outer, (uint32_t)1) - 1,
     165                 :      10089 :             c };
     166                 :            :     }
     167                 :            : 
     168                 :            :     template<class T>
     169                 :          6 :     void emit_lineinfo(std::string &Out, T &DI)
     170                 :            :     {
     171                 :         12 :         raw_string_ostream OS(Out);
     172                 :          6 :         emit_lineinfo(OS, DI);
     173                 :          6 :     }
     174                 :            : 
     175                 :          3 :     void emit_lineinfo(raw_ostream &Out, DILineInfo &DI)
     176                 :            :     {
     177                 :          6 :         std::vector<DILineInfo> DIvec(1);
     178                 :          3 :         DIvec[0] = DI;
     179                 :          3 :         emit_lineinfo(Out, DIvec);
     180                 :          3 :     }
     181                 :            : 
     182                 :          3 :     void emit_lineinfo(raw_ostream &Out, DIInliningInfo &DI)
     183                 :            :     {
     184                 :          3 :         uint32_t nframes = DI.getNumberOfFrames();
     185                 :          6 :         std::vector<DILineInfo> DIvec(nframes);
     186         [ +  + ]:          6 :         for (uint32_t i = 0; i < DI.getNumberOfFrames(); i++) {
     187                 :          3 :             DIvec[i] = DI.getFrame(i);
     188                 :            :         }
     189                 :          3 :         emit_lineinfo(Out, DIvec);
     190                 :          3 :     }
     191                 :            : 
     192                 :          3 :     void emit_finish(std::string &Out)
     193                 :            :     {
     194                 :          6 :         raw_string_ostream OS(Out);
     195                 :          3 :         emit_finish(OS);
     196                 :          3 :     }
     197                 :            : };
     198                 :            : 
     199                 :      20769 : static raw_ostream &operator<<(raw_ostream &Out, struct DILineInfoPrinter::repeat i)
     200                 :            : {
     201         [ +  + ]:      20769 :     while (i.times-- > 0)
     202                 :      10112 :         Out << i.c;
     203                 :      10657 :     return Out;
     204                 :            : }
     205                 :            : 
     206                 :        115 : void DILineInfoPrinter::emit_finish(raw_ostream &Out)
     207                 :            : {
     208                 :        115 :     auto pops = inlining_indent("└");
     209         [ +  + ]:        115 :     if (pops.times > 0)
     210                 :         31 :         Out << LineStart << pops << '\n';
     211                 :        115 :     context.clear();
     212                 :        115 :     this->inline_depth = 0;
     213                 :        115 : }
     214                 :            : 
     215                 :       1227 : void DILineInfoPrinter::emit_lineinfo(raw_ostream &Out, std::vector<DILineInfo> &DI)
     216                 :            : {
     217         [ +  + ]:       1227 :     if (verbosity == output_none)
     218                 :          6 :         return;
     219                 :       1221 :     uint32_t nframes = DI.size();
     220         [ -  + ]:       1221 :     if (nframes == 0)
     221                 :          0 :         return; // just skip over lines with no debug info at all
     222                 :            :     // compute the size of the matching prefix in the inlining information stack
     223                 :            :     uint32_t nctx;
     224   [ +  +  +  +  :       2654 :     for (nctx = 0; nctx < context.size() && nctx < nframes; nctx++) {
                   +  + ]
     225                 :       2188 :         const DILineInfo &CtxLine = context.at(nctx);
     226                 :       2188 :         const DILineInfo &FrameLine = DI.at(nframes - 1 - nctx);
     227         [ +  + ]:       2188 :         if (CtxLine != FrameLine) {
     228                 :        755 :             break;
     229                 :            :         }
     230                 :            :     }
     231                 :       1221 :     bool update_line_only = false;
     232         [ +  - ]:       1221 :     if (collapse_recursive) {
     233         [ +  + ]:       1221 :         if (nctx > 0) {
     234                 :            :             // check if we're adding more frames with the same method name,
     235                 :            :             // if so, drop all existing calls to it from the top of the context
     236                 :            :             // AND check if instead the context was previously printed that way
     237                 :            :             // but now has removed the recursive frames
     238                 :        601 :             StringRef method = StringRef(context.at(nctx - 1).FunctionName).rtrim(';'); // last matching frame
     239   [ +  +  +  +  :       1497 :             if ((nctx < nframes && StringRef(DI.at(nframes - nctx - 1).FunctionName).rtrim(';') == method) ||
                   +  + ]
     240   [ +  +  +  + ]:       1497 :                 (nctx < context.size() && StringRef(context.at(nctx).FunctionName).rtrim(';') == method)) {
     241                 :         85 :                 update_line_only = true;
     242                 :            :                 // transform nctx to exclude the combined frames
     243   [ +  +  +  +  :        236 :                 while (nctx > 0 && StringRef(context.at(nctx - 1).FunctionName).rtrim(';') == method)
                   +  + ]
     244                 :        151 :                     nctx -= 1;
     245                 :            :             }
     246                 :            :         }
     247   [ +  +  +  +  :       1221 :         if (!update_line_only && nctx < context.size() && nctx < nframes) {
             +  +  +  + ]
     248                 :            :             // look at the first non-matching element to see if we are only changing the line number
     249                 :        679 :             const DILineInfo &CtxLine = context.at(nctx);
     250                 :        679 :             const DILineInfo &FrameLine = DI.at(nframes - 1 - nctx);
     251         [ +  + ]:        679 :             if (StringRef(CtxLine.FunctionName).rtrim(';') == StringRef(FrameLine.FunctionName).rtrim(';'))
     252                 :        526 :                 update_line_only = true;
     253                 :            :         }
     254                 :            :     }
     255   [ #  #  #  #  :          0 :     else if (nctx < context.size() && nctx < nframes) {
                   #  # ]
     256                 :            :         // look at the first non-matching element to see if we are only changing the line number
     257                 :          0 :         const DILineInfo &CtxLine = context.at(nctx);
     258                 :          0 :         const DILineInfo &FrameLine = DI.at(nframes - 1 - nctx);
     259   [ #  #  #  # ]:          0 :         if (CtxLine.FileName == FrameLine.FileName &&
     260         [ #  # ]:          0 :                 StringRef(CtxLine.FunctionName).rtrim(';') == StringRef(FrameLine.FunctionName).rtrim(';')) {
     261                 :          0 :             update_line_only = true;
     262                 :            :         }
     263                 :            :     }
     264                 :            :     // examine how many frames we're returning from
     265         [ +  + ]:       1221 :     if (nctx < context.size()) {
     266                 :            :         // compute the new inlining depth
     267                 :            :         uint32_t npops;
     268         [ +  - ]:        964 :         if (collapse_recursive) {
     269                 :        964 :             npops = 1;
     270                 :        964 :             StringRef Prev = StringRef(context.at(nctx).FunctionName).rtrim(';');
     271         [ +  + ]:       1667 :             for (uint32_t i = nctx + 1; i < context.size(); i++) {
     272                 :        703 :                 StringRef Next = StringRef(context.at(i).FunctionName).rtrim(';');
     273         [ +  + ]:        703 :                 if (Prev != Next)
     274                 :        412 :                     npops += 1;
     275                 :        703 :                 Prev = Next;
     276                 :            :             }
     277                 :            :         }
     278                 :            :         else {
     279                 :          0 :             npops = context.size() - nctx;
     280                 :            :         }
     281                 :        964 :         context.resize(nctx);
     282   [ +  +  +  + ]:        964 :         update_line_only && (npops -= 1);
     283         [ +  + ]:        964 :         if (npops > 0) {
     284                 :        652 :             this->inline_depth -= npops;
     285                 :        652 :             Out << LineStart << inlining_indent("│") << repeat{npops, "└"} << '\n';
     286                 :            :         }
     287                 :            :     }
     288                 :            :     // print the new frames
     289         [ +  + ]:       2712 :     while (nctx < nframes) {
     290                 :       1491 :         const DILineInfo &frame = DI.at(nframes - 1 - nctx);
     291                 :       1491 :         Out << LineStart << inlining_indent("│");
     292                 :       1491 :         nctx += 1;
     293                 :       1491 :         context.push_back(frame);
     294         [ +  + ]:       1491 :         if (update_line_only) {
     295                 :        611 :             update_line_only = false;
     296                 :            :         }
     297                 :            :         else {
     298                 :        880 :             this->inline_depth += 1;
     299   [ +  +  +  + ]:        880 :             if (bracket_outer || nctx != 1)
     300                 :        800 :                 Out << "┌";
     301                 :            :         }
     302                 :       1491 :         Out << " @ " << frame.FileName;
     303   [ +  -  +  + ]:       1491 :         if (frame.Line != UINT_MAX && frame.Line != 0)
     304                 :       1444 :             Out << ":" << frame.Line;
     305                 :       1491 :         StringRef method = StringRef(frame.FunctionName).rtrim(';');
     306                 :       1491 :         Out << " within `" << method << "`";
     307         [ +  - ]:       1491 :         if (collapse_recursive) {
     308         [ +  + ]:       1783 :             while (nctx < nframes) {
     309                 :        796 :                 const DILineInfo &frame = DI.at(nframes - 1 - nctx);
     310         [ +  + ]:        796 :                 if (StringRef(frame.FunctionName).rtrim(';') != method)
     311                 :        504 :                     break;
     312                 :        292 :                 nctx += 1;
     313                 :        292 :                 context.push_back(frame);
     314                 :        292 :                 Out << " @ " << frame.FileName
     315                 :        292 :                     << ":" << frame.Line;
     316                 :            :             }
     317                 :            :         }
     318                 :       1491 :         Out << "\n";
     319                 :            :     }
     320                 :            : #ifndef JL_NDEBUG
     321                 :       1221 :     StringRef Prev = StringRef(context.at(0).FunctionName).rtrim(';');
     322                 :       1221 :     uint32_t depth2 = 1;
     323         [ +  + ]:       3065 :     for (uint32_t i = 1; i < nctx; i++) {
     324                 :       1844 :         StringRef Next = StringRef(context.at(i).FunctionName).rtrim(';');
     325   [ +  -  +  +  :       1844 :         if (!collapse_recursive || Prev != Next)
                   +  + ]
     326                 :       1488 :             depth2 += 1;
     327                 :       1844 :         Prev = Next;
     328                 :            :     }
     329         [ -  + ]:       1221 :     assert(this->inline_depth == depth2);
     330                 :            : #endif
     331                 :            : }
     332                 :            : 
     333                 :            : 
     334                 :            : // adaptor class for printing line numbers before llvm IR lines
     335                 :            : class LineNumberAnnotatedWriter : public AssemblyAnnotationWriter {
     336                 :            :     const DILocation *InstrLoc = nullptr;
     337                 :            :     DILineInfoPrinter LinePrinter;
     338                 :            :     DenseMap<const Instruction *, DILocation *> DebugLoc;
     339                 :            :     DenseMap<const Function *, DISubprogram *> Subprogram;
     340                 :            : public:
     341                 :        106 :     LineNumberAnnotatedWriter(const char *LineStart, bool bracket_outer, const char *debuginfo)
     342                 :        106 :       : LinePrinter(LineStart, bracket_outer) {
     343                 :        106 :         LinePrinter.SetVerbosity(debuginfo);
     344                 :        106 :     }
     345                 :            :     virtual void emitFunctionAnnot(const Function *, formatted_raw_ostream &);
     346                 :            :     virtual void emitInstructionAnnot(const Instruction *, formatted_raw_ostream &);
     347                 :            :     virtual void emitInstructionAnnot(const DILocation *, formatted_raw_ostream &);
     348                 :            :     virtual void emitBasicBlockEndAnnot(const BasicBlock *, formatted_raw_ostream &);
     349                 :            :     // virtual void printInfoComment(const Value &, formatted_raw_ostream &) {}
     350                 :            : 
     351                 :        112 :     void emitEnd(formatted_raw_ostream &Out) {
     352                 :        112 :         LinePrinter.emit_finish(Out);
     353                 :        112 :         InstrLoc = nullptr;
     354                 :        112 :     }
     355                 :            : 
     356                 :        775 :     void addSubprogram(const Function *F, DISubprogram *SP)
     357                 :            :     {
     358                 :        775 :         Subprogram[F] = SP;
     359                 :        775 :     }
     360                 :            : 
     361                 :       8184 :     void addDebugLoc(const Instruction *I, DILocation *Loc)
     362                 :            :     {
     363                 :       8184 :         DebugLoc[I] = Loc;
     364                 :       8184 :     }
     365                 :            : };
     366                 :            : 
     367                 :        145 : void LineNumberAnnotatedWriter::emitFunctionAnnot(
     368                 :            :       const Function *F, formatted_raw_ostream &Out)
     369                 :            : {
     370                 :        145 :     InstrLoc = nullptr;
     371                 :        145 :     DISubprogram *FuncLoc = F->getSubprogram();
     372         [ +  + ]:        145 :     if (!FuncLoc) {
     373                 :         89 :         auto SP = Subprogram.find(F);
     374         [ +  + ]:         89 :         if (SP != Subprogram.end())
     375                 :         49 :             FuncLoc = SP->second;
     376                 :            :     }
     377         [ +  + ]:        145 :     if (FuncLoc) {
     378                 :        210 :         std::vector<DILineInfo> DIvec(1);
     379                 :        105 :         DILineInfo &DI = DIvec.back();
     380                 :        105 :         DI.FunctionName = FuncLoc->getName().str();
     381                 :        105 :         DI.FileName = FuncLoc->getFilename().str();
     382                 :        105 :         DI.Line = FuncLoc->getLine();
     383                 :        105 :         LinePrinter.emit_lineinfo(Out, DIvec);
     384                 :            :     }
     385                 :        145 : }
     386                 :            : 
     387                 :       7831 : void LineNumberAnnotatedWriter::emitInstructionAnnot(
     388                 :            :       const Instruction *I, formatted_raw_ostream &Out)
     389                 :            : {
     390                 :       7831 :     const DILocation *NewInstrLoc = I->getDebugLoc();
     391         [ +  + ]:       7831 :     if (!NewInstrLoc) {
     392                 :       7277 :         auto Loc = DebugLoc.find(I);
     393         [ +  + ]:       7277 :         if (Loc != DebugLoc.end())
     394                 :       7098 :             NewInstrLoc = Loc->second;
     395                 :            :     }
     396                 :       7831 :     emitInstructionAnnot(NewInstrLoc, Out);
     397                 :       7831 :     Out << LinePrinter.inlining_indent(" ");
     398                 :       7831 : }
     399                 :            : 
     400                 :       8386 : void LineNumberAnnotatedWriter::emitInstructionAnnot(
     401                 :            :       const DILocation *NewInstrLoc, formatted_raw_ostream &Out)
     402                 :            : {
     403   [ +  +  +  + ]:       8386 :     if (NewInstrLoc && NewInstrLoc != InstrLoc) {
     404                 :       1116 :         InstrLoc = NewInstrLoc;
     405                 :       2232 :         std::vector<DILineInfo> DIvec;
     406                 :       1844 :         do {
     407                 :       2960 :             DIvec.emplace_back();
     408                 :       2960 :             DILineInfo &DI = DIvec.back();
     409                 :       2960 :             DIScope *scope = NewInstrLoc->getScope();
     410         [ +  - ]:       2960 :             if (scope)
     411                 :       2960 :                 DI.FunctionName = scope->getName().str();
     412                 :       2960 :             DI.FileName = NewInstrLoc->getFilename().str();
     413                 :       2960 :             DI.Line = NewInstrLoc->getLine();
     414                 :       2960 :             NewInstrLoc = NewInstrLoc->getInlinedAt();
     415         [ +  + ]:       2960 :         } while (NewInstrLoc);
     416                 :       1116 :         LinePrinter.emit_lineinfo(Out, DIvec);
     417                 :            :     }
     418                 :       8386 : }
     419                 :            : 
     420                 :        555 : void LineNumberAnnotatedWriter::emitBasicBlockEndAnnot(
     421                 :            :         const BasicBlock *BB, formatted_raw_ostream &Out)
     422                 :            : {
     423         [ +  + ]:        555 :     if (BB == &BB->getParent()->back())
     424                 :         88 :         emitEnd(Out);
     425                 :        555 : }
     426                 :            : 
     427                 :         49 : static void jl_strip_llvm_debug(Module *m, bool all_meta, LineNumberAnnotatedWriter *AAW)
     428                 :            : {
     429                 :            :     // strip metadata from all instructions in all functions in the module
     430                 :         49 :     Instruction *deletelast = nullptr; // can't actually delete until the iterator advances
     431         [ +  + ]:        824 :     for (Function &f : m->functions()) {
     432         [ +  - ]:        775 :         if (AAW)
     433                 :        775 :             AAW->addSubprogram(&f, f.getSubprogram());
     434         [ +  + ]:       1339 :         for (BasicBlock &f_bb : f) {
     435         [ +  + ]:       8829 :             for (Instruction &inst : f_bb) {
     436         [ +  + ]:       8265 :                 if (deletelast) {
     437                 :         81 :                     deletelast->eraseFromParent();
     438                 :         81 :                     deletelast = nullptr;
     439                 :            :                 }
     440                 :            :                 // remove dbg.declare and dbg.value calls
     441   [ +  +  +  +  :       8265 :                 if (isa<DbgDeclareInst>(inst) || isa<DbgValueInst>(inst)) {
                   +  + ]
     442                 :         81 :                     deletelast = &inst;
     443                 :         81 :                     continue;
     444                 :            :                 }
     445                 :            : 
     446                 :            :                 // iterate over all metadata kinds and set to NULL to remove
     447         [ +  - ]:       8184 :                 if (all_meta) {
     448                 :      16368 :                     SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
     449                 :       8184 :                     inst.getAllMetadataOtherThanDebugLoc(MDForInst);
     450         [ +  + ]:       9653 :                     for (const auto &md_iter : MDForInst) {
     451                 :       1469 :                         inst.setMetadata(md_iter.first, NULL);
     452                 :            :                     }
     453                 :            :                 }
     454                 :            :                 // record debug location before erasing it
     455         [ +  - ]:       8184 :                 if (AAW)
     456                 :       8184 :                     AAW->addDebugLoc(&inst, inst.getDebugLoc());
     457                 :       8184 :                 inst.setDebugLoc(DebugLoc());
     458                 :            :             }
     459         [ -  + ]:        564 :             if (deletelast) {
     460                 :          0 :                 deletelast->eraseFromParent();
     461                 :          0 :                 deletelast = nullptr;
     462                 :            :             }
     463                 :            :         }
     464                 :        775 :         f.setSubprogram(NULL);
     465                 :            :     }
     466         [ +  - ]:         49 :     if (all_meta) {
     467         [ +  + ]:        846 :         for (GlobalObject &g : m->global_objects()) {
     468                 :        797 :             g.clearMetadata();
     469                 :            :         }
     470                 :            :     }
     471                 :            :     // now that the subprogram is not referenced, we can delete it too
     472         [ +  - ]:         49 :     if (NamedMDNode *md = m->getNamedMetadata("llvm.dbg.cu"))
     473                 :         49 :         m->eraseNamedMetadata(md);
     474                 :            :     //if (NamedMDNode *md = m->getNamedMetadata("llvm.module.flags"))
     475                 :            :     //    m->eraseNamedMetadata(md);
     476                 :         49 : }
     477                 :            : 
     478                 :          0 : void jl_strip_llvm_debug(Module *m)
     479                 :            : {
     480                 :          0 :     jl_strip_llvm_debug(m, false, NULL);
     481                 :          0 : }
     482                 :            : 
     483                 :         49 : void jl_strip_llvm_addrspaces(Module *m)
     484                 :            : {
     485                 :         98 :     legacy::PassManager PM;
     486                 :         49 :     PM.add(createRemoveJuliaAddrspacesPass());
     487                 :         49 :     PM.run(*m);
     488                 :         49 : }
     489                 :            : 
     490                 :            : // print an llvm IR acquired from jl_get_llvmf
     491                 :            : // warning: this takes ownership of, and destroys, dump->TSM
     492                 :            : extern "C" JL_DLLEXPORT
     493                 :         82 : jl_value_t *jl_dump_function_ir_impl(jl_llvmf_dump_t *dump, char strip_ir_metadata, char dump_module, const char *debuginfo)
     494                 :            : {
     495                 :        164 :     std::string code;
     496                 :        164 :     raw_string_ostream stream(code);
     497                 :            : 
     498                 :            :     {
     499                 :            :         //RAII will release the module
     500                 :        164 :         auto TSM = std::unique_ptr<orc::ThreadSafeModule>(unwrap(dump->TSM));
     501                 :            :         //If TSM is not passed in, then the context MUST be locked externally.
     502                 :            :         //RAII will release the lock
     503                 :         82 :         Optional<orc::ThreadSafeContext::Lock> lock;
     504         [ +  - ]:         82 :         if (TSM) {
     505                 :         82 :             lock.emplace(TSM->getContext().getLock());
     506                 :            :         }
     507                 :         82 :         Function *llvmf = cast<Function>(unwrap(dump->F));
     508   [ +  -  +  -  :         82 :         if (!llvmf || (!llvmf->isDeclaration() && !llvmf->getParent()))
             -  +  -  + ]
     509                 :          0 :             jl_error("jl_dump_function_ir: Expected Function* in a temporary Module");
     510                 :            : 
     511                 :        164 :         LineNumberAnnotatedWriter AAW{"; ", false, debuginfo};
     512         [ -  + ]:         82 :         if (!llvmf->getParent()) {
     513                 :            :             // print the function declaration as-is
     514                 :          0 :             llvmf->print(stream, &AAW);
     515         [ #  # ]:          0 :             delete llvmf;
     516                 :            :         }
     517                 :            :         else {
     518   [ +  -  +  - ]:         82 :             assert(TSM && TSM->getModuleUnlocked() == llvmf->getParent() && "Passed module was not the same as function parent!");
     519                 :         82 :             auto m = TSM->getModuleUnlocked();
     520         [ +  + ]:         82 :             if (strip_ir_metadata) {
     521                 :         49 :                 std::string llvmfn(llvmf->getName());
     522                 :         49 :                 jl_strip_llvm_addrspaces(m);
     523                 :         49 :                 jl_strip_llvm_debug(m, true, &AAW);
     524                 :            :                 // rewriting the function type creates a new function, so look it up again
     525                 :         49 :                 llvmf = m->getFunction(llvmfn);
     526                 :            :             }
     527         [ +  + ]:         82 :             if (dump_module) {
     528                 :          6 :                 m->print(stream, &AAW);
     529                 :            :             }
     530                 :            :             else {
     531                 :         76 :                 llvmf->print(stream, &AAW);
     532                 :            :             }
     533                 :            :         }
     534                 :            :     }
     535                 :            : 
     536                 :         82 :     return jl_pchar_to_string(stream.str().data(), stream.str().size());
     537                 :            : }
     538                 :            : 
     539                 :            : static void jl_dump_asm_internal(
     540                 :            :         uintptr_t Fptr, size_t Fsize, int64_t slide,
     541                 :            :         object::SectionRef Section,
     542                 :            :         DIContext *di_ctx,
     543                 :            :         raw_ostream &rstream,
     544                 :            :         const char* asm_variant,
     545                 :            :         const char* debuginfo,
     546                 :            :         bool binary);
     547                 :            : 
     548                 :            : // This isn't particularly fast, but neither is printing assembly, and they're only used for interactive mode
     549                 :          3 : static uint64_t compute_obj_symsize(object::SectionRef Section, uint64_t offset)
     550                 :            : {
     551                 :            :     // Scan the object file for the closest symbols above and below offset in the given section
     552                 :          3 :     uint64_t lo = 0;
     553                 :          3 :     uint64_t hi = 0;
     554                 :          3 :     bool setlo = false;
     555                 :          3 :     uint64_t SAddr = Section.getAddress();
     556                 :          3 :     uint64_t SSize = Section.getSize();
     557   [ +  -  -  + ]:          3 :     if (offset < SAddr || offset >= SAddr + SSize)
     558                 :          0 :         return 0;
     559                 :            :     // test for lower and upper symbol bounds relative to other symbols
     560                 :          3 :     hi = SAddr + SSize;
     561         [ +  + ]:         30 :     for (const object::SymbolRef &Sym : Section.getObject()->symbols()) {
     562         [ +  + ]:         27 :         if (!Section.containsSymbol(Sym))
     563                 :         18 :             continue;
     564                 :          9 :         uint64_t Addr = cantFail(Sym.getAddress());
     565   [ +  +  +  - ]:          9 :         if (Addr <= offset && Addr >= lo) {
     566                 :            :             // test for lower bound on symbol
     567                 :          6 :             lo = Addr;
     568                 :          6 :             setlo = true;
     569                 :            :         }
     570   [ +  +  +  - ]:          9 :         if (Addr > offset && Addr < hi) {
     571                 :            :             // test for upper bound on symbol
     572                 :          3 :             hi = Addr;
     573                 :            :         }
     574                 :            :     }
     575         [ +  - ]:          3 :     if (setlo)
     576                 :          3 :         return hi - lo;
     577                 :          0 :     return 0;
     578                 :            : }
     579                 :            : 
     580                 :            : // print a native disassembly for the function starting at fptr
     581                 :            : extern "C" JL_DLLEXPORT
     582                 :          3 : jl_value_t *jl_dump_fptr_asm_impl(uint64_t fptr, char raw_mc, const char* asm_variant, const char *debuginfo, char binary)
     583                 :            : {
     584         [ -  + ]:          3 :     assert(fptr != 0);
     585                 :          6 :     std::string code;
     586                 :          6 :     raw_string_ostream stream(code);
     587                 :            : 
     588                 :            :     // Find debug info (line numbers) to print alongside
     589                 :          3 :     object::SectionRef Section;
     590                 :          3 :     int64_t slide = 0;
     591                 :          3 :     uint64_t symsize = 0;
     592                 :          3 :     llvm::DIContext *context = NULL;
     593         [ -  + ]:          3 :     if (!jl_DI_for_fptr(fptr, &symsize, &slide, &Section, &context)) {
     594         [ #  # ]:          0 :         if (!jl_dylib_DI_for_fptr(fptr, &Section, &slide, &context,
     595                 :            :                     false, NULL, NULL, NULL, NULL)) {
     596                 :          0 :             jl_printf(JL_STDERR, "WARNING: Unable to find function pointer\n");
     597                 :          0 :             return jl_pchar_to_string("", 0);
     598                 :            :         }
     599                 :            :     }
     600   [ +  -  +  -  :          3 :     if (symsize == 0 && Section.getObject())
                   +  - ]
     601                 :          3 :         symsize = compute_obj_symsize(Section, fptr + slide);
     602         [ -  + ]:          3 :     if (symsize == 0) {
     603                 :          0 :         jl_printf(JL_STDERR, "WARNING: Could not determine size of symbol\n");
     604                 :          0 :         return jl_pchar_to_string("", 0);
     605                 :            :     }
     606                 :            : 
     607         [ -  + ]:          3 :     if (raw_mc) {
     608                 :          0 :         return (jl_value_t*)jl_pchar_to_array((char*)fptr, symsize);
     609                 :            :     }
     610                 :            : 
     611                 :            :     // Dump assembly code
     612                 :          3 :     jl_ptls_t ptls = jl_current_task->ptls;
     613                 :          3 :     int8_t gc_state = jl_gc_safe_enter(ptls);
     614                 :          3 :     jl_dump_asm_internal(
     615                 :            :             fptr, symsize, slide,
     616                 :            :             Section, context,
     617                 :            :             stream,
     618                 :            :             asm_variant,
     619                 :            :             debuginfo,
     620                 :            :             binary);
     621                 :          3 :     jl_gc_safe_leave(ptls, gc_state);
     622                 :            : 
     623                 :          3 :     return jl_pchar_to_string(stream.str().data(), stream.str().size());
     624                 :            : }
     625                 :            : 
     626                 :            : 
     627                 :            : namespace {
     628                 :            : #define FuncMCView ArrayRef<uint8_t>
     629                 :            : 
     630                 :            : // Look up a symbol, and return a const char* to its name when the
     631                 :            : // address matches. We currently just use "L<address>" as name for the
     632                 :            : // symbol. We could easily get more fancy, e.g. numbering symbols
     633                 :            : // sequentially or encoding the line number, but that doesn't seem
     634                 :            : // necessary.
     635                 :            : class SymbolTable {
     636                 :            :     typedef std::map<uint64_t, std::string> TableType;
     637                 :            :     TableType Table;
     638                 :            :     MCContext& Ctx;
     639                 :            :     const FuncMCView &MemObj;
     640                 :            :     int Pass;
     641                 :            :     const object::ObjectFile *object;
     642                 :            :     uint64_t ip; // virtual instruction pointer of the current instruction
     643                 :            :     int64_t slide;
     644                 :            : public:
     645                 :          3 :     SymbolTable(MCContext &Ctx, const object::ObjectFile *object, int64_t slide, const FuncMCView &MemObj):
     646                 :          3 :         Ctx(Ctx), MemObj(MemObj), object(object), ip(0), slide(slide) {}
     647                 :          6 :     const FuncMCView &getMemoryObject() const { return MemObj; }
     648                 :          6 :     void setPass(int Pass) { this->Pass = Pass; }
     649                 :          6 :     int getPass() const { return Pass; }
     650                 :            :     void insertAddress(uint64_t addr);
     651                 :            :     // void createSymbol(const char *name, uint64_t addr);
     652                 :            :     void createSymbols();
     653                 :            :     const char *lookupSymbolName(uint64_t addr);
     654                 :            :     MCSymbol *lookupSymbol(uint64_t addr);
     655                 :            :     StringRef getSymbolNameAt(uint64_t offset) const;
     656                 :            :     const char *lookupLocalPC(size_t addr);
     657                 :            :     void setIP(uint64_t addr);
     658                 :            :     uint64_t getIP() const;
     659                 :            : };
     660                 :            : 
     661                 :         24 : void SymbolTable::setIP(uint64_t addr)
     662                 :            : {
     663                 :         24 :     ip = addr;
     664                 :         24 : }
     665                 :          6 : uint64_t SymbolTable::getIP() const
     666                 :            : {
     667                 :          6 :     return ip;
     668                 :            : }
     669                 :            : 
     670                 :          9 : const char *SymbolTable::lookupLocalPC(size_t addr) {
     671                 :          9 :     jl_frame_t *frame = NULL;
     672                 :          9 :     jl_getFunctionInfo(&frame,
     673                 :            :             addr,
     674                 :            :             /*skipC*/0,
     675                 :            :             /*noInline*/1/* the entry pointer shouldn't have inlining */);
     676                 :          9 :     char *name = frame->func_name; // TODO: free me
     677                 :          9 :     free(frame->file_name);
     678                 :          9 :     free(frame);
     679                 :          9 :     return name;
     680                 :            : }
     681                 :            : 
     682                 :          9 : StringRef SymbolTable::getSymbolNameAt(uint64_t offset) const
     683                 :            : {
     684         [ -  + ]:          9 :     if (object == NULL)
     685                 :          0 :         return StringRef();
     686                 :          9 :     object::section_iterator ESection = object->section_end();
     687         [ +  + ]:         90 :     for (const object::SymbolRef &Sym : object->symbols()) {
     688                 :         81 :         auto Sect = cantFail(Sym.getSection());
     689         [ +  + ]:         81 :         if (Sect == ESection)
     690                 :         54 :             continue;
     691         [ +  + ]:         63 :         if (Sect->getAddress() == 0)
     692                 :         36 :             continue;
     693                 :         27 :         uint64_t Addr = cantFail(Sym.getAddress());
     694         [ -  + ]:         27 :         if (Addr == offset) {
     695                 :          0 :             auto sNameOrError = Sym.getName();
     696         [ #  # ]:          0 :             if (sNameOrError)
     697                 :          0 :                 return sNameOrError.get();
     698                 :            :         }
     699                 :            :     }
     700                 :          9 :     return StringRef();
     701                 :            : }
     702                 :            : 
     703                 :            : // Insert an address
     704                 :          0 : void SymbolTable::insertAddress(uint64_t addr)
     705                 :            : {
     706                 :          0 :     Table[addr] = "";
     707                 :          0 : }
     708                 :            : // Create symbols for all addresses
     709                 :          3 : void SymbolTable::createSymbols()
     710                 :            : {
     711                 :          3 :     uintptr_t Fptr = (uintptr_t)MemObj.data();
     712                 :          3 :     uintptr_t Fsize = MemObj.size();
     713                 :          3 :     for (TableType::iterator isymb = Table.begin(), esymb = Table.end();
     714         [ -  + ]:          3 :          isymb != esymb; ++isymb) {
     715                 :          0 :         uintptr_t rel = isymb->first - ip;
     716                 :          0 :         uintptr_t addr = isymb->first;
     717   [ #  #  #  # ]:          0 :         if (Fptr <= addr && addr < Fptr + Fsize) {
     718                 :          0 :             std::string name;
     719                 :          0 :             raw_string_ostream(name) << "L" << rel;
     720                 :          0 :             isymb->second = name;
     721                 :            :         }
     722                 :            :         else {
     723                 :          0 :             const char *global = lookupLocalPC(addr);
     724   [ #  #  #  # ]:          0 :             if (global && global[0])
     725                 :          0 :                 isymb->second = global;
     726                 :            :             // TODO: free(global)?
     727                 :            :         }
     728                 :            :     }
     729                 :          3 : }
     730                 :            : 
     731                 :         15 : const char *SymbolTable::lookupSymbolName(uint64_t addr)
     732                 :            : {
     733                 :         15 :     TableType::iterator Sym;
     734                 :            :     bool insertion;
     735                 :         15 :     std::tie(Sym, insertion) = Table.insert(std::make_pair(addr, std::string()));
     736         [ +  + ]:         15 :     if (insertion) {
     737                 :            :         // First time we've seen addr: try to look it up
     738                 :          9 :         StringRef local_name = getSymbolNameAt(addr + slide);
     739         [ +  - ]:          9 :         if (local_name.empty()) {
     740                 :          9 :             const char *global = lookupLocalPC(addr);
     741         [ -  + ]:          9 :             if (global) {
     742                 :            :                 //std::string name;
     743                 :            :                 //raw_string_ostream(name) << global << "@0x" << std::hex
     744                 :            :                 //     << std::setfill('0') << std::setw(2 * sizeof(void*))
     745                 :            :                 //     << addr;
     746                 :            :                 //Sym->second = name.str();
     747                 :          0 :                 Sym->second = global;
     748                 :            :             }
     749                 :            :         }
     750                 :            :         else {
     751                 :          0 :             Sym->second = local_name.str();
     752                 :            :         }
     753                 :            :     }
     754         [ +  - ]:         15 :     return Sym->second.empty() ? NULL : Sym->second.c_str();
     755                 :            : }
     756                 :            : 
     757                 :          9 : MCSymbol *SymbolTable::lookupSymbol(uint64_t addr)
     758                 :            : {
     759                 :          9 :     TableType::iterator Sym = Table.find(addr);
     760   [ -  +  -  -  :          9 :     if (Sym == Table.end() || Sym->second.empty())
                   +  - ]
     761                 :          9 :         return NULL;
     762                 :          0 :     MCSymbol *symb = Ctx.getOrCreateSymbol(Sym->second);
     763         [ #  # ]:          0 :     assert(symb->isUndefined());
     764                 :          0 :     return symb;
     765                 :            : }
     766                 :            : 
     767                 :          6 : static const char *SymbolLookup(void *DisInfo, uint64_t ReferenceValue, uint64_t *ReferenceType,
     768                 :            :                                 uint64_t ReferencePC, const char **ReferenceName)
     769                 :            : {
     770                 :          6 :     uint64_t RTypeIn = *ReferenceType;
     771                 :          6 :     SymbolTable *SymTab = (SymbolTable*)DisInfo;
     772                 :          6 :     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
     773                 :          6 :     *ReferenceName = NULL;
     774         [ +  - ]:          6 :     if (SymTab->getPass() != 0) {
     775         [ -  + ]:          6 :         if (RTypeIn == LLVMDisassembler_ReferenceType_In_Branch) {
     776                 :          0 :             uint64_t addr = ReferenceValue + SymTab->getIP(); // probably pc-rel
     777                 :          0 :             const char *symbolName = SymTab->lookupSymbolName(addr);
     778                 :          0 :             return symbolName;
     779                 :            :         }
     780         [ -  + ]:          6 :         else if (RTypeIn == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
     781                 :          0 :             uint64_t addr = ReferenceValue + SymTab->getIP();
     782                 :          0 :             const char *symbolName = SymTab->lookupSymbolName(addr);
     783         [ #  # ]:          0 :             if (symbolName) {
     784                 :          0 :                 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
     785                 :          0 :                 *ReferenceName = symbolName;
     786                 :            :             }
     787                 :            :         }
     788         [ +  - ]:          6 :         else if (RTypeIn == LLVMDisassembler_ReferenceType_InOut_None) {
     789                 :          6 :             uint64_t addr = ReferenceValue; // probably not pc-rel
     790                 :          6 :             const char *symbolName = SymTab->lookupSymbolName(addr);
     791                 :          6 :             return symbolName;
     792                 :            :         }
     793                 :            :     }
     794                 :          0 :     return NULL;
     795                 :            : }
     796                 :            : 
     797                 :          6 : static int OpInfoLookup(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Size,
     798                 :            :                         int TagType, void *TagBuf)
     799                 :            : {
     800                 :          6 :     SymbolTable *SymTab = (SymbolTable*)DisInfo;
     801                 :          6 :     LLVMOpInfo1 *info = (LLVMOpInfo1*)TagBuf;
     802                 :          6 :     memset(info, 0, sizeof(*info));
     803         [ -  + ]:          6 :     if (TagType != 1)
     804                 :          0 :         return 0;               // Unknown data format
     805                 :          6 :     PC += SymTab->getIP() - (uint64_t)(uintptr_t)SymTab->getMemoryObject().data(); // add offset from MemoryObject base
     806                 :            :     // TODO: see if we knew of a relocation applied at PC
     807                 :            :     // info->AddSymbol.Present = 1;
     808                 :            :     // info->AddSymbol.Name = name;
     809                 :            :     // info->AddSymbol.Value = pointer; // unused by LLVM
     810                 :            :     // info->Value = 0;                 // offset
     811                 :            :     // return 1;                        // Success
     812                 :          6 :     return 0;
     813                 :            : }
     814                 :            : } // namespace
     815                 :            : 
     816                 :            : // Stringify raw bytes as a comment string.
     817                 :          3 : std::string rawCodeComment(const llvm::ArrayRef<uint8_t>& Memory, const llvm::Triple& Triple)
     818                 :            : {
     819                 :          6 :     std::string Buffer{"; "};
     820                 :          6 :     llvm::raw_string_ostream Stream{Buffer};
     821                 :          3 :     auto Address = reinterpret_cast<uintptr_t>(Memory.data());
     822                 :            :     // write abbreviated address
     823                 :          3 :     llvm::write_hex(Stream, Address & 0xffff, HexPrintStyle::Lower, 4);
     824                 :          3 :     Stream << ":";
     825                 :          3 :     auto Arch = Triple.getArch();
     826   [ +  -  -  + ]:          3 :     bool FixedLength = !(Arch == Triple::x86 || Arch == Triple::x86_64);
     827         [ -  + ]:          3 :     if (FixedLength)
     828                 :          0 :         Stream << " ";
     829   [ -  +  -  -  :          3 :     if (FixedLength && Triple.isLittleEndian()) {
                   -  + ]
     830         [ #  # ]:          0 :         for (auto Iter = Memory.rbegin(); Iter != Memory.rend(); ++Iter)
     831                 :          0 :             llvm::write_hex(Stream, *Iter, HexPrintStyle::Lower, 2);
     832                 :            :     }
     833                 :            :     else {
     834                 :            :         // variable-length or (fixed-length) big-endian format
     835         [ +  + ]:         19 :         for (auto Byte : Memory) {
     836         [ +  - ]:         16 :             if (!FixedLength)
     837                 :         16 :                 Stream << " ";
     838                 :         16 :             llvm::write_hex(Stream, Byte, HexPrintStyle::Lower, 2);
     839                 :            :         }
     840                 :            :     }
     841                 :          3 :     return Stream.str();
     842                 :            : }
     843                 :            : 
     844                 :          3 : static void jl_dump_asm_internal(
     845                 :            :         uintptr_t Fptr, size_t Fsize, int64_t slide,
     846                 :            :         object::SectionRef Section,
     847                 :            :         DIContext *di_ctx,
     848                 :            :         raw_ostream &rstream,
     849                 :            :         const char* asm_variant,
     850                 :            :         const char* debuginfo,
     851                 :            :         bool binary)
     852                 :            : {
     853                 :            :     // GC safe
     854                 :            :     // Get the host information
     855                 :          3 :     Triple TheTriple(sys::getProcessTriple());
     856                 :            : 
     857                 :          3 :     const auto &target = jl_get_llvm_disasm_target();
     858                 :          3 :     const auto &cpu = target.first;
     859                 :          3 :     const auto &features = target.second;
     860                 :            : 
     861                 :          3 :     std::string err;
     862                 :          3 :     const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple.str(), err);
     863                 :            : 
     864                 :            :     // Set up required helpers and streamer
     865                 :          3 :     SourceMgr SrcMgr;
     866                 :            : 
     867                 :          3 :     MCTargetOptions Options;
     868                 :            :     std::unique_ptr<MCAsmInfo> MAI(
     869                 :          3 :         TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TheTriple.str()), TheTriple.str(), Options));
     870         [ +  - ]:          3 :     assert(MAI && "Unable to create target asm info!");
     871                 :            : 
     872                 :          3 :     std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TheTriple.str()));
     873         [ +  - ]:          3 :     assert(MRI && "Unable to create target register info!");
     874                 :            : 
     875                 :            :     std::unique_ptr<llvm::MCSubtargetInfo> STI(
     876                 :          3 :       TheTarget->createMCSubtargetInfo(TheTriple.str(), cpu, features));
     877         [ +  - ]:          3 :     assert(STI && "Unable to create subtarget info!");
     878                 :            : 
     879                 :            : #if JL_LLVM_VERSION >= 130000
     880                 :          3 :     MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
     881                 :            :     std::unique_ptr<MCObjectFileInfo> MOFI(
     882                 :          3 :       TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false, /*LargeCodeModel=*/ false));
     883                 :          3 :     Ctx.setObjectFileInfo(MOFI.get());
     884                 :            : #else
     885                 :            :     std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
     886                 :            :     MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
     887                 :            :     MOFI->InitMCObjectFileInfo(TheTriple, /* PIC */ false, Ctx);
     888                 :            : #endif
     889                 :            : 
     890                 :          3 :     std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx));
     891         [ -  + ]:          3 :     if (!DisAsm) {
     892                 :          0 :         rstream << "ERROR: no disassembler for target " << TheTriple.str();
     893                 :          0 :         return;
     894                 :            :     }
     895                 :          3 :     unsigned OutputAsmVariant = 0; // ATT or Intel-style assembly
     896                 :            : 
     897         [ -  + ]:          3 :     if (strcmp(asm_variant, "intel") == 0) {
     898                 :          0 :         OutputAsmVariant = 1;
     899                 :            :     }
     900                 :          3 :     bool ShowEncoding = false;
     901                 :            : 
     902                 :            :     std::unique_ptr<MCInstrInfo> MCII(
     903                 :          6 :             TheTarget->createMCInstrInfo());
     904                 :            :     std::unique_ptr<MCInstrAnalysis> MCIA(
     905                 :          6 :             TheTarget->createMCInstrAnalysis(MCII.get()));
     906                 :            :     std::unique_ptr<MCInstPrinter> IP(
     907                 :          6 :             TheTarget->createMCInstPrinter(TheTriple, OutputAsmVariant, *MAI, *MCII, *MRI));
     908                 :            :     //IP->setPrintImmHex(true); // prefer hex or decimal immediates
     909                 :          3 :     std::unique_ptr<MCCodeEmitter> CE;
     910                 :          3 :     std::unique_ptr<MCAsmBackend> MAB;
     911         [ -  + ]:          3 :     if (ShowEncoding) {
     912                 :            : #if JL_LLVM_VERSION >= 150000
     913                 :            :         CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
     914                 :            : #else
     915                 :          0 :         CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
     916                 :            : #endif
     917                 :          0 :         MAB.reset(TheTarget->createMCAsmBackend(*STI, *MRI, Options));
     918                 :            :     }
     919                 :            : 
     920                 :            :     // createAsmStreamer expects a unique_ptr to a formatted stream, which means
     921                 :            :     // it will destruct the stream when it is done. We cannot have this, so we
     922                 :            :     // start out with a raw stream, and create formatted stream from it here.
     923                 :            :     // LLVM will destroy the formatted stream, and we keep the raw stream.
     924                 :          6 :     std::unique_ptr<formatted_raw_ostream> ustream(new formatted_raw_ostream(rstream));
     925                 :            :     std::unique_ptr<MCStreamer> Streamer(
     926                 :          3 :             TheTarget->createAsmStreamer(Ctx, std::move(ustream), /*asmverbose*/true,
     927                 :            :                                          /*useDwarfDirectory*/ true,
     928                 :            :                                          IP.release(),
     929                 :          3 :                                          std::move(CE), std::move(MAB),
     930                 :          9 :                                          /*ShowInst*/ false));
     931                 :            : #if JL_LLVM_VERSION >= 140000
     932                 :          3 :     Streamer->initSections(true, *STI);
     933                 :            : #else
     934                 :            :     Streamer->InitSections(true);
     935                 :            : #endif
     936                 :            : 
     937                 :            :     // Make the MemoryObject wrapper
     938                 :          3 :     ArrayRef<uint8_t> memoryObject(const_cast<uint8_t*>((const uint8_t*)Fptr),Fsize);
     939                 :          6 :     SymbolTable DisInfo(Ctx, Section.getObject(), slide, memoryObject);
     940                 :            : 
     941                 :          6 :     DILineInfoTable di_lineinfo;
     942         [ +  - ]:          3 :     if (di_ctx)
     943                 :          3 :         di_lineinfo = di_ctx->getLineInfoForAddressRange(makeAddress(Section, Fptr + slide), Fsize);
     944         [ +  - ]:          3 :     if (!di_lineinfo.empty()) {
     945                 :          3 :         auto cur_addr = di_lineinfo[0].first;
     946                 :          3 :         auto nlineinfo = di_lineinfo.size();
     947                 :            :         // filter out line infos that doesn't contain any instructions
     948                 :          3 :         unsigned j = 0;
     949         [ +  + ]:          6 :         for (unsigned i = 1; i < nlineinfo; i++) {
     950                 :          3 :             auto &info = di_lineinfo[i];
     951         [ +  - ]:          3 :             if (info.first != cur_addr)
     952                 :          3 :                 j++;
     953                 :          3 :             cur_addr = info.first;
     954         [ -  + ]:          3 :             if (i != j) {
     955                 :          0 :                 di_lineinfo[j] = std::move(info);
     956                 :            :             }
     957                 :            :         }
     958         [ -  + ]:          3 :         if (j + 1 < nlineinfo) {
     959                 :          0 :             di_lineinfo.resize(j + 1);
     960                 :            :         }
     961                 :            :     }
     962                 :            : 
     963         [ +  + ]:          3 :     if (binary) {
     964                 :            :         // Print the complete address and the size at the top (instruction addresses are abbreviated)
     965                 :          2 :         std::string Buffer{"; code origin: "};
     966                 :          1 :         llvm::raw_string_ostream Stream{Buffer};
     967                 :          1 :         auto Address = reinterpret_cast<uintptr_t>(memoryObject.data());
     968                 :          1 :         llvm::write_hex(Stream, Address, HexPrintStyle::Lower, 16);
     969                 :          1 :         Stream << ", code size: " << memoryObject.size();
     970                 :          1 :         Streamer->emitRawText(Stream.str());
     971                 :            :     }
     972                 :            : 
     973                 :            :     // Take two passes: In the first pass we record all branch labels,
     974                 :            :     // in the second we actually perform the output
     975         [ +  + ]:          9 :     for (int pass = 0; pass < 2; ++ pass) {
     976                 :          6 :         DisInfo.setPass(pass);
     977         [ +  + ]:          6 :         if (pass != 0) {
     978                 :            :             // Switch to symbolic disassembly. We cannot do this
     979                 :            :             // before the first pass, because this changes branch
     980                 :            :             // targets from immediate values (constants) to
     981                 :            :             // expressions, which are not handled correctly by
     982                 :            :             // MCIA->evaluateBranch. (It should be possible to rewrite
     983                 :            :             // this routine to handle this case correctly as well.)
     984                 :            :             // Could add OpInfoLookup here
     985                 :          6 :             DisAsm->setSymbolizer(std::unique_ptr<MCSymbolizer>(new MCExternalSymbolizer(
     986                 :            :                         Ctx,
     987                 :          6 :                         std::unique_ptr<MCRelocationInfo>(new MCRelocationInfo(Ctx)),
     988                 :            :                         OpInfoLookup,
     989                 :            :                         SymbolLookup,
     990                 :          3 :                         &DisInfo)));
     991                 :            :         }
     992                 :            : 
     993                 :          6 :         uint64_t nextLineAddr = -1;
     994                 :          6 :         DILineInfoTable::iterator di_lineIter = di_lineinfo.begin();
     995                 :          6 :         DILineInfoTable::iterator di_lineEnd = di_lineinfo.end();
     996                 :         12 :         DILineInfoPrinter dbgctx{"; ", true};
     997                 :          6 :         dbgctx.SetVerbosity(debuginfo);
     998         [ +  + ]:          6 :         if (pass != 0) {
     999   [ +  -  +  - ]:          3 :             if (di_ctx && di_lineIter != di_lineEnd) {
    1000                 :            :                 // Set up the line info
    1001                 :          3 :                 nextLineAddr = di_lineIter->first;
    1002         [ -  + ]:          3 :                 if (nextLineAddr != (uint64_t)(Fptr + slide)) {
    1003                 :          0 :                     std::string buf;
    1004                 :          0 :                     dbgctx.emit_lineinfo(buf, di_lineIter->second);
    1005         [ #  # ]:          0 :                     if (!buf.empty()) {
    1006                 :          0 :                         Streamer->emitRawText(buf);
    1007                 :            :                     }
    1008                 :            :                 }
    1009                 :            :             }
    1010                 :            :         }
    1011                 :            : 
    1012                 :          6 :         uint64_t Index = 0;
    1013                 :          6 :         uint64_t insSize = 0;
    1014                 :            : 
    1015                 :            :         // Do the disassembly
    1016         [ +  + ]:         24 :         for (Index = 0; Index < Fsize; Index += insSize) {
    1017                 :            : 
    1018   [ +  +  +  -  :         18 :             if (pass != 0 && nextLineAddr != (uint64_t)-1 && Index + Fptr + slide == nextLineAddr) {
                   +  + ]
    1019         [ +  - ]:          6 :                 if (di_ctx) {
    1020                 :         12 :                     std::string buf;
    1021                 :            :                     DILineInfoSpecifier infoSpec(
    1022                 :            :                         DILineInfoSpecifier::FileLineInfoKind::RawValue,
    1023                 :          6 :                         DILineInfoSpecifier::FunctionNameKind::ShortName);
    1024                 :          6 :                     DIInliningInfo dbg = di_ctx->getInliningInfoForAddress(makeAddress(Section, Index + Fptr + slide), infoSpec);
    1025         [ +  + ]:          6 :                     if (dbg.getNumberOfFrames()) {
    1026                 :          3 :                         dbgctx.emit_lineinfo(buf, dbg);
    1027                 :            :                     }
    1028                 :            :                     else {
    1029                 :          3 :                         dbgctx.emit_lineinfo(buf, di_lineIter->second);
    1030                 :            :                     }
    1031         [ +  - ]:          6 :                     if (!buf.empty()) {
    1032                 :          6 :                         Streamer->emitRawText(buf);
    1033                 :            :                     }
    1034                 :          6 :                     nextLineAddr = (++di_lineIter)->first;
    1035                 :            :                 }
    1036                 :            :             }
    1037                 :            : 
    1038                 :         18 :             DisInfo.setIP(Fptr+Index);
    1039         [ +  + ]:         18 :             if (pass != 0) {
    1040                 :            :                 // Uncomment this to output addresses for all instructions
    1041                 :            :                 // stream << Index << ": ";
    1042                 :          9 :                 MCSymbol *symbol = DisInfo.lookupSymbol(Fptr+Index);
    1043         [ -  + ]:          9 :                 if (symbol) {
    1044                 :          0 :                     Streamer->emitLabel(symbol);
    1045                 :            :                 }
    1046                 :            :             }
    1047                 :            : 
    1048                 :         36 :             MCInst Inst;
    1049                 :            :             MCDisassembler::DecodeStatus S;
    1050                 :         18 :             FuncMCView view = memoryObject.slice(Index);
    1051                 :         36 :             S = DisAsm->getInstruction(Inst, insSize, view, 0,
    1052         [ +  + ]:         18 :                                       /*CStream*/ pass != 0 ? Streamer->GetCommentOS() : nulls());
    1053   [ +  +  -  +  :         18 :             if (pass != 0 && Streamer->GetCommentOS().tell() > 0)
                   -  + ]
    1054                 :          0 :                 Streamer->GetCommentOS() << '\n';
    1055   [ -  -  +  - ]:         18 :             switch (S) {
    1056                 :          0 :             case MCDisassembler::Fail:
    1057         [ #  # ]:          0 :                 if (insSize == 0) // skip illegible bytes
    1058                 :            : #if defined(_CPU_PPC_) || defined(_CPU_PPC64_) || defined(_CPU_ARM_) || defined(_CPU_AARCH64_)
    1059                 :            :                     insSize = 4; // instructions are always 4 bytes
    1060                 :            : #else
    1061                 :          0 :                     insSize = 1; // attempt to slide 1 byte forward
    1062                 :            : #endif
    1063         [ #  # ]:          0 :                 if (pass != 0) {
    1064                 :          0 :                     std::string _buf;
    1065                 :          0 :                     raw_string_ostream buf(_buf);
    1066         [ #  # ]:          0 :                     if (insSize == 4) {
    1067                 :          0 :                         buf << "\t.long\t";
    1068                 :          0 :                         llvm::write_hex(buf, *(uint32_t*)(Fptr + Index), HexPrintStyle::PrefixLower, 8);
    1069                 :            :                     }
    1070                 :            :                     else {
    1071         [ #  # ]:          0 :                         for (uint64_t i = 0; i < insSize; ++i) {
    1072                 :          0 :                             buf << "\t.byte\t";
    1073                 :          0 :                             llvm::write_hex(buf, *(uint8_t*)(Fptr + Index + i), HexPrintStyle::PrefixLower, 2);
    1074                 :            :                         }
    1075                 :            :                     }
    1076                 :          0 :                     Streamer->emitRawText(StringRef(buf.str()));
    1077                 :            :                 }
    1078                 :          0 :                 break;
    1079                 :            : 
    1080                 :          0 :             case MCDisassembler::SoftFail:
    1081         [ #  # ]:          0 :                 if (pass != 0) {
    1082                 :          0 :                     Streamer->emitRawText(StringRef("potentially undefined instruction encoding:"));
    1083                 :            :                 }
    1084                 :            :                 // Fall through
    1085                 :            : 
    1086                 :            :             case MCDisassembler::Success:
    1087         [ +  + ]:         18 :                 if (pass == 0) {
    1088                 :            :                     // Pass 0: Record all branch target references
    1089         [ +  - ]:          9 :                     if (MCIA) {
    1090                 :          9 :                         const MCInstrDesc &opcode = MCII->get(Inst.getOpcode());
    1091   [ +  -  -  +  :          9 :                         if (opcode.isBranch() || opcode.isCall()) {
                   -  + ]
    1092                 :            :                             uint64_t addr;
    1093         [ #  # ]:          0 :                             if (MCIA->evaluateBranch(Inst, Fptr + Index, insSize, addr))
    1094                 :          0 :                                 DisInfo.insertAddress(addr);
    1095                 :            :                         }
    1096                 :            :                     }
    1097                 :            :                 }
    1098                 :            :                 else {
    1099                 :            :                     // Pass 1: Output instruction
    1100         [ +  - ]:          9 :                     if (pass != 0) {
    1101                 :            :                         // attempt to symbolicate any immediate operands
    1102                 :          9 :                         const MCInstrDesc &opinfo = MCII->get(Inst.getOpcode());
    1103         [ +  + ]:         30 :                         for (unsigned Op = 0; Op < opinfo.NumOperands; Op++) {
    1104                 :         21 :                             const MCOperand &OpI = Inst.getOperand(Op);
    1105         [ +  + ]:         21 :                             if (OpI.isImm()) {
    1106                 :          9 :                                 int64_t imm = OpI.getImm();
    1107         [ -  + ]:          9 :                                 if (opinfo.OpInfo[Op].OperandType == MCOI::OPERAND_PCREL)
    1108                 :          0 :                                     imm += Fptr + Index;
    1109                 :          9 :                                 const char *name = DisInfo.lookupSymbolName(imm);
    1110         [ -  + ]:          9 :                                 if (name)
    1111                 :          0 :                                     Streamer->AddComment(name);
    1112                 :            :                             }
    1113                 :            :                         }
    1114                 :            :                     }
    1115         [ +  + ]:          9 :                     if (binary)
    1116                 :          3 :                         Streamer->emitRawText(rawCodeComment(memoryObject.slice(Index, insSize), TheTriple));
    1117                 :          9 :                     Streamer->emitInstruction(Inst, *STI);
    1118                 :            :                 }
    1119                 :         18 :                 break;
    1120                 :            :             }
    1121                 :            :         }
    1122                 :            : 
    1123                 :          6 :         DisInfo.setIP(Fptr);
    1124         [ +  + ]:          6 :         if (pass == 0)
    1125                 :          3 :             DisInfo.createSymbols();
    1126                 :            : 
    1127   [ +  +  +  - ]:          6 :         if (pass != 0 && di_ctx) {
    1128                 :          6 :             std::string buf;
    1129                 :          3 :             dbgctx.emit_finish(buf);
    1130         [ +  - ]:          3 :             if (!buf.empty()) {
    1131                 :          3 :                 Streamer->emitRawText(buf);
    1132                 :            :             }
    1133                 :            :         }
    1134                 :            :     }
    1135                 :            : }
    1136                 :            : 
    1137                 :            : /// addPassesToX helper drives creation and initialization of TargetPassConfig.
    1138                 :            : static MCContext *
    1139                 :         24 : addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM) {
    1140                 :         24 :     TargetPassConfig *PassConfig = TM->createPassConfig(PM);
    1141                 :         24 :     PassConfig->setDisableVerify(false);
    1142                 :         24 :     PM.add(PassConfig);
    1143                 :            :     MachineModuleInfoWrapperPass *MMIWP =
    1144                 :         24 :         new MachineModuleInfoWrapperPass(TM);
    1145                 :         24 :     PM.add(MMIWP);
    1146         [ -  + ]:         24 :     if (PassConfig->addISelPasses())
    1147                 :          0 :         return NULL;
    1148                 :         24 :     PassConfig->addMachinePasses();
    1149                 :         24 :     PassConfig->setInitialized();
    1150                 :         24 :     return &MMIWP->getMMI().getContext();
    1151                 :            : }
    1152                 :            : 
    1153                 :            : class LineNumberPrinterHandler : public AsmPrinterHandler {
    1154                 :            :     MCStreamer &S;
    1155                 :            :     LineNumberAnnotatedWriter LinePrinter;
    1156                 :            :     std::string Buffer;
    1157                 :            :     llvm::raw_string_ostream RawStream;
    1158                 :            :     llvm::formatted_raw_ostream Stream;
    1159                 :            : 
    1160                 :            : public:
    1161                 :         24 :     LineNumberPrinterHandler(AsmPrinter &Printer, const char *debuginfo)
    1162                 :         48 :         : S(*Printer.OutStreamer),
    1163                 :            :           LinePrinter("; ", true, debuginfo),
    1164                 :         24 :           RawStream(Buffer),
    1165                 :         24 :           Stream(RawStream) {}
    1166                 :            : 
    1167                 :        603 :     void emitAndReset() {
    1168                 :        603 :         Stream.flush();
    1169                 :        603 :         RawStream.flush();
    1170         [ +  + ]:        603 :         if (Buffer.empty())
    1171                 :        518 :             return;
    1172                 :         85 :         S.emitRawText(Buffer);
    1173                 :         85 :         Buffer.clear();
    1174                 :            :     }
    1175                 :            : 
    1176                 :          0 :     virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
    1177                 :            :     //virtual void beginModule(Module *M) override {}
    1178                 :         24 :     virtual void endModule() override {}
    1179                 :            :     /// note that some AsmPrinter implementations may not call beginFunction at all
    1180                 :         24 :     virtual void beginFunction(const MachineFunction *MF) override {
    1181                 :         24 :         LinePrinter.emitFunctionAnnot(&MF->getFunction(), Stream);
    1182                 :         24 :         emitAndReset();
    1183                 :         24 :     }
    1184                 :            :     //virtual void markFunctionEnd() override {}
    1185                 :         24 :     virtual void endFunction(const MachineFunction *MF) override {
    1186                 :         24 :         LinePrinter.emitEnd(Stream);
    1187                 :         24 :         emitAndReset();
    1188                 :         24 :     }
    1189                 :            :     //virtual void beginFragment(const MachineBasicBlock *MBB,
    1190                 :            :     //                           ExceptionSymbolProvider ESP) override {}
    1191                 :            :     //virtual void endFragment() override {}
    1192                 :            :     //virtual void beginFunclet(const MachineBasicBlock &MBB,
    1193                 :            :     //                          MCSymbol *Sym = nullptr) override {}
    1194                 :            :     //virtual void endFunclet() override {}
    1195                 :        555 :     virtual void beginInstruction(const MachineInstr *MI) override {
    1196                 :        555 :         LinePrinter.emitInstructionAnnot(MI->getDebugLoc(), Stream);
    1197                 :        555 :         emitAndReset();
    1198                 :        555 :     }
    1199                 :        555 :     virtual void endInstruction() override {}
    1200                 :            : };
    1201                 :            : 
    1202                 :            : // get a native assembly for llvm::Function
    1203                 :            : extern "C" JL_DLLEXPORT
    1204                 :         24 : jl_value_t *jl_dump_function_asm_impl(jl_llvmf_dump_t* dump, char raw_mc, const char* asm_variant, const char *debuginfo, char binary)
    1205                 :            : {
    1206                 :            :     // precise printing via IR assembler
    1207                 :         48 :     SmallVector<char, 4096> ObjBufferSV;
    1208                 :            :     { // scope block
    1209                 :         24 :         auto TSM = std::unique_ptr<orc::ThreadSafeModule>(unwrap(dump->TSM));
    1210                 :         24 :         llvm::raw_svector_ostream asmfile(ObjBufferSV);
    1211                 :         24 :         TSM->withModuleDo([&](Module &m) {
    1212                 :         24 :             Function *f = cast<Function>(unwrap(dump->F));
    1213         [ -  + ]:         24 :             assert(!f->isDeclaration());
    1214         [ +  + ]:        281 :             for (auto &f2 : m.functions()) {
    1215   [ +  +  +  -  :        257 :                 if (f != &f2 && !f->isDeclaration())
                   +  + ]
    1216                 :        233 :                     f2.deleteBody();
    1217                 :            :             }
    1218                 :         24 :         });
    1219                 :         24 :         auto TMBase = jl_ExecutionEngine->cloneTargetMachine();
    1220                 :         24 :         LLVMTargetMachine *TM = static_cast<LLVMTargetMachine*>(TMBase.get());
    1221                 :         24 :         legacy::PassManager PM;
    1222                 :         24 :         addTargetPasses(&PM, TM->getTargetTriple(), TM->getTargetIRAnalysis());
    1223         [ -  + ]:         24 :         if (raw_mc) {
    1224                 :          0 :             raw_svector_ostream obj_OS(ObjBufferSV);
    1225         [ #  # ]:          0 :             if (TM->addPassesToEmitFile(PM, obj_OS, nullptr, CGFT_ObjectFile, false, nullptr))
    1226                 :          0 :                 return jl_an_empty_string;
    1227                 :          0 :             TSM->withModuleDo([&](Module &m) { PM.run(m); });
    1228                 :            :         }
    1229                 :            :         else {
    1230                 :         24 :             MCContext *Context = addPassesToGenerateCode(TM, PM);
    1231         [ -  + ]:         24 :             if (!Context)
    1232                 :          0 :                 return jl_an_empty_string;
    1233                 :         24 :             Context->setGenDwarfForAssembly(false);
    1234                 :            :             // Duplicate LLVMTargetMachine::addAsmPrinter here so we can set the asm dialect and add the custom annotation printer
    1235                 :         24 :             const MCSubtargetInfo &STI = *TM->getMCSubtargetInfo();
    1236                 :         24 :             const MCAsmInfo &MAI = *TM->getMCAsmInfo();
    1237                 :         24 :             const MCRegisterInfo &MRI = *TM->getMCRegisterInfo();
    1238                 :         24 :             const MCInstrInfo &MII = *TM->getMCInstrInfo();
    1239                 :         24 :             unsigned OutputAsmDialect = MAI.getAssemblerDialect();
    1240         [ +  + ]:         24 :             if (!strcmp(asm_variant, "att"))
    1241                 :         23 :                 OutputAsmDialect = 0;
    1242         [ +  + ]:         24 :             if (!strcmp(asm_variant, "intel"))
    1243                 :          1 :                 OutputAsmDialect = 1;
    1244                 :         24 :             MCInstPrinter *InstPrinter = TM->getTarget().createMCInstPrinter(
    1245                 :            :                 jl_ExecutionEngine->getTargetTriple(), OutputAsmDialect, MAI, MII, MRI);
    1246                 :         24 :              std::unique_ptr<MCAsmBackend> MAB(TM->getTarget().createMCAsmBackend(
    1247                 :         24 :                 STI, MRI, TM->Options.MCOptions));
    1248                 :         24 :             std::unique_ptr<MCCodeEmitter> MCE;
    1249         [ -  + ]:         24 :             if (binary) { // enable MCAsmStreamer::AddEncodingComment printing
    1250                 :            : #if JL_LLVM_VERSION >= 150000
    1251                 :            :                 MCE.reset(TM->getTarget().createMCCodeEmitter(MII, *Context));
    1252                 :            : #else
    1253                 :          0 :                 MCE.reset(TM->getTarget().createMCCodeEmitter(MII, MRI, *Context));
    1254                 :            : #endif
    1255                 :            :             }
    1256                 :         24 :             auto FOut = std::make_unique<formatted_raw_ostream>(asmfile);
    1257                 :         24 :             std::unique_ptr<MCStreamer> S(TM->getTarget().createAsmStreamer(
    1258                 :         24 :                 *Context, std::move(FOut), true,
    1259                 :            :                 true, InstPrinter,
    1260                 :         24 :                 std::move(MCE), std::move(MAB),
    1261                 :         24 :                 false));
    1262                 :            :             std::unique_ptr<AsmPrinter> Printer(
    1263                 :         24 :                 TM->getTarget().createAsmPrinter(*TM, std::move(S)));
    1264                 :         48 :             Printer->addAsmPrinterHandler(AsmPrinter::HandlerInfo(
    1265                 :         48 :                         std::unique_ptr<AsmPrinterHandler>(new LineNumberPrinterHandler(*Printer, debuginfo)),
    1266                 :            :                         "emit", "Debug Info Emission", "Julia", "Julia::LineNumberPrinterHandler Markup"));
    1267         [ -  + ]:         24 :             if (!Printer)
    1268                 :          0 :                 return jl_an_empty_string;
    1269                 :         24 :             PM.add(Printer.release());
    1270                 :         24 :             PM.add(createFreeMachineFunctionPass());
    1271                 :         48 :             TSM->withModuleDo([&](Module &m){ PM.run(m); });
    1272                 :            :         }
    1273                 :            :     }
    1274                 :         24 :     return jl_pchar_to_string(ObjBufferSV.data(), ObjBufferSV.size());
    1275                 :            : }
    1276                 :            : 
    1277                 :            : extern "C" JL_DLLEXPORT
    1278                 :          0 : LLVMDisasmContextRef jl_LLVMCreateDisasm_impl(
    1279                 :            :         const char *TripleName, void *DisInfo, int TagType,
    1280                 :            :         LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp)
    1281                 :            : {
    1282                 :          0 :     return LLVMCreateDisasm(TripleName, DisInfo, TagType, GetOpInfo, SymbolLookUp);
    1283                 :            : }
    1284                 :            : 
    1285                 :            : extern "C" JL_DLLEXPORT
    1286                 :          0 : JL_DLLEXPORT size_t jl_LLVMDisasmInstruction_impl(
    1287                 :            :         LLVMDisasmContextRef DC, uint8_t *Bytes, uint64_t BytesSize,
    1288                 :            :         uint64_t PC, char *OutString, size_t OutStringSize)
    1289                 :            : {
    1290                 :          0 :     return LLVMDisasmInstruction(DC, Bytes, BytesSize, PC, OutString, OutStringSize);
    1291                 :            : }

Generated by: LCOV version 1.14