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.

llvm-svn: 82082
This commit is contained in:
Fariborz Jahanian 2009-09-16 21:37:16 +00:00
parent ca968cf1f0
commit a7fa6beb2e
4 changed files with 124 additions and 6 deletions

View File

@ -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;

View File

@ -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<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
VD->isFileVarDecl())
LV.SetGlobalObjCRef(LV, true);
}
}
else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E))
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E))
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E))
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E))
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E))
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
}
}
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const VarDecl *VD = dyn_cast<VarDecl>(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<FunctionDecl>(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;
}

View File

@ -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;
}

View File

@ -371,6 +371,10 @@ static llvm::cl::opt<bool>
ObjCEnableGC("fobjc-gc",
llvm::cl::desc("Enable Objective-C garbage collection"));
static llvm::cl::opt<bool>
ObjCEnableNewGCAPI("fobjc-newgc-api",
llvm::cl::desc("Enable Objective-C garbage collection's new API"));
static llvm::cl::opt<bool>
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;