|
11 | 11 | //
|
12 | 12 | //===----------------------------------------------------------------------===//
|
13 | 13 |
|
| 14 | +#include "llvm/Constants.h" |
| 15 | +#include "llvm/DerivedTypes.h" |
| 16 | +#include "llvm/Module.h" |
14 | 17 | #include "llvm/CodeGen/GCs.h"
|
15 | 18 | #include "llvm/CodeGen/AsmPrinter.h"
|
16 | 19 | #include "llvm/CodeGen/GCMetadataPrinter.h"
|
17 |
| -#include "llvm/Module.h" |
18 | 20 | #include "llvm/MC/MCAsmInfo.h"
|
19 | 21 | #include "llvm/MC/MCContext.h"
|
20 | 22 | #include "llvm/MC/MCSymbol.h"
|
|
27 | 29 | #include "llvm/Support/ErrorHandling.h"
|
28 | 30 | #include "llvm/Support/FormattedStream.h"
|
29 | 31 | #include <cctype>
|
| 32 | +#include <map> |
30 | 33 |
|
31 | 34 | using namespace llvm;
|
32 | 35 |
|
33 | 36 | 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 | + }; |
34 | 42 |
|
35 | 43 | 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); |
36 | 49 | public:
|
37 | 50 | void beginAssembly(AsmPrinter &AP) {};
|
38 |
| - void finishAssembly(AsmPrinter &AP) {}; |
| 51 | + void finishAssembly(AsmPrinter &AP); |
39 | 52 | };
|
40 | 53 |
|
| 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 | + }; |
41 | 65 | }
|
42 | 66 |
|
43 | 67 | 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 | +} |
45 | 201 |
|
0 commit comments