brintos

brintos / llvm-project-archived public Read only

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