From 48f4e5752e202ad5f32b17de36f2b6c04843e896 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Jan 2012 21:19:38 +0000 Subject: [PATCH] Use llvm.global_ctors to locate global constructors instead of recognizing them by name. llvm-svn: 148416 --- lib/Transforms/Scalar/ObjCARC.cpp | 25 +++++++++++++++++++------ test/Transforms/ObjCARC/apelim.ll | 2 ++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp index 87df83857b1..a01676ab65b 100644 --- a/lib/Transforms/Scalar/ObjCARC.cpp +++ b/lib/Transforms/Scalar/ObjCARC.cpp @@ -887,6 +887,8 @@ bool ObjCARCExpand::runOnFunction(Function &F) { // ARC autorelease pool elimination. //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" + namespace { /// ObjCARCAPElim - Autorelease pool elimination. class ObjCARCAPElim : public ModulePass { @@ -978,17 +980,28 @@ bool ObjCARCAPElim::runOnModule(Module &M) { if (!ModuleHasARC(M)) return false; + // Find the llvm.global_ctors variable, as the first step in + // identifying the global constructors. + GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); + if (!GV) + return false; + + assert(GV->hasDefinitiveInitializer() && + "llvm.global_ctors is uncooperative!"); + bool Changed = false; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - Function *F = I; + // Dig the constructor functions out of GV's initializer. + ConstantArray *Init = cast(GV->getInitializer()); + for (User::op_iterator OI = Init->op_begin(), OE = Init->op_end(); + OI != OE; ++OI) { + Value *Op = *OI; + // llvm.global_ctors is an array of pairs where the second members + // are constructor functions. + Function *F = cast(cast(Op)->getOperand(1)); // Only look at function definitions. if (F->isDeclaration()) continue; - // Only look at global constructor functions. Unfortunately, - // the name is the most convenient way to recognize them. - if (!F->getName().startswith("_GLOBAL__I_")) - continue; // Only look at functions with one basic block. if (llvm::next(F->begin()) != F->end()) continue; diff --git a/test/Transforms/ObjCARC/apelim.ll b/test/Transforms/ObjCARC/apelim.ll index 5fefe53551c..8c7b5b1e654 100644 --- a/test/Transforms/ObjCARC/apelim.ll +++ b/test/Transforms/ObjCARC/apelim.ll @@ -1,6 +1,8 @@ ; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s ; rdar://10227311 +@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }] + @x = global i32 0 declare i32 @bar() nounwind