From 2ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Mon, 31 Oct 2011 23:58:51 +0000 Subject: [PATCH] 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 --- include/llvm/Transforms/Utils/ModuleUtils.h | 30 +++++++++++ lib/Transforms/Utils/CMakeLists.txt | 1 + lib/Transforms/Utils/ModuleUtils.cpp | 55 +++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 include/llvm/Transforms/Utils/ModuleUtils.h create mode 100644 lib/Transforms/Utils/ModuleUtils.cpp diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h new file mode 100644 index 00000000000..d7e12a61db6 --- /dev/null +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -0,0 +1,30 @@ +//===-- ModuleUtils.h - Functions to manipulate Modules ---------*- C++ -*-===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H +#define LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H + +namespace llvm { + +class Module; +class Function; + +/// Append F to the list of global ctors of module M with the given Priority. +/// This wraps the function in the appropriate structure and stores it along +/// side other global constructors. For details see +/// http://llvm.org/docs/LangRef.html#intg_global_ctors +void appendToGlobalCtors(Module &M, Function *F, int Priority); + +} // End llvm namespace + +#endif // LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H diff --git a/lib/Transforms/Utils/CMakeLists.txt b/lib/Transforms/Utils/CMakeLists.txt index 7adc5f1ac2e..6d5432d9632 100644 --- a/lib/Transforms/Utils/CMakeLists.txt +++ b/lib/Transforms/Utils/CMakeLists.txt @@ -18,6 +18,7 @@ add_llvm_library(LLVMTransformUtils LowerInvoke.cpp LowerSwitch.cpp Mem2Reg.cpp + ModuleUtils.cpp PromoteMemoryToRegister.cpp SSAUpdater.cpp SimplifyCFG.cpp diff --git a/lib/Transforms/Utils/ModuleUtils.cpp b/lib/Transforms/Utils/ModuleUtils.cpp new file mode 100644 index 00000000000..db81de7b1d8 --- /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"); +} -- 2.34.1