[cfe-commits] r54258 - in /cfe/trunk: include/clang/AST/Attr.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/constructor-attribute.c
Daniel Dunbar
daniel at zuster.org
Thu Jul 31 17:01:51 PDT 2008
Author: ddunbar
Date: Thu Jul 31 19:01:51 2008
New Revision: 54258
URL: http://llvm.org/viewvc/llvm-project?rev=54258&view=rev
Log:
Support constructor and destructor attributes in CodeGen
- There is an miscompilation issue remaining due to a poor
interaction between the delayed emission of static functions and
the emission of constructors, but that already existed prior to
this change.
Added:
cfe/trunk/test/CodeGen/constructor-attribute.c
Modified:
cfe/trunk/include/clang/AST/Attr.h
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=54258&r1=54257&r2=54258&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Thu Jul 31 19:01:51 2008
@@ -132,6 +132,8 @@
int priority;
public:
ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
+
+ int getPriority() const { return priority; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Constructor; }
@@ -142,6 +144,8 @@
int priority;
public:
DestructorAttr(int p) : Attr(Destructor), priority(p) {}
+
+ int getPriority() const { return priority; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Destructor; }
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=54258&r1=54257&r2=54258&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Jul 31 19:01:51 2008
@@ -53,7 +53,8 @@
llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction();
if (ObjCInitFunction)
AddGlobalCtor(ObjCInitFunction);
- EmitGlobalCtors();
+ EmitCtorList(GlobalCtors, "llvm.global_ctors");
+ EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
delete Runtime;
delete DebugInfo;
@@ -102,55 +103,48 @@
/// AddGlobalCtor - Add a function to the list that will be called before
/// main() runs.
-void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor) {
+void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
// TODO: Type coercion of void()* types.
- GlobalCtors.push_back(Ctor);
+ GlobalCtors.push_back(std::make_pair(Ctor, Priority));
}
-/// EmitGlobalCtors - Generates the array of contsturctor functions to be
-/// called on module load, if any have been registered with AddGlobalCtor.
-void CodeGenModule::EmitGlobalCtors() {
- if (GlobalCtors.empty()) return;
-
- // Get the type of @llvm.global_ctors
- std::vector<const llvm::Type*> CtorFields;
- CtorFields.push_back(llvm::IntegerType::get(32));
- // Constructor function type
- std::vector<const llvm::Type*> VoidArgs;
- llvm::FunctionType* CtorFuncTy =
- llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false);
-
- // i32, function type pair
- const llvm::Type *FPType = llvm::PointerType::getUnqual(CtorFuncTy);
+/// AddGlobalDtor - Add a function to the list that will be called
+/// when the module is unloaded.
+void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) {
+ // TODO: Type coercion of void()* types.
+ GlobalDtors.push_back(std::make_pair(Dtor, Priority));
+}
+
+void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
+ // Ctor function type is void()*.
+ llvm::FunctionType* CtorFTy =
+ llvm::FunctionType::get(llvm::Type::VoidTy,
+ std::vector<const llvm::Type*>(),
+ false);
+ llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
+
+ // Get the type of a ctor entry, { i32, void ()* }.
llvm::StructType* CtorStructTy =
- llvm::StructType::get(llvm::Type::Int32Ty, FPType, NULL);
- // Array of fields
- llvm::ArrayType* GlobalCtorsTy =
- llvm::ArrayType::get(CtorStructTy, GlobalCtors.size());
-
- // Define the global variable
- llvm::GlobalVariable *GlobalCtorsVal =
- new llvm::GlobalVariable(GlobalCtorsTy, false,
- llvm::GlobalValue::AppendingLinkage,
- (llvm::Constant*)0, "llvm.global_ctors",
- &TheModule);
+ llvm::StructType::get(llvm::Type::Int32Ty,
+ llvm::PointerType::getUnqual(CtorFTy), NULL);
- // Populate the array
- std::vector<llvm::Constant*> CtorValues;
- llvm::Constant *MagicNumber =
- llvm::ConstantInt::get(llvm::Type::Int32Ty, 65535, false);
- std::vector<llvm::Constant*> StructValues;
- for (std::vector<llvm::Constant*>::iterator I = GlobalCtors.begin(),
- E = GlobalCtors.end(); I != E; ++I) {
- StructValues.clear();
- StructValues.push_back(MagicNumber);
- StructValues.push_back(*I);
+ // Construct the constructor and destructor arrays.
+ std::vector<llvm::Constant*> Ctors;
+ for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+ std::vector<llvm::Constant*> S;
+ S.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, I->second, false));
+ S.push_back(llvm::ConstantExpr::getBitCast(I->first, CtorPFTy));
+ Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
+ }
- CtorValues.push_back(llvm::ConstantStruct::get(CtorStructTy, StructValues));
+ if (!Ctors.empty()) {
+ llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
+ new llvm::GlobalVariable(AT, false,
+ llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(AT, Ctors),
+ GlobalName,
+ &TheModule);
}
-
- GlobalCtorsVal->setInitializer(llvm::ConstantArray::get(GlobalCtorsTy,
- CtorValues));
}
void CodeGenModule::EmitAnnotations() {
@@ -796,6 +790,12 @@
} else {
llvm::Function *Fn = cast<llvm::Function>(Entry);
CodeGenFunction(*this).GenerateCode(D, Fn);
+
+ if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
+ AddGlobalCtor(Fn, CA->getPriority());
+ } else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
+ AddGlobalDtor(Fn, DA->getPriority());
+ }
}
}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=54258&r1=54257&r2=54258&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Jul 31 19:01:51 2008
@@ -54,6 +54,8 @@
/// CodeGenModule - This class organizes the cross-module state that is used
/// while generating LLVM code.
class CodeGenModule {
+ typedef std::vector< std::pair<llvm::Constant*, int> > CtorList;
+
ASTContext &Context;
const LangOptions &Features;
llvm::Module &TheModule;
@@ -80,7 +82,16 @@
/// which actually define something.
std::vector<const ValueDecl*> StaticDecls;
- std::vector<llvm::Constant*> GlobalCtors;
+ /// GlobalCtors - Store the list of global constructors and their
+ /// respective priorities to be emitted when the translation unit is
+ /// complete.
+ CtorList GlobalCtors;
+
+ /// GlobalDtors - Store the list of global destructors and their
+ /// respective priorities to be emitted when the translation unit is
+ /// complete.
+ CtorList GlobalDtors;
+
std::vector<llvm::Constant*> Annotations;
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
@@ -173,9 +184,17 @@
llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D);
void EmitGlobalFunctionDefinition(const FunctionDecl *D);
void EmitGlobalVarDefinition(const VarDecl *D);
+
+ // FIXME: Hardcoding priority here is gross.
+ void AddGlobalCtor(llvm::Function * Ctor, int Priority=65535);
+ void AddGlobalDtor(llvm::Function * Dtor, int Priority=65535);
+
+ /// EmitCtorList - Generates a global array of functions and
+ /// priorities using the given list and name. This array will have
+ /// appending linkage and is suitable for use as a LLVM constructor
+ /// or destructor array.
+ void EmitCtorList(const CtorList &Fns, const char *GlobalName);
- void AddGlobalCtor(llvm::Function * Ctor);
- void EmitGlobalCtors(void);
void EmitAnnotations(void);
void EmitStatics(void);
Added: cfe/trunk/test/CodeGen/constructor-attribute.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/constructor-attribute.c?rev=54258&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/constructor-attribute.c (added)
+++ cfe/trunk/test/CodeGen/constructor-attribute.c Thu Jul 31 19:01:51 2008
@@ -0,0 +1,20 @@
+// RUN: clang -emit-llvm -o %t %s &&
+// RUN: grep -e "global_ctors.*@A" %t &&
+// RUN: grep -e "global_dtors.*@B" %t
+
+#include <stdio.h>
+
+void A() __attribute__((constructor));
+void B() __attribute__((destructor));
+
+void A() {
+ printf("A\n");
+}
+
+void B() {
+ printf("B\n");
+}
+
+int main() {
+ return 0;
+}
More information about the cfe-commits
mailing list