1477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris//===-- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter -----*- C++ -*-===// 2477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// 3477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// The LLVM Compiler Infrastructure 4477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// 5477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// This file is distributed under the University of Illinois Open Source 6477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// License. See LICENSE.TXT for details. 7477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// 8477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris//===----------------------------------------------------------------------===// 9477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// 10477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// This file implements the compiler plugin that is used in order to emit 11477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// garbage collection information in a convenient layout for parsing and 12477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// loading in the Erlang/OTP runtime. 13477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris// 14477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris//===----------------------------------------------------------------------===// 15477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 16477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/CodeGen/AsmPrinter.h" 17477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/CodeGen/GCMetadataPrinter.h" 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/CodeGen/GCs.h" 19477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/IR/DataLayout.h" 20477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/IR/Function.h" 21477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/IR/Instruction.h" 22477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/IR/IntrinsicInst.h" 23477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/IR/Metadata.h" 24477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/MC/MCAsmInfo.h" 25477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/MC/MCContext.h" 26477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/MC/MCSectionELF.h" 27477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/MC/MCStreamer.h" 28477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/MC/MCSymbol.h" 29477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/Target/TargetLoweringObjectFile.h" 30477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris#include "llvm/Target/TargetMachine.h" 31477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 32477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisusing namespace llvm; 33477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 34477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisnamespace { 35477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 36477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris class ErlangGCPrinter : public GCMetadataPrinter { 37477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris public: 3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void beginAssembly(AsmPrinter &AP) override; 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void finishAssembly(AsmPrinter &AP) override; 40477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris }; 41477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 42477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris} 43477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 44477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisstatic GCMetadataPrinterRegistry::Add<ErlangGCPrinter> 45477de3a7859104d7c41a36628169e13e524e980aYiannis TsiourisX("erlang", "erlang-compatible garbage collector"); 46477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 47477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisvoid llvm::linkErlangGCPrinter() { } 48477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 49477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisvoid ErlangGCPrinter::beginAssembly(AsmPrinter &AP) { } 50477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 51477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiourisvoid ErlangGCPrinter::finishAssembly(AsmPrinter &AP) { 52477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris MCStreamer &OS = AP.OutStreamer; 53477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); 54477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 55477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Put this in a custom .note section. 56477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getContext() 57477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris .getELFSection(".note.gc", ELF::SHT_PROGBITS, 0, 58477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris SectionKind::getDataRel())); 59477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 60477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // For each function... 61477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { 62477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris GCFunctionInfo &MD = **FI; 63477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 64477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris /** A compact GC layout. Emit this data structure: 65477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * 66477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * struct { 67477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * int16_t PointCount; 68477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * void *SafePointAddress[PointCount]; 69477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * int16_t StackFrameSize; (in words) 70477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * int16_t StackArity; 71477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * int16_t LiveCount; 72477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * int16_t LiveOffsets[LiveCount]; 73477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris * } __gcmap_<FUNCTIONNAME>; 74477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris **/ 75477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 76477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Align to address width. 77477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); 78477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 79477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit PointCount. 80477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("safe point count"); 81477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitInt16(MD.size()); 82477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 83477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // And each safe point... 84477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE; 85477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris ++PI) { 86477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit the address of the safe point. 87477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("safe point address"); 88477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris MCSymbol *Label = PI->Label; 89477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/); 90477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris } 91477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 92477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Stack information never change in safe points! Only print info from the 93477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // first call-site. 94477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris GCFunctionInfo::iterator PI = MD.begin(); 95477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 96477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit the stack frame size. 97477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("stack frame size (in words)"); 98477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitInt16(MD.getFrameSize() / IntPtrSize); 99477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 100477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit stack arity, i.e. the number of stacked arguments. 101477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6; 102477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ? 103477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris MD.getFunction().arg_size() - RegisteredArgs : 0; 104477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("stack arity"); 105477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitInt16(StackArity); 106477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 107477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit the number of live roots in the function. 108477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("live root count"); 109477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitInt16(MD.live_size(PI)); 110477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris 111477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // And for each live root... 112477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), 113477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris LE = MD.live_end(PI); 114477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris LI != LE; ++LI) { 115477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris // Emit live root's offset within the stack frame. 116477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris OS.AddComment("stack index (offset / wordsize)"); 117477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris AP.EmitInt16(LI->StackOffset / IntPtrSize); 118477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris } 119477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris } 120477de3a7859104d7c41a36628169e13e524e980aYiannis Tsiouris} 121