From 4a894dae8ec784480cc7d8b127a79f9418e8fa7d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Aug 2011 18:08:36 -0700 Subject: rustllvm: Emit a stack map for frames with only static type descriptors --- src/rustllvm/RustGCMetadataPrinter.cpp | 162 ++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) (limited to 'src/rustllvm/RustGCMetadataPrinter.cpp') diff --git a/src/rustllvm/RustGCMetadataPrinter.cpp b/src/rustllvm/RustGCMetadataPrinter.cpp index d17d7da1703..d2ee0c3baeb 100644 --- a/src/rustllvm/RustGCMetadataPrinter.cpp +++ b/src/rustllvm/RustGCMetadataPrinter.cpp @@ -11,10 +11,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" #include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" -#include "llvm/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" @@ -27,19 +29,173 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include +#include using namespace llvm; namespace { + enum RustGCMetaType { + RGCMT_DestIndex, // Type descriptor index -> type descriptor. + RGCMT_SrcIndex, // Value -> type descriptor index. + RGCMT_Static // Value with static type descriptor. + }; class RustGCMetadataPrinter : public GCMetadataPrinter { + private: + std::pair + GetGCMetadataForRoot(const GCRoot &Root); + void EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out, GCRoot &Root); + bool HandleDestIndex(const GCRoot &Root); public: void beginAssembly(AsmPrinter &AP) {}; - void finishAssembly(AsmPrinter &AP) {}; + void finishAssembly(AsmPrinter &AP); }; + struct OrderedSymbol { + unsigned Index; + MCSymbol *Sym; + + OrderedSymbol(unsigned I, MCSymbol *S) : Index(I), Sym(S) {} + + static OrderedSymbol make(unsigned I, MCSymbol *S) { + OrderedSymbol OS(I, S); + return OS; + } + }; } static GCMetadataPrinterRegistry::Add -Y("rust", "Rust GC metadata printer"); +X("rust", "Rust GC metadata printer"); + + +typedef std::vector< std::pair< MCSymbol *,std::vector > > RootMap; + +std::pair +RustGCMetadataPrinter::GetGCMetadataForRoot(const GCRoot &Root) { + const GlobalVariable *GCMetaVar = + cast(Root.Metadata->stripPointerCasts()); + + const Constant *GCMetaInit = GCMetaVar->getInitializer(); + if (isa(GCMetaInit)) { + // "zeroinitializer": expand to (0, 0). + IntegerType *I32 = IntegerType::get(GCMetaInit->getContext(), 32); + ConstantInt *Zero = ConstantInt::get(I32, 0); + return std::make_pair(RGCMT_DestIndex, Zero); + } + + const ConstantStruct *GCMeta = + cast(GCMetaVar->getInitializer()); + + RustGCMetaType GCMetaType = (RustGCMetaType) + (cast(GCMeta->getOperand(0))->getZExtValue()); + const Constant *Payload = cast(GCMeta->getOperand(1)); + return std::make_pair(GCMetaType, Payload); +} + +void RustGCMetadataPrinter::EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out, + GCRoot &Root) { + int WordSize = AP.TM.getTargetData()->getPointerSize(); + + std::pair Pair = + GetGCMetadataForRoot(Root); + const GlobalValue *Tydesc; + + switch (Pair.first) { + case RGCMT_DestIndex: // Dest index. + assert(0 && "Dest index should not be here!"); + case RGCMT_SrcIndex: + // TODO: Use the mapping to find the tydesc frame offset. + Out.EmitIntValue(1, WordSize, 0); + Out.EmitIntValue(0, WordSize, 0); + return; + case 2: // Static type descriptor. + Out.EmitIntValue(0, WordSize, 0); + Tydesc = cast(Pair.second); + break; + } + + MCSymbol *TydescSym = AP.Mang->getSymbol(Tydesc); + Out.EmitSymbolValue(TydescSym, WordSize, 0); +} + +// Records the destination index of a type descriptor in the type descriptor +// map, if this GC root is a destination index. Returns true if the GC root is +// a destination index and false otherwise. +bool RustGCMetadataPrinter::HandleDestIndex(const GCRoot &Root) { + std::pair Pair = + GetGCMetadataForRoot(Root); + return Pair.first == RGCMT_DestIndex; // TODO +} + +void RustGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { + MCStreamer &Out = AP.OutStreamer; + + // Use the data section. + Out.SwitchSection(AP.getObjFileLowering().getDataSection()); + + // Iterate over each function. + RootMap Map; + + iterator FI = begin(), FE = end(); + while (FI != FE) { + GCFunctionInfo &GCFI = **FI; + + // Iterate over each safe point. + GCFunctionInfo::iterator SPI = GCFI.begin(), SPE = GCFI.end(); + while (SPI != SPE) { + std::vector Roots; + + // Iterate over each live root. + GCFunctionInfo::live_iterator LI = GCFI.live_begin(SPI); + GCFunctionInfo::live_iterator LE = GCFI.live_end(SPI); + while (LI != LE) { + if (!HandleDestIndex(*LI)) + Roots.push_back(*LI); + ++LI; + } + + Map.push_back(std::make_pair(SPI->Label, Roots)); + ++SPI; + } + ++FI; + } + + // Write out the map. + Out.AddBlankLine(); + + int WordSize = AP.TM.getTargetData()->getPointerSize(); + + MCSymbol *SafePointSym = AP.GetExternalSymbolSymbol("rust_gc_safe_points"); + Out.EmitSymbolAttribute(SafePointSym, MCSA_Global); + Out.EmitLabel(SafePointSym); + Out.EmitIntValue(Map.size(), WordSize, 0); + + std::vector FrameMapLabels; + + RootMap::iterator MI = Map.begin(), ME = Map.end(); + unsigned i = 0; + while (MI != ME) { + Out.EmitSymbolValue(MI->first, WordSize, 0); + MCSymbol *FrameMapLabel = AP.GetTempSymbol("rust_frame_map_label", i); + FrameMapLabels.push_back(FrameMapLabel); + ++MI, ++i; + } + + MI = Map.begin(), i = 0; + while (MI != ME) { + Out.EmitLabel(FrameMapLabels[i]); + + std::vector &Roots = MI->second; + Out.EmitIntValue(Roots.size(), WordSize, 0); + + std::vector::iterator RI = Roots.begin(), RE = Roots.end(); + while (RI != RE) { + Out.EmitIntValue(RI->StackOffset, WordSize, 0); + EmitGCMetadata(AP, Out, *RI); + ++RI; + } + + ++MI, ++i; + } +} -- cgit 1.4.1-3-g733a5