Skip to content

Commit 4a894da

Browse files
committed
rustllvm: Emit a stack map for frames with only static type descriptors
1 parent d81d864 commit 4a894da

File tree

1 file changed

+159
-3
lines changed

1 file changed

+159
-3
lines changed

src/rustllvm/RustGCMetadataPrinter.cpp

Lines changed: 159 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "llvm/Constants.h"
15+
#include "llvm/DerivedTypes.h"
16+
#include "llvm/Module.h"
1417
#include "llvm/CodeGen/GCs.h"
1518
#include "llvm/CodeGen/AsmPrinter.h"
1619
#include "llvm/CodeGen/GCMetadataPrinter.h"
17-
#include "llvm/Module.h"
1820
#include "llvm/MC/MCAsmInfo.h"
1921
#include "llvm/MC/MCContext.h"
2022
#include "llvm/MC/MCSymbol.h"
@@ -27,19 +29,173 @@
2729
#include "llvm/Support/ErrorHandling.h"
2830
#include "llvm/Support/FormattedStream.h"
2931
#include <cctype>
32+
#include <map>
3033

3134
using namespace llvm;
3235

3336
namespace {
37+
enum RustGCMetaType {
38+
RGCMT_DestIndex, // Type descriptor index -> type descriptor.
39+
RGCMT_SrcIndex, // Value -> type descriptor index.
40+
RGCMT_Static // Value with static type descriptor.
41+
};
3442

3543
class RustGCMetadataPrinter : public GCMetadataPrinter {
44+
private:
45+
std::pair<RustGCMetaType,const Constant *>
46+
GetGCMetadataForRoot(const GCRoot &Root);
47+
void EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out, GCRoot &Root);
48+
bool HandleDestIndex(const GCRoot &Root);
3649
public:
3750
void beginAssembly(AsmPrinter &AP) {};
38-
void finishAssembly(AsmPrinter &AP) {};
51+
void finishAssembly(AsmPrinter &AP);
3952
};
4053

54+
struct OrderedSymbol {
55+
unsigned Index;
56+
MCSymbol *Sym;
57+
58+
OrderedSymbol(unsigned I, MCSymbol *S) : Index(I), Sym(S) {}
59+
60+
static OrderedSymbol make(unsigned I, MCSymbol *S) {
61+
OrderedSymbol OS(I, S);
62+
return OS;
63+
}
64+
};
4165
}
4266

