/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter ----------------===// |
2 | | // |
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/BinaryFormat/ELF.h" |
17 | | #include "llvm/CodeGen/AsmPrinter.h" |
18 | | #include "llvm/CodeGen/GCMetadata.h" |
19 | | #include "llvm/CodeGen/GCMetadataPrinter.h" |
20 | | #include "llvm/CodeGen/GCStrategy.h" |
21 | | #include "llvm/CodeGen/GCs.h" |
22 | | #include "llvm/IR/DataLayout.h" |
23 | | #include "llvm/IR/Function.h" |
24 | | #include "llvm/IR/Module.h" |
25 | | #include "llvm/MC/MCContext.h" |
26 | | #include "llvm/MC/MCSectionELF.h" |
27 | | #include "llvm/MC/MCStreamer.h" |
28 | | #include "llvm/MC/MCSymbol.h" |
29 | | #include "llvm/Target/TargetLoweringObjectFile.h" |
30 | | |
31 | | using namespace llvm; |
32 | | |
33 | | namespace { |
34 | | |
35 | | class ErlangGCPrinter : public GCMetadataPrinter { |
36 | | public: |
37 | | void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override; |
38 | | }; |
39 | | |
40 | | } // end anonymous namespace |
41 | | |
42 | | static GCMetadataPrinterRegistry::Add<ErlangGCPrinter> |
43 | | X("erlang", "erlang-compatible garbage collector"); |
44 | | |
45 | | void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info, |
46 | 3 | AsmPrinter &AP) { |
47 | 3 | MCStreamer &OS = *AP.OutStreamer; |
48 | 3 | unsigned IntPtrSize = M.getDataLayout().getPointerSize(); |
49 | 3 | |
50 | 3 | // Put this in a custom .note section. |
51 | 3 | OS.SwitchSection( |
52 | 3 | AP.getObjFileLowering().getContext().getELFSection(".note.gc", |
53 | 3 | ELF::SHT_PROGBITS, 0)); |
54 | 3 | |
55 | 3 | // For each function... |
56 | 3 | for (GCModuleInfo::FuncInfoVec::iterator FI = Info.funcinfo_begin(), |
57 | 3 | IE = Info.funcinfo_end(); |
58 | 6 | FI != IE6 ; ++FI3 ) { |
59 | 3 | GCFunctionInfo &MD = **FI; |
60 | 3 | if (MD.getStrategy().getName() != getStrategy().getName()) |
61 | 3 | // this function is managed by some other GC |
62 | 0 | continue; |
63 | 3 | /** A compact GC layout. Emit this data structure: |
64 | 3 | * |
65 | 3 | * struct { |
66 | 3 | * int16_t PointCount; |
67 | 3 | * void *SafePointAddress[PointCount]; |
68 | 3 | * int16_t StackFrameSize; (in words) |
69 | 3 | * int16_t StackArity; |
70 | 3 | * int16_t LiveCount; |
71 | 3 | * int16_t LiveOffsets[LiveCount]; |
72 | 3 | * } __gcmap_<FUNCTIONNAME>; |
73 | 3 | **/ |
74 | 3 | |
75 | 3 | // Align to address width. |
76 | 3 | AP.EmitAlignment(IntPtrSize == 4 ? 3 21 : 32 ); |
77 | 3 | |
78 | 3 | // Emit PointCount. |
79 | 3 | OS.AddComment("safe point count"); |
80 | 3 | AP.EmitInt16(MD.size()); |
81 | 3 | |
82 | 3 | // And each safe point... |
83 | 6 | for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE; |
84 | 3 | ++PI3 ) { |
85 | 3 | // Emit the address of the safe point. |
86 | 3 | OS.AddComment("safe point address"); |
87 | 3 | MCSymbol *Label = PI->Label; |
88 | 3 | AP.EmitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/); |
89 | 3 | } |
90 | 3 | |
91 | 3 | // Stack information never change in safe points! Only print info from the |
92 | 3 | // first call-site. |
93 | 3 | GCFunctionInfo::iterator PI = MD.begin(); |
94 | 3 | |
95 | 3 | // Emit the stack frame size. |
96 | 3 | OS.AddComment("stack frame size (in words)"); |
97 | 3 | AP.EmitInt16(MD.getFrameSize() / IntPtrSize); |
98 | 3 | |
99 | 3 | // Emit stack arity, i.e. the number of stacked arguments. |
100 | 3 | unsigned RegisteredArgs = IntPtrSize == 4 ? 51 : 62 ; |
101 | 3 | unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs |
102 | 0 | ? MD.getFunction().arg_size() - RegisteredArgs |
103 | 3 | : 0; |
104 | 3 | OS.AddComment("stack arity"); |
105 | 3 | AP.EmitInt16(StackArity); |
106 | 3 | |
107 | 3 | // Emit the number of live roots in the function. |
108 | 3 | OS.AddComment("live root count"); |
109 | 3 | AP.EmitInt16(MD.live_size(PI)); |
110 | 3 | |
111 | 3 | // And for each live root... |
112 | 3 | for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), |
113 | 3 | LE = MD.live_end(PI); |
114 | 3 | LI != LE3 ; ++LI0 ) { |
115 | 0 | // Emit live root's offset within the stack frame. |
116 | 0 | OS.AddComment("stack index (offset / wordsize)"); |
117 | 0 | AP.EmitInt16(LI->StackOffset / IntPtrSize); |
118 | 0 | } |
119 | 3 | } |
120 | 3 | } |
121 | | |
122 | 0 | void llvm::linkErlangGCPrinter() {} |