blob: 342efc3611c784ff0af28a40b5c5a0f26e604438 [file] [log] [blame]
Eugene Zelenkod96089b2017-02-14 00:33:36 +00001//===- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter ----------------===//
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +00002//
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/CodeGen/AsmPrinter.h"
Eugene Zelenkod96089b2017-02-14 00:33:36 +000017#include "llvm/CodeGen/GCMetadata.h"
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000018#include "llvm/CodeGen/GCMetadataPrinter.h"
Eugene Zelenkod96089b2017-02-14 00:33:36 +000019#include "llvm/CodeGen/GCStrategy.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000020#include "llvm/CodeGen/GCs.h"
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000021#include "llvm/IR/DataLayout.h"
22#include "llvm/IR/Function.h"
Eugene Zelenkod96089b2017-02-14 00:33:36 +000023#include "llvm/IR/Module.h"
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCSectionELF.h"
26#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSymbol.h"
Eugene Zelenkod96089b2017-02-14 00:33:36 +000028#include "llvm/Target/TargetLoweringObjectFile.h"
29#include "llvm/Support/ELF.h"
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000030
31using namespace llvm;
32
33namespace {
34
Philip Reames36319532015-01-16 23:16:12 +000035class ErlangGCPrinter : public GCMetadataPrinter {
36public:
37 void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override;
38};
Eugene Zelenkod96089b2017-02-14 00:33:36 +000039
40} // end anonymous namespace
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000041
42static GCMetadataPrinterRegistry::Add<ErlangGCPrinter>
Philip Reames36319532015-01-16 23:16:12 +000043 X("erlang", "erlang-compatible garbage collector");
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000044
Philip Reames1e308972014-12-11 01:47:23 +000045void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
46 AsmPrinter &AP) {
Lang Hames9ff69c82015-04-24 19:11:51 +000047 MCStreamer &OS = *AP.OutStreamer;
Mehdi Aminibd7287e2015-07-16 06:11:10 +000048 unsigned IntPtrSize = M.getDataLayout().getPointerSize();
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000049
50 // Put this in a custom .note section.
Lang Hames9ff69c82015-04-24 19:11:51 +000051 OS.SwitchSection(
Rafael Espindolaba31e272015-01-29 17:33:21 +000052 AP.getObjFileLowering().getContext().getELFSection(".note.gc",
53 ELF::SHT_PROGBITS, 0));
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000054
55 // For each function...
Philip Reames1e308972014-12-11 01:47:23 +000056 for (GCModuleInfo::FuncInfoVec::iterator FI = Info.funcinfo_begin(),
Philip Reames36319532015-01-16 23:16:12 +000057 IE = Info.funcinfo_end();
Philip Reames1e308972014-12-11 01:47:23 +000058 FI != IE; ++FI) {
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000059 GCFunctionInfo &MD = **FI;
Philip Reames1e308972014-12-11 01:47:23 +000060 if (MD.getStrategy().getName() != getStrategy().getName())
61 // this function is managed by some other GC
62 continue;
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000063 /** 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 AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
77
78 // Emit PointCount.
79 OS.AddComment("safe point count");
80 AP.EmitInt16(MD.size());
81
82 // And each safe point...
83 for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
84 ++PI) {
85 // Emit the address of the safe point.
86 OS.AddComment("safe point address");
87 MCSymbol *Label = PI->Label;
Philip Reames36319532015-01-16 23:16:12 +000088 AP.EmitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/);
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +000089 }
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 OS.AddComment("stack frame size (in words)");
97 AP.EmitInt16(MD.getFrameSize() / IntPtrSize);
98
99 // Emit stack arity, i.e. the number of stacked arguments.
100 unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
Philip Reames36319532015-01-16 23:16:12 +0000101 unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs
102 ? MD.getFunction().arg_size() - RegisteredArgs
103 : 0;
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +0000104 OS.AddComment("stack arity");
105 AP.EmitInt16(StackArity);
106
107 // Emit the number of live roots in the function.
108 OS.AddComment("live root count");
109 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);
Philip Reames36319532015-01-16 23:16:12 +0000114 LI != LE; ++LI) {
Yiannis Tsiourisdbb4adf2013-03-25 13:47:46 +0000115 // Emit live root's offset within the stack frame.
116 OS.AddComment("stack index (offset / wordsize)");
117 AP.EmitInt16(LI->StackOffset / IntPtrSize);
118 }
119 }
120}
Eugene Zelenkod96089b2017-02-14 00:33:36 +0000121
122void llvm::linkErlangGCPrinter() {}