From c3260988a8d234bd32d6fd4f121df783eb290d9a Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Mon, 31 Oct 2011 23:58:51 +0000 Subject: Add utility to append a function to the list of global constructors. Patch by Kostya Serebryany. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143405 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/ModuleUtils.cpp | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 lib/Transforms/Utils/ModuleUtils.cpp (limited to 'lib/Transforms/Utils/ModuleUtils.cpp') diff --git a/lib/Transforms/Utils/ModuleUtils.cpp b/lib/Transforms/Utils/ModuleUtils.cpp new file mode 100644 index 0000000000..db81de7b1d --- /dev/null +++ b/lib/Transforms/Utils/ModuleUtils.cpp @@ -0,0 +1,55 @@ +//===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform manipulations on Modules. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" +using namespace llvm; + +void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { + IRBuilder<> IRB(M.getContext()); + FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); + StructType *Ty = StructType::get( + IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL); + + Constant *RuntimeCtorInit = ConstantStruct::get( + Ty, IRB.getInt32(Priority), F, NULL); + + // Get the current set of static global constructors and add the new ctor + // to the list. + SmallVector CurrentCtors; + if (GlobalVariable * GVCtor = M.getNamedGlobal("llvm.global_ctors")) { + if (Constant *Init = GVCtor->getInitializer()) { + unsigned n = Init->getNumOperands(); + CurrentCtors.reserve(n + 1); + for (unsigned i = 0; i != n; ++i) + CurrentCtors.push_back(cast(Init->getOperand(i))); + } + GVCtor->eraseFromParent(); + } + + CurrentCtors.push_back(RuntimeCtorInit); + + // Create a new initializer. + ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(), + CurrentCtors.size()); + Constant *NewInit = ConstantArray::get(AT, CurrentCtors); + + // Create the new global variable and replace all uses of + // the old global variable with the new one. + (void)new GlobalVariable(M, NewInit->getType(), false, + GlobalValue::AppendingLinkage, NewInit, + "llvm.global_ctors"); +} -- cgit v1.2.3