blob: eee4169c5a60b864564ceb322a5812b68fd6985a [file] [log] [blame]
//===- RegisterRuntimeInitializer.cpp ---------------------------*- C++ -*----//
//
// The SAFECode Compiler
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Pass to register runtime initialization calls into user-space programs.
//
//===----------------------------------------------------------------------===//
#include "safecode/InsertChecks/RegisterRuntimeInitializer.h"
#include "safecode/SAFECodeConfig.h"
#include "llvm/Constants.h"
#include "llvm/LLVMContext.h"
using namespace llvm;
NAMESPACE_SC_BEGIN
char RegisterRuntimeInitializer::ID = 0;
static llvm::RegisterPass<RegisterRuntimeInitializer> X1 ("reg-runtime-init", "Register runtime initializer into programs");
bool
RegisterRuntimeInitializer::runOnModule(llvm::Module & M) {
intrinsic = &getAnalysis<InsertSCIntrinsic>();
constructInitializer(M);
insertInitializerIntoGlobalCtorList(M);
return true;
}
void
RegisterRuntimeInitializer::constructInitializer(llvm::Module & M) {
//
// Create a new function with zero arguments. This will be the SAFECode
// run-time constructor; it will be called by static global variable
// constructor magic before main() is called.
//
Function * RuntimeCtor = intrinsic->getIntrinsic("sc.init_runtime").F;
Function * RuntimeInit = intrinsic->getIntrinsic("sc.init_pool_runtime").F;
Function * RegGlobals = intrinsic->getIntrinsic("sc.register_globals").F;
// Function * PoolInit = M.getFunction("poolalloc.init");
// Make the runtime constructor compatible with other ctors
RuntimeCtor->setDoesNotThrow();
RuntimeCtor->setLinkage(GlobalValue::InternalLinkage);
//
// Add a call in the new constructor function to the SAFECode initialization
// function.
//
BasicBlock * BB = BasicBlock::Create (getGlobalContext(), "entry", RuntimeCtor);
// Delegate the responbilities of initializing pool descriptor to the
// SAFECode runtime initializer
// CallInst::Create (PoolInit, "", BB);
const Type * Int32Type = IntegerType::getInt32Ty(getGlobalContext());
std::vector<Value *> args;
if (SCConfig.dpChecks())
args.push_back (ConstantInt::get(Int32Type, 1));
else
args.push_back (ConstantInt::get(Int32Type, 0));
args.push_back (ConstantInt::get(Int32Type, SCConfig.rewriteOOB()));
args.push_back (ConstantInt::get(Int32Type, SCConfig.terminateOnErrors()));
CallInst::Create (RuntimeInit, args.begin(), args.end(), "", BB);
args.clear();
CallInst::Create (RegGlobals, args.begin(), args.end(), "", BB);
//
// Add a return instruction at the end of the basic block.
//
ReturnInst::Create (getGlobalContext(), BB);
}
void
RegisterRuntimeInitializer::insertInitializerIntoGlobalCtorList(Module & M) {
Function * RuntimeCtor = intrinsic->getIntrinsic("sc.init_runtime").F;
//
// Insert the run-time ctor into the ctor list.
//
const Type * Int32Type = IntegerType::getInt32Ty(getGlobalContext());
std::vector<Constant *> CtorInits;
CtorInits.push_back (ConstantInt::get (Int32Type, 65535));
CtorInits.push_back (RuntimeCtor);
Constant * RuntimeCtorInit=ConstantStruct::get(getGlobalContext(),CtorInits, false);
//
// Get the current set of static global constructors and add the new ctor
// to the end of the list (the list seems to be initialized in reverse
// order).
//
std::vector<Constant *> CurrentCtors;
GlobalVariable * GVCtor = M.getNamedGlobal ("llvm.global_ctors");
if (GVCtor) {
if (Constant * C = GVCtor->getInitializer()) {
for (unsigned index = 0; index < C->getNumOperands(); ++index) {
CurrentCtors.push_back (cast<Constant>(C->getOperand (index)));
}
}
//
// Rename the global variable so that we can name our global
// llvm.global_ctors.
//
GVCtor->setName ("removed");
}
CurrentCtors.push_back (RuntimeCtorInit);
//
// Create a new initializer.
//
const ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(),
CurrentCtors.size());
Constant * NewInit=ConstantArray::get (AT, CurrentCtors);
//
// Create the new llvm.global_ctors global variable and replace all uses of
// the old global variable with the new one.
//
new GlobalVariable (M,
NewInit->getType(),
false,
GlobalValue::AppendingLinkage,
NewInit,
"llvm.global_ctors");
}
NAMESPACE_SC_END