LLVM API Documentation

ErlangGCPrinter.cpp
Go to the documentation of this file.
00001 //===-- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter -----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the compiler plugin that is used in order to emit
00011 // garbage collection information in a convenient layout for parsing and
00012 // loading in the Erlang/OTP runtime.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/CodeGen/AsmPrinter.h"
00017 #include "llvm/CodeGen/GCMetadataPrinter.h"
00018 #include "llvm/CodeGen/GCs.h"
00019 #include "llvm/IR/DataLayout.h"
00020 #include "llvm/IR/Function.h"
00021 #include "llvm/IR/Instruction.h"
00022 #include "llvm/IR/IntrinsicInst.h"
00023 #include "llvm/IR/Metadata.h"
00024 #include "llvm/MC/MCAsmInfo.h"
00025 #include "llvm/MC/MCContext.h"
00026 #include "llvm/MC/MCSectionELF.h"
00027 #include "llvm/MC/MCStreamer.h"
00028 #include "llvm/MC/MCSymbol.h"
00029 #include "llvm/Target/TargetLoweringObjectFile.h"
00030 #include "llvm/Target/TargetMachine.h"
00031 #include "llvm/Target/TargetSubtargetInfo.h"
00032 
00033 using namespace llvm;
00034 
00035 namespace {
00036 
00037   class ErlangGCPrinter : public GCMetadataPrinter {
00038   public:
00039     void beginAssembly(AsmPrinter &AP) override;
00040     void finishAssembly(AsmPrinter &AP) override;
00041   };
00042 
00043 }
00044 
00045 static GCMetadataPrinterRegistry::Add<ErlangGCPrinter>
00046 X("erlang", "erlang-compatible garbage collector");
00047 
00048 void llvm::linkErlangGCPrinter() { }
00049 
00050 void ErlangGCPrinter::beginAssembly(AsmPrinter &AP) { }
00051 
00052 void ErlangGCPrinter::finishAssembly(AsmPrinter &AP) {
00053   MCStreamer &OS = AP.OutStreamer;
00054   unsigned IntPtrSize =
00055       AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize();
00056 
00057   // Put this in a custom .note section.
00058   AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getContext()
00059     .getELFSection(".note.gc", ELF::SHT_PROGBITS, 0,
00060                    SectionKind::getDataRel()));
00061 
00062   // For each function...
00063   for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
00064     GCFunctionInfo &MD = **FI;
00065 
00066     /** A compact GC layout. Emit this data structure:
00067      *
00068      * struct {
00069      *   int16_t PointCount;
00070      *   void *SafePointAddress[PointCount];
00071      *   int16_t StackFrameSize; (in words)
00072      *   int16_t StackArity;
00073      *   int16_t LiveCount;
00074      *   int16_t LiveOffsets[LiveCount];
00075      * } __gcmap_<FUNCTIONNAME>;
00076      **/
00077 
00078     // Align to address width.
00079     AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
00080 
00081     // Emit PointCount.
00082     OS.AddComment("safe point count");
00083     AP.EmitInt16(MD.size());
00084 
00085     // And each safe point...
00086     for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
00087          ++PI) {
00088       // Emit the address of the safe point.
00089       OS.AddComment("safe point address");
00090       MCSymbol *Label = PI->Label;
00091       AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/);
00092     }
00093 
00094     // Stack information never change in safe points! Only print info from the
00095     // first call-site.
00096     GCFunctionInfo::iterator PI = MD.begin();
00097 
00098     // Emit the stack frame size.
00099     OS.AddComment("stack frame size (in words)");
00100     AP.EmitInt16(MD.getFrameSize() / IntPtrSize);
00101 
00102     // Emit stack arity, i.e. the number of stacked arguments.
00103     unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
00104     unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ?
00105                           MD.getFunction().arg_size() - RegisteredArgs : 0;
00106     OS.AddComment("stack arity");
00107     AP.EmitInt16(StackArity);
00108 
00109     // Emit the number of live roots in the function.
00110     OS.AddComment("live root count");
00111     AP.EmitInt16(MD.live_size(PI));
00112 
00113     // And for each live root...
00114     for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
00115                                        LE = MD.live_end(PI);
00116                                        LI != LE; ++LI) {
00117       // Emit live root's offset within the stack frame.
00118       OS.AddComment("stack index (offset / wordsize)");
00119       AP.EmitInt16(LI->StackOffset / IntPtrSize);
00120     }
00121   }
00122 }