size_t live_size(const iterator &p) const { return roots_size(); }
};
-
/// An analysis pass which caches information about the entire Module.
/// Records both the function level information used by GCRoots and a
/// cache of the 'active' gc strategy objects for the current Module.
class GCModuleInfo : public ImmutablePass {
typedef StringMap<GCStrategy*> strategy_map_type;
typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
- typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
strategy_map_type StrategyMap;
list_type StrategyList;
- finfo_map_type FInfoMap;
GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name);
public:
+ /// List of per function info objects. In theory, Each of these
+ /// may be associated with a different GC.
+ typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec;
+
+ FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
+ FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
+
+
+ private:
+ /// Owning list of all GCFunctionInfos associated with this Module
+ FuncInfoVec Functions;
+
+ /// Non-owning map to bypass linear search when finding the GCFunctionInfo
+ /// associated with a particular Function.
+ typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
+ finfo_map_type FInfoMap;
+ public:
+
typedef list_type::const_iterator iterator;
static char ID;
iterator begin() const { return StrategyList.begin(); }
iterator end() const { return StrategyList.end(); }
- /// get - Look up function metadata.
- ///
+ /// get - Look up function metadata. This is currently assumed
+ /// have the side effect of initializing the associated GCStrategy. That
+ /// will soon change.
GCFunctionInfo &getFunctionInfo(const Function &F);
};
/// defaults from Registry.
typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry;
- /// GCMetadataPrinter - Emits GC metadata as assembly code.
- ///
+ /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
+ /// created, managed, and owned by the AsmPrinter.
class GCMetadataPrinter {
- public:
- typedef GCStrategy::list_type list_type;
- typedef GCStrategy::iterator iterator;
-
private:
GCStrategy *S;
-
friend class AsmPrinter;
protected:
public:
GCStrategy &getStrategy() { return *S; }
- /// begin/end - Iterate over the collected function metadata.
- iterator begin() { return S->begin(); }
- iterator end() { return S->end(); }
-
- /// beginAssembly/finishAssembly - Emit module metadata as assembly code.
- virtual void beginAssembly(Module &M, AsmPrinter &AP);
- virtual void finishAssembly(Module &M, AsmPrinter &AP);
+ /// Called before the assembly for the module is generated by
+ /// the AsmPrinter (but after target specific hooks.)
+ virtual void beginAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {}
+ /// Called after the assembly for the module is generated by
+ /// the AsmPrinter (but before target specific hooks)
+ virtual void finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {}
virtual ~GCMetadataPrinter();
};
/// through the GCModuleInfo analysis pass. They are owned by the analysis
/// pass and recreated every time that pass is invalidated.
class GCStrategy {
- public:
- typedef std::vector<std::unique_ptr<GCFunctionInfo>> list_type;
- typedef list_type::iterator iterator;
-
private:
friend class GCModuleInfo;
std::string Name;
- list_type Functions;
-
protected:
unsigned NeededSafePoints; ///< Bitmask of required safe points.
bool CustomReadBarriers; ///< Default is to insert loads.
/// the back-end (assembler, JIT, or otherwise).
bool usesMetadata() const { return UsesMetadata; }
- /// begin/end - Iterators for function metadata.
- ///
- iterator begin() { return Functions.begin(); }
- iterator end() { return Functions.end(); }
-
- /// insertFunctionMetadata - Creates metadata for a function.
- ///
- GCFunctionInfo *insertFunctionInfo(const Function &F);
-
/// initializeCustomLowering/performCustomLowering - If any of the actions
/// are set to custom, performCustomLowering must be overriden to transform
/// the corresponding actions to LLVM IR. initializeCustomLowering is
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
for (auto &I : *MI)
if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
- MP->beginAssembly(M, *this);
+ MP->beginAssembly(M, *MI, *this);
// Emit module-level inline asm if it exists.
if (!M.getModuleInlineAsm().empty()) {
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; )
if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(**--I))
- MP->finishAssembly(M, *this);
+ MP->finishAssembly(M, *MI, *this);
// Emit llvm.ident metadata in an '.ident' directive.
EmitModuleIdents(M);
class ErlangGCPrinter : public GCMetadataPrinter {
public:
- void beginAssembly(Module &M, AsmPrinter &AP) override;
- void finishAssembly(Module &M, AsmPrinter &AP) override;
+ void finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) override;
};
}
void llvm::linkErlangGCPrinter() { }
-void ErlangGCPrinter::beginAssembly(Module &M, AsmPrinter &AP) { }
-
-void ErlangGCPrinter::finishAssembly(Module &M, AsmPrinter &AP) {
+void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
MCStreamer &OS = AP.OutStreamer;
unsigned IntPtrSize =
AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize();
SectionKind::getDataRel()));
// For each function...
- for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
+ for (GCModuleInfo::FuncInfoVec::iterator FI = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end();
+ FI != IE; ++FI) {
GCFunctionInfo &MD = **FI;
-
+ if (MD.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
/** A compact GC layout. Emit this data structure:
*
* struct {
class OcamlGCMetadataPrinter : public GCMetadataPrinter {
public:
- void beginAssembly(Module &M, AsmPrinter &AP) override;
- void finishAssembly(Module &M, AsmPrinter &AP) override;
+ void beginAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) override;
+ void finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) override;
};
}
AP.OutStreamer.EmitLabel(Sym);
}
-void OcamlGCMetadataPrinter::beginAssembly(Module &M, AsmPrinter &AP) {
+void OcamlGCMetadataPrinter::beginAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection());
EmitCamlGlobal(M, AP, "code_begin");
/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
/// either condition is detected in a function which uses the GC.
///
-void OcamlGCMetadataPrinter::finishAssembly(Module &M, AsmPrinter &AP) {
+void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
unsigned IntPtrSize =
AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize();
EmitCamlGlobal(M, AP, "frametable");
int NumDescriptors = 0;
- for (iterator I = begin(), IE = end(); I != IE; ++I) {
+ for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end(); I != IE; ++I) {
GCFunctionInfo &FI = **I;
+ if (FI.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) {
NumDescriptors++;
}
AP.EmitInt16(NumDescriptors);
AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
- for (iterator I = begin(), IE = end(); I != IE; ++I) {
+ for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end(); I != IE; ++I) {
GCFunctionInfo &FI = **I;
+ if (FI.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
uint64_t FrameSize = FI.getFrameSize();
if (FrameSize >= 1<<16) {
return *I->second;
GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC());
- GCFunctionInfo *GFI = S->insertFunctionInfo(F);
+ Functions.push_back(make_unique<GCFunctionInfo>(F, *S));
+ GCFunctionInfo *GFI = Functions.back().get();
FInfoMap[&F] = GFI;
return *GFI;
}
void GCModuleInfo::clear() {
+ Functions.clear();
FInfoMap.clear();
StrategyMap.clear();
StrategyList.clear();
GCMetadataPrinter::GCMetadataPrinter() { }
GCMetadataPrinter::~GCMetadataPrinter() { }
-
-void GCMetadataPrinter::beginAssembly(Module &M, AsmPrinter &AP) {
- // Default is no action.
-}
-
-void GCMetadataPrinter::finishAssembly(Module &M, AsmPrinter &AP) {
- // Default is no action.
-}
llvm_unreachable(nullptr);
}
-
-GCFunctionInfo *GCStrategy::insertFunctionInfo(const Function &F) {
- Functions.push_back(make_unique<GCFunctionInfo>(F, *this));
- return Functions.back().get();
-}
-
// -----------------------------------------------------------------------------
INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering",