From: Fariborz Jahanian Date: Wed, 16 Sep 2009 21:37:16 +0000 (+0000) Subject: Starting patch to generate more specific API for objc's X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b123ea395ee607de85161f84c6e78595946304a5;p=clang Starting patch to generate more specific API for objc's GC. Currently, new API will be generated under clang-cc's -fobjc-newgc-api flag which will eventually become the default. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82082 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index d4d3fe50eb..8f60b47f4c 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -88,6 +88,7 @@ public: unsigned ElideConstructors : 1; // Whether C++ copy constructors should be // elided if possible. + unsigned ObjCNewGCAPI : 1; // Generate objective-c's new GC API private: unsigned GC : 2; // Objective-C Garbage Collection modes. We // declare this enum as unsigned because MSVC @@ -146,6 +147,7 @@ public: OverflowChecking = 0; ObjCGCBitmapPrint = 0; + ObjCNewGCAPI = 0; InstantiationDepth = 99; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index f163c18552..4dc7c265bb 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -694,6 +694,37 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified()); } +// setObjCGCLValueClass - sets class of he lvalue for the purpose of +// generating write-barries API. It is currently a global, ivar, +// or neither. +static +void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) { + if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC || + !Ctx.getLangOptions().ObjCNewGCAPI) + return; + + if (const DeclRefExpr *Exp = dyn_cast(E)) { + if (const VarDecl *VD = dyn_cast(Exp->getDecl())) { + if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) || + VD->isFileVarDecl()) + LV.SetGlobalObjCRef(LV, true); + } + } + else if (const UnaryOperator *Exp = dyn_cast(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const ParenExpr *Exp = dyn_cast(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const ImplicitCastExpr *Exp = dyn_cast(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const CStyleCastExpr *Exp = dyn_cast(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const ArraySubscriptExpr *Exp = dyn_cast(E)) + setObjCGCLValueClass(Ctx, Exp->getBase(), LV); + else if (const MemberExpr *Exp = dyn_cast(E)) { + setObjCGCLValueClass(Ctx, Exp->getBase(), LV); + } +} + LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const VarDecl *VD = dyn_cast(E->getDecl()); @@ -729,6 +760,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { E->getType().getAddressSpace()); } LValue::SetObjCNonGC(LV, NonGCable); + setObjCGCLValueClass(getContext(), E, LV); return LV; } else if (VD && VD->isFileVarDecl()) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); @@ -737,7 +769,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), getContext().getObjCGCAttrKind(E->getType()), E->getType().getAddressSpace()); - LV.SetGlobalObjCRef(LV, true); + setObjCGCLValueClass(getContext(), E, LV); return LV; } else if (const FunctionDecl *FD = dyn_cast(E->getDecl())) { llvm::Value* V = CGM.GetAddrOfFunction(FD); @@ -937,8 +969,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { getContext().getObjCGCAttrKind(T), E->getBase()->getType().getAddressSpace()); if (getContext().getLangOptions().ObjC1 && - getContext().getLangOptions().getGCMode() != LangOptions::NonGC) + getContext().getLangOptions().getGCMode() != LangOptions::NonGC) { LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext())); + setObjCGCLValueClass(getContext(), E, LV); + } return LV; } @@ -1042,6 +1076,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { CVRQualifiers); LValue::SetObjCIvar(MemExpLV, isIvar); LValue::SetObjCNonGC(MemExpLV, isNonGC); + setObjCGCLValueClass(getContext(), E, MemExpLV); return MemExpLV; } diff --git a/test/CodeGenObjC/objc2-assign-global.m b/test/CodeGenObjC/objc2-assign-global.m index ae40761909..426b99fde1 100644 --- a/test/CodeGenObjC/objc2-assign-global.m +++ b/test/CodeGenObjC/objc2-assign-global.m @@ -1,8 +1,82 @@ -// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s && -// RUN: grep -F '@objc_assign_global' %t | count 2 && +// RUN: clang-cc -fnext-runtime -fobjc-gc -fobjc-newgc-api -emit-llvm -o %t %s && +// RUN: grep -F '@objc_assign_global' %t | count 26 && // RUN: true -id a; + +@class NSObject; +typedef const struct __CFDictionary * CFDictionaryRef; +typedef struct { + id element; + id elementArray[10]; + __strong CFDictionaryRef cfElement; + __strong CFDictionaryRef cfElementArray[10]; +} struct_with_ids_t; + + +// assignments to these should generate objc_assign_global +@interface A +@end + +typedef struct s0 { + A *a[4]; +} T; + +T g0; + +extern id FileExternID; +static id FileStaticID; +id GlobalId; +id GlobalArray[20]; +NSObject *GlobalObject; +NSObject *GlobalObjectArray[20]; +__strong CFDictionaryRef Gdict; +__strong CFDictionaryRef Gdictarray[10]; +struct_with_ids_t GlobalStruct; +struct_with_ids_t GlobalStructArray[10]; + +#define ASSIGNTEST(expr, global) expr = rhs +void *rhs = 0; + int main() { - a = 0; + static id staticGlobalId; + static id staticGlobalArray[20]; + static NSObject *staticGlobalObject; + static NSObject *staticGlobalObjectArray[20]; + static __strong CFDictionaryRef staticGdict; + static __strong CFDictionaryRef staticGdictarray[10]; + static struct_with_ids_t staticGlobalStruct; + static struct_with_ids_t staticGlobalStructArray[10]; + extern id ExID; + id localID; + + ASSIGNTEST(GlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(GlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + ExID = 0; + localID = 0; + FileStaticID = 0; + FileExternID=0; + g0.a[0] = 0; + ((T*) &g0)->a[0] = 0; } diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 3c451c8c0d..31aeb74049 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -371,6 +371,10 @@ static llvm::cl::opt ObjCEnableGC("fobjc-gc", llvm::cl::desc("Enable Objective-C garbage collection")); +static llvm::cl::opt +ObjCEnableNewGCAPI("fobjc-newgc-api", + llvm::cl::desc("Enable Objective-C garbage collection's new API")); + static llvm::cl::opt ObjCEnableGCBitmapPrint("print-ivar-layout", llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace")); @@ -508,6 +512,9 @@ static void InitializeLangOptions(LangOptions &Options, LangKind LK){ else if (ObjCEnableGC) Options.setGCMode(LangOptions::HybridGC); + if (ObjCEnableNewGCAPI) + Options.ObjCNewGCAPI = 1; + if (ObjCEnableGCBitmapPrint) Options.ObjCGCBitmapPrint = 1;