LCOV - code coverage report
Current view: top level - lib/CodeGen/AsmPrinter - ErlangGCPrinter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 26 30 86.7 %
Date: 2018-10-20 13:21:21 Functions: 1 2 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter ----------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file implements the compiler plugin that is used in order to emit
      11             : // garbage collection information in a convenient layout for parsing and
      12             : // loading in the Erlang/OTP runtime.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #include "llvm/BinaryFormat/ELF.h"
      17             : #include "llvm/CodeGen/AsmPrinter.h"
      18             : #include "llvm/CodeGen/GCMetadata.h"
      19             : #include "llvm/CodeGen/GCMetadataPrinter.h"
      20             : #include "llvm/CodeGen/GCStrategy.h"
      21             : #include "llvm/CodeGen/GCs.h"
      22             : #include "llvm/IR/DataLayout.h"
      23             : #include "llvm/IR/Function.h"
      24             : #include "llvm/IR/Module.h"
      25             : #include "llvm/MC/MCContext.h"
      26             : #include "llvm/MC/MCSectionELF.h"
      27             : #include "llvm/MC/MCStreamer.h"
      28             : #include "llvm/MC/MCSymbol.h"
      29             : #include "llvm/Target/TargetLoweringObjectFile.h"
      30             : 
      31             : using namespace llvm;
      32             : 
      33             : namespace {
      34             : 
      35           3 : class ErlangGCPrinter : public GCMetadataPrinter {
      36             : public:
      37             :   void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override;
      38             : };
      39             : 
      40             : } // end anonymous namespace
      41             : 
      42             : static GCMetadataPrinterRegistry::Add<ErlangGCPrinter>
      43             :     X("erlang", "erlang-compatible garbage collector");
      44             : 
      45           3 : void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
      46             :                                      AsmPrinter &AP) {
      47             :   MCStreamer &OS = *AP.OutStreamer;
      48           3 :   unsigned IntPtrSize = M.getDataLayout().getPointerSize();
      49             : 
      50             :   // Put this in a custom .note section.
      51           3 :   OS.SwitchSection(
      52           6 :       AP.getObjFileLowering().getContext().getELFSection(".note.gc",
      53           3 :                                                          ELF::SHT_PROGBITS, 0));
      54             : 
      55             :   // For each function...
      56             :   for (GCModuleInfo::FuncInfoVec::iterator FI = Info.funcinfo_begin(),
      57             :                                            IE = Info.funcinfo_end();
      58           6 :        FI != IE; ++FI) {
      59             :     GCFunctionInfo &MD = **FI;
      60           9 :     if (MD.getStrategy().getName() != getStrategy().getName())
      61             :       // this function is managed by some other GC
      62             :       continue;
      63             :     /** A compact GC layout. Emit this data structure:
      64             :      *
      65             :      * struct {
      66             :      *   int16_t PointCount;
      67             :      *   void *SafePointAddress[PointCount];
      68             :      *   int16_t StackFrameSize; (in words)
      69             :      *   int16_t StackArity;
      70             :      *   int16_t LiveCount;
      71             :      *   int16_t LiveOffsets[LiveCount];
      72             :      * } __gcmap_<FUNCTIONNAME>;
      73             :      **/
      74             : 
      75             :     // Align to address width.
      76           5 :     AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
      77             : 
      78             :     // Emit PointCount.
      79           6 :     OS.AddComment("safe point count");
      80           3 :     AP.emitInt16(MD.size());
      81             : 
      82             :     // And each safe point...
      83           6 :     for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
      84             :          ++PI) {
      85             :       // Emit the address of the safe point.
      86           6 :       OS.AddComment("safe point address");
      87           3 :       MCSymbol *Label = PI->Label;
      88           3 :       AP.EmitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/);
      89             :     }
      90             : 
      91             :     // Stack information never change in safe points! Only print info from the
      92             :     // first call-site.
      93             :     GCFunctionInfo::iterator PI = MD.begin();
      94             : 
      95             :     // Emit the stack frame size.
      96           6 :     OS.AddComment("stack frame size (in words)");
      97           3 :     AP.emitInt16(MD.getFrameSize() / IntPtrSize);
      98             : 
      99             :     // Emit stack arity, i.e. the number of stacked arguments.
     100           3 :     unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
     101           3 :     unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs
     102           0 :                               ? MD.getFunction().arg_size() - RegisteredArgs
     103           3 :                               : 0;
     104           6 :     OS.AddComment("stack arity");
     105           3 :     AP.emitInt16(StackArity);
     106             : 
     107             :     // Emit the number of live roots in the function.
     108           6 :     OS.AddComment("live root count");
     109           3 :     AP.emitInt16(MD.live_size(PI));
     110             : 
     111             :     // And for each live root...
     112             :     for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
     113             :                                        LE = MD.live_end(PI);
     114           3 :          LI != LE; ++LI) {
     115             :       // Emit live root's offset within the stack frame.
     116           0 :       OS.AddComment("stack index (offset / wordsize)");
     117           0 :       AP.emitInt16(LI->StackOffset / IntPtrSize);
     118             :     }
     119             :   }
     120           3 : }
     121             : 
     122           0 : void llvm::linkErlangGCPrinter() {}

Generated by: LCOV version 1.13