blob: 5746dc53bfd3ace19a3f51da19018a80e66a3679 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
using namespace llvm;
static unsigned kGCAddressSpace = 1;
void MaybeStatepointFunction(Function* F) {
if (F->hasFnAttribute("statepoint")) {
if (F->hasFnAttribute("no-statepoint"))
return;
F->setGC("statepoint-example");
}
}
namespace {
struct RegisterGcFunctions : public ModulePass {
static char ID;
RegisterGcFunctions() : ModulePass(ID) {}
bool runOnModule(Module& M) override {
auto GA = M.getNamedGlobal("llvm.global.annotations");
if (GA) {
auto a = cast<ConstantArray>(GA->getOperand(0));
for (int i = 0; i < a->getNumOperands(); i++) {
auto e = cast<ConstantStruct>(a->getOperand(i));
if (auto F = dyn_cast<Function>(e->getOperand(0)->getOperand(0))) {
auto Anno = cast<ConstantDataArray>(
cast<GlobalVariable>(e->getOperand(1)->getOperand(0))
->getOperand(0))
->getAsCString();
F->addFnAttr(Anno);
}
}
}
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
MaybeStatepointFunction(&*F);
}
return false;
}
};
char RegisterGcFunctions::ID;
} // end of anonymous namespace
static RegisterPass<RegisterGcFunctions> X("register-gc-fns",
"Register GC Functions",
false /* Only looks at CFG */,
true /* Analysis Pass */);
static RegisterStandardPasses Y(PassManagerBuilder::EP_ModuleOptimizerEarly,
[](const PassManagerBuilder& Builder,
legacy::PassManagerBase& PM) {
PM.add(new RegisterGcFunctions());
});