llvm.org GIT mirror llvm / 477de3a
Add a GC plugin for Erlang git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177867 91177308-0d34-0410-b5e6-96231b3b80d8 Yiannis Tsiouris 6 years ago
6 changed file(s) with 234 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
2525
2626 /// Creates an ocaml-compatible metadata printer.
2727 void linkOcamlGCPrinter();
28
29 /// Creates an erlang-compatible garbage collector.
30 void linkErlangGC();
31
32 /// Creates an erlang-compatible metadata printer.
33 void linkErlangGCPrinter();
2834
2935 /// Creates a shadow stack garbage collector. This collector requires no code
3036 /// generator support.
2828 return;
2929
3030 llvm::linkOcamlGCPrinter();
31 llvm::linkErlangGCPrinter();
3132
3233 }
3334 } ForceAsmWriterLinking; // Force link by creating a global definition.
3636 (void) llvm::createDefaultPBQPRegisterAllocator();
3737
3838 llvm::linkOcamlGC();
39 llvm::linkErlangGC();
3940 llvm::linkShadowStackGC();
4041
4142 (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default);
0 //===-- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the compiler plugin that is used in order to emit
10 // garbage collection information in a convenient layout for parsing and
11 // loading in the Erlang/OTP runtime.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/CodeGen/AsmPrinter.h"
16 #include "llvm/CodeGen/GCs.h"
17 #include "llvm/CodeGen/GCMetadataPrinter.h"
18 #include "llvm/IR/DataLayout.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/Instruction.h"
21 #include "llvm/IR/IntrinsicInst.h"
22 #include "llvm/IR/Metadata.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/Target/TargetLoweringObjectFile.h"
29 #include "llvm/Target/TargetMachine.h"
30
31 using namespace llvm;
32
33 namespace {
34
35 class ErlangGCPrinter : public GCMetadataPrinter {
36 public:
37 void beginAssembly(AsmPrinter &AP);
38 void finishAssembly(AsmPrinter &AP);
39 };
40
41 }
42
43 static GCMetadataPrinterRegistry::Add
44 X("erlang", "erlang-compatible garbage collector");
45
46 void llvm::linkErlangGCPrinter() { }
47
48 void ErlangGCPrinter::beginAssembly(AsmPrinter &AP) { }
49
50 void ErlangGCPrinter::finishAssembly(AsmPrinter &AP) {
51 MCStreamer &OS = AP.OutStreamer;
52 unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize();
53
54 // Put this in a custom .note section.
55 AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getContext()
56 .getELFSection(".note.gc", ELF::SHT_PROGBITS, 0,
57 SectionKind::getDataRel()));
58
59 // For each function...
60 for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
61 GCFunctionInfo &MD = **FI;
62
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_;
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;
88 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 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;
101 unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ?
102 MD.getFunction().arg_size() - RegisteredArgs : 0;
103 OS.AddComment("stack arity");
104 AP.EmitInt16(StackArity);
105
106 // Emit the number of live roots in the function.
107 OS.AddComment("live root count");
108 AP.EmitInt16(MD.live_size(PI));
109
110 // And for each live root...
111 for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
112 LE = MD.live_end(PI);
113 LI != LE; ++LI) {
114 // Emit live root's offset within the stack frame.
115 OS.AddComment("stack index (offset / wordsize)");
116 AP.EmitInt16(LI->StackOffset / IntPtrSize);
117 }
118 }
119 }
0 //===-- ErlangGC.cpp - Erlang/OTP GC strategy -------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Erlang/OTP runtime-compatible garbage collector
10 // (e.g. defines safe points, root initialization etc.)
11 //
12 // The frametable emitter is in ErlangGCPrinter.cpp.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/CodeGen/GCs.h"
17 #include "llvm/CodeGen/GCStrategy.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Target/TargetMachine.h"
23
24 using namespace llvm;
25
26 namespace {
27
28 class ErlangGC : public GCStrategy {
29 MCSymbol *InsertLabel(MachineBasicBlock &MBB,
30 MachineBasicBlock::iterator MI,
31 DebugLoc DL) const;
32 public:
33 ErlangGC();
34 bool findCustomSafePoints(GCFunctionInfo &FI, MachineFunction &MF);
35 };
36
37 }
38
39 static GCRegistry::Add
40 X("erlang", "erlang-compatible garbage collector");
41
42 void llvm::linkErlangGC() { }
43
44 ErlangGC::ErlangGC() {
45 InitRoots = false;
46 NeededSafePoints = 1 << GC::PostCall;
47 UsesMetadata = true;
48 CustomRoots = false;
49 CustomSafePoints = true;
50 }
51
52 MCSymbol *ErlangGC::InsertLabel(MachineBasicBlock &MBB,
53 MachineBasicBlock::iterator MI,
54 DebugLoc DL) const {
55 const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
56 MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol();
57 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
58 return Label;
59 }
60
61 bool ErlangGC::findCustomSafePoints(GCFunctionInfo &FI, MachineFunction &MF) {
62 for (MachineFunction::iterator BBI = MF.begin(), BBE = MF.end(); BBI != BBE;
63 ++BBI)
64 for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end();
65 MI != ME; ++MI)
66
67 if (MI->getDesc().isCall()) {
68
69 // Do not treat tail call sites as safe points.
70 if (MI->getDesc().isTerminator())
71 continue;
72
73 /* Code copied from VisitCallPoint(...) */
74 MachineBasicBlock::iterator RAI = MI; ++RAI;
75 MCSymbol* Label = InsertLabel(*MI->getParent(), RAI, MI->getDebugLoc());
76 FI.addSafePoint(GC::PostCall, Label, MI->getDebugLoc());
77 }
78
79 return false;
80 }
0 ; RUN: llc -mtriple=x86_64-linux-gnu < %s | FileCheck %s --check-prefix=CHECK64
1 ; RUN: llc -mtriple=i686-linux-gnu < %s | FileCheck %s --check-prefix=CHECK32
2
3 define i32 @main(i32 %x) nounwind gc "erlang" {
4 %puts = tail call i32 @foo(i32 %x)
5 ret i32 0
6
7 ; CHECK64: .section .note.gc,"",@progbits
8 ; CHECK64-NEXT: .align 8
9 ; CHECK64-NEXT: .short 1 # safe point count
10 ; CHECK64-NEXT: .long .Ltmp0 # safe point address
11 ; CHECK64-NEXT: .short 1 # stack frame size (in words)
12 ; CHECK64-NEXT: .short 0 # stack arity
13 ; CHECK64-NEXT: .short 0 # live root count
14
15 ; CHECK32: .section .note.gc,"",@progbits
16 ; CHECK32-NEXT: .align 4
17 ; CHECK32-NEXT: .short 1 # safe point count
18 ; CHECK32-NEXT: .long .Ltmp0 # safe point address
19 ; CHECK32-NEXT: .short 3 # stack frame size (in words)
20 ; CHECK32-NEXT: .short 0 # stack arity
21 ; CHECK32-NEXT: .short 0 # live root count
22 }
23
24 declare i32 @foo(i32)