mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 22:04:55 +00:00
0b8c9a80f2
into their new header subdirectory: include/llvm/IR. This matches the directory structure of lib, and begins to correct a long standing point of file layout clutter in LLVM. There are still more header files to move here, but I wanted to handle them in separate commits to make tracking what files make sense at each layer easier. The only really questionable files here are the target intrinsic tablegen files. But that's a battle I'd rather not fight today. I've updated both CMake and Makefile build systems (I think, and my tests think, but I may have missed something). I've also re-sorted the includes throughout the project. I'll be committing updates to Clang, DragonEgg, and Polly momentarily. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171366 91177308-0d34-0410-b5e6-96231b3b80d8
214 lines
5.6 KiB
C++
214 lines
5.6 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/GCStrategy.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/Passes.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;
|
|
void getAnalysisUsage(AnalysisUsage &AU) const;
|
|
|
|
bool runOnFunction(Function &F);
|
|
};
|
|
|
|
class Deleter : public FunctionPass {
|
|
static char ID;
|
|
|
|
public:
|
|
Deleter();
|
|
|
|
const char *getPassName() const;
|
|
void getAnalysisUsage(AnalysisUsage &AU) const;
|
|
|
|
bool runOnFunction(Function &F);
|
|
bool doFinalization(Module &M);
|
|
};
|
|
|
|
}
|
|
|
|
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());
|
|
}
|
|
|
|
GCModuleInfo::~GCModuleInfo() {
|
|
clear();
|
|
}
|
|
|
|
GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M,
|
|
const std::string &Name) {
|
|
strategy_map_type::iterator NMI = StrategyMap.find(Name);
|
|
if (NMI != StrategyMap.end())
|
|
return NMI->getValue();
|
|
|
|
for (GCRegistry::iterator I = GCRegistry::begin(),
|
|
E = GCRegistry::end(); I != E; ++I) {
|
|
if (Name == I->getName()) {
|
|
GCStrategy *S = I->instantiate();
|
|
S->M = M;
|
|
S->Name = Name;
|
|
StrategyMap.GetOrCreateValue(Name).setValue(S);
|
|
StrategyList.push_back(S);
|
|
return S;
|
|
}
|
|
}
|
|
|
|
dbgs() << "unsupported GC: " << Name << "\n";
|
|
llvm_unreachable(0);
|
|
}
|
|
|
|
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 = getOrCreateStrategy(F.getParent(), F.getGC());
|
|
GCFunctionInfo *GFI = S->insertFunctionInfo(F);
|
|
FInfoMap[&F] = GFI;
|
|
return *GFI;
|
|
}
|
|
|
|
void GCModuleInfo::clear() {
|
|
FInfoMap.clear();
|
|
StrategyMap.clear();
|
|
|
|
for (iterator I = begin(), E = end(); I != E; ++I)
|
|
delete *I;
|
|
StrategyList.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;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
char Deleter::ID = 0;
|
|
|
|
FunctionPass *llvm::createGCInfoDeleter() {
|
|
return new Deleter();
|
|
}
|
|
|
|
Deleter::Deleter() : FunctionPass(ID) {}
|
|
|
|
const char *Deleter::getPassName() const {
|
|
return "Delete Garbage Collector Information";
|
|
}
|
|
|
|
void Deleter::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.setPreservesAll();
|
|
AU.addRequired<GCModuleInfo>();
|
|
}
|
|
|
|
bool Deleter::runOnFunction(Function &MF) {
|
|
return false;
|
|
}
|
|
|
|
bool Deleter::doFinalization(Module &M) {
|
|
GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
|
|
assert(GMI && "Deleter didn't require GCModuleInfo?!");
|
|
GMI->clear();
|
|
return false;
|
|
}
|