blob: cdba82fe0f1e3b20e1bb7b9bc0c7f8b490a04226 [file] [log] [blame]
//===---- StaticGCPass.cpp - Put GC information in functions compiled --------//
//===----------------------- with llvm-gcc --------------------------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
using namespace llvm;
namespace {
class StaticGCPass : public ModulePass {
public:
static char ID;
StaticGCPass() : ModulePass(ID) {}
virtual bool runOnModule(Module& M);
/// getAnalysisUsage - We do not modify anything.
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
};
char StaticGCPass::ID = 0;
RegisterPass<StaticGCPass> X("StaticGCPass",
"Add GC information in files compiled with llvm-gcc");
bool StaticGCPass::runOnModule(Module& M) {
Function* F = M.getFunction("__llvm_gcroot");
Function *gcrootFun = Intrinsic::getDeclaration(&M, Intrinsic::gcroot);
if (F) {
F->replaceAllUsesWith(gcrootFun);
F->eraseFromParent();
}
bool error = false;
for (Value::use_iterator I = gcrootFun->use_begin(),
E = gcrootFun->use_end(); I != E; ++I) {
if (Instruction* II = dyn_cast<Instruction>(*I)) {
Function* F = II->getParent()->getParent();
if (!F->hasGC()) {
F->setGC("vmkit");
}
}
}
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (I->hasGC() && I->hasInternalLinkage()) {
error = true;
fprintf(stderr, "Method %s has static linkage but uses gc_root. "
"Functions using gc_root should not have static linkage.\n",
I->getName().data());
}
}
if (error) abort();
return true;
}
}