mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
This change reverts the interesting parts of 226311 (and 227046). This change introduced two problems, and I've been convinced that an alternate approach is preferrable anyways. The bugs were: - Registery appears to require all users be within the same linkage unit. After this change, asking for "statepoint-example" in Transform/ would sometimes get you nullptr, whereas asking the same question in CodeGen would return the right GCStrategy. The correct long term fix is to get rid of the utter hack which is Registry, but I don't have time for that right now. 227046 appears to have been an attempt to fix this, but I don't believe it does so completely. - GCMetadataPrinter::finishAssembly was being called more than once per GCStrategy. Each Strategy was being added to the GCModuleInfo multiple times. Once I get time again, I'm going to split GCModuleInfo into the gc.root specific part and a GCStrategy owning Analysis pass. I'm probably also going to kill off the Registry. Once that's done, I'll move the new GCStrategyAnalysis and all built in GCStrategies into Analysis. (As original suggested by Chandler.) This will accomplish my original goal of being able to access GCStrategy from Transform/ without adding all of the builtin GCs to IR/. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227109 91177308-0d34-0410-b5e6-96231b3b80d8
174 lines
4.7 KiB
C++
174 lines
4.7 KiB
C++
//===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the GCFunctionInfo class and GCModuleInfo pass.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/GCMetadata.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/CodeGen/GCStrategy.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/MC/MCSymbol.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class Printer : public FunctionPass {
|
|
static char ID;
|
|
raw_ostream &OS;
|
|
|
|
public:
|
|
explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {}
|
|
|
|
const char *getPassName() const override;
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
|
|
|
bool runOnFunction(Function &F) override;
|
|
bool doFinalization(Module &M) override;
|
|
};
|
|
}
|
|
|
|
INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
|
|
"Create Garbage Collector Module Metadata", false, false)
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
|
|
: F(F), S(S), FrameSize(~0LL) {}
|
|
|
|
GCFunctionInfo::~GCFunctionInfo() {}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
char GCModuleInfo::ID = 0;
|
|
|
|
GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
|
|
initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
|
|
assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
|
|
assert(F.hasGC());
|
|
|
|
finfo_map_type::iterator I = FInfoMap.find(&F);
|
|
if (I != FInfoMap.end())
|
|
return *I->second;
|
|
|
|
GCStrategy *S = getGCStrategy(F.getGC());
|
|
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();
|
|
GCStrategyList.clear();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
char Printer::ID = 0;
|
|
|
|
FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) {
|
|
return new Printer(OS);
|
|
}
|
|
|
|
const char *Printer::getPassName() const {
|
|
return "Print Garbage Collector Information";
|
|
}
|
|
|
|
void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
FunctionPass::getAnalysisUsage(AU);
|
|
AU.setPreservesAll();
|
|
AU.addRequired<GCModuleInfo>();
|
|
}
|
|
|
|
static const char *DescKind(GC::PointKind Kind) {
|
|
switch (Kind) {
|
|
case GC::Loop:
|
|
return "loop";
|
|
case GC::Return:
|
|
return "return";
|
|
case GC::PreCall:
|
|
return "pre-call";
|
|
case GC::PostCall:
|
|
return "post-call";
|
|
}
|
|
llvm_unreachable("Invalid point kind");
|
|
}
|
|
|
|
bool Printer::runOnFunction(Function &F) {
|
|
if (F.hasGC())
|
|
return false;
|
|
|
|
GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
|
|
|
|
OS << "GC roots for " << FD->getFunction().getName() << ":\n";
|
|
for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
|
|
RE = FD->roots_end();
|
|
RI != RE; ++RI)
|
|
OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
|
|
|
|
OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
|
|
for (GCFunctionInfo::iterator PI = FD->begin(), PE = FD->end(); PI != PE;
|
|
++PI) {
|
|
|
|
OS << "\t" << PI->Label->getName() << ": " << DescKind(PI->Kind)
|
|
<< ", live = {";
|
|
|
|
for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
|
|
RE = FD->live_end(PI);
|
|
;) {
|
|
OS << " " << RI->Num;
|
|
if (++RI == RE)
|
|
break;
|
|
OS << ",";
|
|
}
|
|
|
|
OS << " }\n";
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Printer::doFinalization(Module &M) {
|
|
GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
|
|
assert(GMI && "Printer didn't require GCModuleInfo?!");
|
|
GMI->clear();
|
|
return false;
|
|
}
|
|
|
|
|
|
GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
|
|
// TODO: Arguably, just doing a linear search would be faster for small N
|
|
auto NMI = GCStrategyMap.find(Name);
|
|
if (NMI != GCStrategyMap.end())
|
|
return NMI->getValue();
|
|
|
|
for (auto& Entry : GCRegistry::entries()) {
|
|
if (Name == Entry.getName()) {
|
|
std::unique_ptr<GCStrategy> S = Entry.instantiate();
|
|
S->Name = Name;
|
|
GCStrategyMap[Name] = S.get();
|
|
GCStrategyList.push_back(std::move(S));
|
|
return GCStrategyList.back().get();
|
|
}
|
|
}
|
|
|
|
report_fatal_error(std::string("unsupported GC: ") + Name);
|
|
}
|