4367
static GCMetadataPrinterRegistry::Add<RustGCMetadataPrinter>
44-
Y("rust", "Rust GC metadata printer");
68+
X("rust", "Rust GC metadata printer");
69+
70+
71+
typedef std::vector< std::pair< MCSymbol *,std::vector<GCRoot> > > RootMap;
72+
73+
std::pair<RustGCMetaType,const Constant *>
74+
RustGCMetadataPrinter::GetGCMetadataForRoot(const GCRoot &Root) {
75+
const GlobalVariable *GCMetaVar =
76+
cast<const GlobalVariable>(Root.Metadata->stripPointerCasts());
77+
78+
const Constant *GCMetaInit = GCMetaVar->getInitializer();
79+
if (isa<ConstantAggregateZero>(GCMetaInit)) {
80+
// "zeroinitializer": expand to (0, 0).
81+
IntegerType *I32 = IntegerType::get(GCMetaInit->getContext(), 32);
82+
ConstantInt *Zero = ConstantInt::get(I32, 0);
83+
return std::make_pair(RGCMT_DestIndex, Zero);
84+
}
85+
86+
const ConstantStruct *GCMeta =
87+
cast<const ConstantStruct>(GCMetaVar->getInitializer());
88+
89+
RustGCMetaType GCMetaType = (RustGCMetaType)
90+
(cast<const ConstantInt>(GCMeta->getOperand(0))->getZExtValue());
91+
const Constant *Payload = cast<const Constant>(GCMeta->getOperand(1));
92+
return std::make_pair(GCMetaType, Payload);
93+
}
94+
95+
void RustGCMetadataPrinter::EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out,
96+
GCRoot &Root) {
97+
int WordSize = AP.TM.getTargetData()->getPointerSize();
98+
99+
std::pair<RustGCMetaType,const Constant *> Pair =
100+
GetGCMetadataForRoot(Root);
101+
const GlobalValue *Tydesc;
102+
103+
switch (Pair.first) {
104+
case RGCMT_DestIndex: // Dest index.
105+
assert(0 && "Dest index should not be here!");
106+
case RGCMT_SrcIndex:
107+
// TODO: Use the mapping to find the tydesc frame offset.
108+
Out.EmitIntValue(1, WordSize, 0);
109+
Out.EmitIntValue(0, WordSize, 0);
110+
return;
111+
case 2: // Static type descriptor.
112+
Out.EmitIntValue(0, WordSize, 0);
113+
Tydesc = cast<const GlobalValue>(Pair.second);
114+
break;
115+
}
116+
117+
MCSymbol *TydescSym = AP.Mang->getSymbol(Tydesc);
118+
Out.EmitSymbolValue(TydescSym, WordSize, 0);
119+
}
120+
121+
// Records the destination index of a type descriptor in the type descriptor
122+
// map, if this GC root is a destination index. Returns true if the GC root is
123+
// a destination index and false otherwise.
124+
bool RustGCMetadataPrinter::HandleDestIndex(const GCRoot &Root) {
125+
std::pair<RustGCMetaType,const Constant *> Pair =
126+
GetGCMetadataForRoot(Root);
127+
return Pair.first == RGCMT_DestIndex; // TODO
128+
}
129+
130+
void RustGCMetadataPrinter::finishAssembly(AsmPrinter &AP) {
131+
MCStreamer &Out = AP.OutStreamer;
132+
133+
// Use the data section.
134+
Out.SwitchSection(AP.getObjFileLowering().getDataSection());
135+
136+
// Iterate over each function.
137+
RootMap Map;
138+
139+
iterator FI = begin(), FE = end();
140+
while (FI != FE) {
141+
GCFunctionInfo &GCFI = **FI;
142+
143+
// Iterate over each safe point.
144+
GCFunctionInfo::iterator SPI = GCFI.begin(), SPE = GCFI.end();
145+
while (SPI != SPE) {
146+
std::vector<GCRoot> Roots;
147+
148+
// Iterate over each live root.
149+
GCFunctionInfo::live_iterator LI = GCFI.live_begin(SPI);
150+
GCFunctionInfo::live_iterator LE = GCFI.live_end(SPI);
151+
while (LI != LE) {
152+
if (!HandleDestIndex(*LI))
153+
Roots.push_back(*LI);
154+
++LI;
155+
}
156+
157+
Map.push_back(std::make_pair(SPI->Label, Roots));
158+
++SPI;
159+
}
160+
++FI;
161+
}
162+
163+
// Write out the map.
164+
Out.AddBlankLine();
165+
166+
int WordSize = AP.TM.getTargetData()->getPointerSize();
167+
168+
MCSymbol *SafePointSym = AP.GetExternalSymbolSymbol("rust_gc_safe_points");
169+
Out.EmitSymbolAttribute(SafePointSym, MCSA_Global);
170+
Out.EmitLabel(SafePointSym);
171+
Out.EmitIntValue(Map.size(), WordSize, 0);
172+
173+
std::vector<MCSymbol *> FrameMapLabels;
174+
175+
RootMap::iterator MI = Map.begin(), ME = Map.end();
176+
unsigned i = 0;
177+
while (MI != ME) {
178+
Out.EmitSymbolValue(MI->first, WordSize, 0);
179+
MCSymbol *FrameMapLabel = AP.GetTempSymbol("rust_frame_map_label", i);
180+
FrameMapLabels.push_back(FrameMapLabel);
181+
++MI, ++i;
182+
}
183+
184+
MI = Map.begin(), i = 0;
185+
while (MI != ME) {
186+
Out.EmitLabel(FrameMapLabels[i]);
187+
188+
std::vector<GCRoot> &Roots = MI->second;
189+
Out.EmitIntValue(Roots.size(), WordSize, 0);
190+
191+
std::vector<GCRoot>::iterator RI = Roots.begin(), RE = Roots.end();
192+
while (RI != RE) {
193+
Out.EmitIntValue(RI->StackOffset, WordSize, 0);
194+
EmitGCMetadata(AP, Out, *RI);
195+
++RI;
196+
}
197+
198+
++MI, ++i;
199+
}
200+
}
45201

0 commit comments

Comments
 (0)