From: Fariborz Jahanian Date: Tue, 3 Feb 2009 00:09:52 +0000 (+0000) Subject: objc2's ir-gen for nonfragile ivar access. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45012a7ef5abf1042c893f3f2fa5c23cb5485ea9;p=clang objc2's ir-gen for nonfragile ivar access. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63578 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2c16c1940b..4f8bd46b52 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1020,7 +1020,8 @@ llvm::Value *CodeGenFunction::EmitIvarOffset(ObjCInterfaceDecl *Interface, Offset); } -LValue CodeGenFunction::EmitLValueForIvar(llvm::Value *BaseValue, +LValue CodeGenFunction::EmitLValueForIvar(QualType ObjectTy, + llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, unsigned CVRQualifiers) { @@ -1035,6 +1036,7 @@ LValue CodeGenFunction::EmitLValueForIvar(llvm::Value *BaseValue, CVRQualifiers, Index); } llvm::Value *V = CGM.getObjCRuntime().EmitObjCValueForIvar(*this, + ObjectTy, BaseValue, Ivar, Field, CVRQualifiers); LValue LV = LValue::MakeAddr(V, Ivar->getType().getCVRQualifiers()|CVRQualifiers); SetVarDeclObjCAttribute(getContext(), Ivar, Ivar->getType(), LV); @@ -1047,19 +1049,22 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { llvm::Value *BaseValue = 0; const Expr *BaseExpr = E->getBase(); unsigned CVRQualifiers = 0; + QualType ObjectTy; if (E->isArrow()) { BaseValue = EmitScalarExpr(BaseExpr); const PointerType *PTy = cast(getContext().getCanonicalType(BaseExpr->getType())); - CVRQualifiers = PTy->getPointeeType().getCVRQualifiers(); + ObjectTy = PTy->getPointeeType(); + CVRQualifiers = ObjectTy.getCVRQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); // FIXME: this isn't right for bitfields. BaseValue = BaseLV.getAddress(); - CVRQualifiers = BaseExpr->getType().getCVRQualifiers(); + ObjectTy = BaseExpr->getType(); + CVRQualifiers = ObjectTy.getCVRQualifiers(); } - return EmitLValueForIvar(BaseValue, E->getDecl(), + return EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), getContext().getFieldDecl(E), CVRQualifiers); } diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 9dc45efc68..3ebee12f0d 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -194,7 +194,8 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, } else { FieldDecl *Field = IMP->getClassInterface()->lookupFieldDeclForIvar(getContext(), Ivar); - LValue LV = EmitLValueForIvar(LoadObjCSelf(), Ivar, Field, 0); + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), + LoadObjCSelf(), Ivar, Field, 0); if (hasAggregateLLVMType(Ivar->getType())) { EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); } @@ -294,6 +295,14 @@ llvm::Value *CodeGenFunction::LoadObjCSelf() { return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); } +QualType CodeGenFunction::TypeOfSelfObject() { + const ObjCMethodDecl *OMD = cast(CurFuncDecl); + ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); + const PointerType *PTy = + cast(getContext().getCanonicalType(selfDecl->getType())); + return PTy->getPointeeType(); +} + RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { // FIXME: Split it into two separate routines. if (const ObjCPropertyRefExpr *E = dyn_cast(Exp)) { diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 1ce28bf91d..d3b57b0e9a 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -141,6 +141,7 @@ public: virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, @@ -1037,6 +1038,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, } llvm::Value *CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index a577bd03cb..2b1d9fff0b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -551,6 +551,7 @@ private: llvm::Value *src, llvm::Value *dest); virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, @@ -676,12 +677,11 @@ public: llvm::Value *src, llvm::Value *dest) { return; } virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, - unsigned CVRQualifiers) - { return 0; } - + unsigned CVRQualifiers); }; } // end anonymous namespace @@ -2114,6 +2114,7 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, /// EmitObjCValueForIvar - Code Gen for ivar reference. /// llvm::Value *CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, @@ -3755,15 +3756,16 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( std::string ExternalName("\01_OBJC_IVAR_$_" + ID->getNameAsString() + '.' + Ivar->getNameAsString()); - llvm::Constant *Init = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset); + llvm::Constant *Init = llvm::ConstantInt::get(ObjCTypes.LongTy, Offset); llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(ExternalName); if (IvarOffsetGV) { // ivar offset symbol already built due to user code referencing it. IvarOffsetGV->setAlignment( - CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.Int8PtrTy)); + CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); IvarOffsetGV->setInitializer(Init); + IvarOffsetGV->setSection("__DATA, __objc_const"); UsedGlobals.push_back(IvarOffsetGV); return IvarOffsetGV; } @@ -3776,7 +3778,7 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( ExternalName, &CGM.getModule()); IvarOffsetGV->setAlignment( - CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.Int8PtrTy)); + CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); // @private and @package have hidden visibility. bool globalVisibility = (Ivar->getAccessControl() == ObjCIvarDecl::Public || Ivar->getAccessControl() == ObjCIvarDecl::Protected); @@ -3789,10 +3791,7 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( IvarOffsetGV->setSection("__DATA, __objc_const"); UsedGlobals.push_back(IvarOffsetGV); - - return llvm::ConstantExpr::getBitCast( - IvarOffsetGV, - llvm::PointerType::getUnqual(ObjCTypes.LongTy)); + return IvarOffsetGV; } /// EmitIvarList - Emit the ivar list for the given @@ -4094,6 +4093,52 @@ CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); } + +/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. +/// This code gen. amounts to generating code for: +/// @code +/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; +/// @encode +/// +llvm::Value *CGObjCNonFragileABIMac::EmitObjCValueForIvar( + CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, + llvm::Value *BaseValue, + const ObjCIvarDecl *Ivar, + const FieldDecl *Field, + unsigned CVRQualifiers) { + assert(ObjectTy->isObjCInterfaceType() && + "CGObjCNonFragileABIMac::EmitObjCValueForIvar"); + NamedDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl(); + // NOTE. This name must match one in EmitIvarOffsetVar. + // FIXME. Consolidate into one naming routine. + std::string ExternalName("\01_OBJC_IVAR_$_" + ID->getNameAsString() + '.' + + Ivar->getNameAsString()); + + llvm::GlobalVariable *IvarOffsetGV = + CGM.getModule().getGlobalVariable(ExternalName); + if (!IvarOffsetGV) + IvarOffsetGV = + new llvm::GlobalVariable(ObjCTypes.LongTy, + false, + llvm::GlobalValue::ExternalLinkage, + 0, + ExternalName, + &CGM.getModule()); + // (char *) BaseValue + llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, + ObjCTypes.Int8PtrTy); + llvm::Value *Offset = CGF.Builder.CreateLoad(IvarOffsetGV); + // (char*)BaseValue + Offset_symbol + V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); + // (type *)((char*)BaseValue + Offset_symbol) + const llvm::Type *IvarTy = + CGM.getTypes().ConvertType(Ivar->getType()); + llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy); + V = CGF.Builder.CreateBitCast(V, ptrIvarTy); + return V; +} + /* *** */ CodeGen::CGObjCRuntime * diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index ded1db2c0b..ade77af156 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -158,6 +158,7 @@ public: llvm::Value *src, llvm::Value *dest) = 0; virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, const FieldDecl *Field, diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 9033a65be2..75353a7d98 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -233,6 +233,10 @@ public: /// LoadObjCSelf - Load the value of self. This function is only /// valid while generating code for an Objective-C method. llvm::Value *LoadObjCSelf(); + + /// TypeOfSelfObject + /// Return type of object that this self represents. + QualType TypeOfSelfObject(); /// isObjCPointerType - Return true if the specificed AST type will map onto /// some Objective-C pointer type. @@ -521,7 +525,8 @@ public: const ObjCIvarDecl *Ivar); LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field, bool isUnion, unsigned CVRQualifiers); - LValue EmitLValueForIvar(llvm::Value* Base, const ObjCIvarDecl *Ivar, + LValue EmitLValueForIvar(QualType ObjectTy, + llvm::Value* Base, const ObjCIvarDecl *Ivar, const FieldDecl *Field, unsigned CVRQualifiers);