Objective-c armv7 API for atomic properties of

scalar types. // rdar://7761305

llvm-svn: 125946
This commit is contained in:
Fariborz Jahanian 2011-02-18 19:15:13 +00:00
parent a1bf8db478
commit 302a3d4e4d
3 changed files with 152 additions and 97 deletions

View File

@ -143,6 +143,44 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart());
}
void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar,
bool IsAtomic, bool IsStrong) {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
llvm::Value *GetCopyStructFn =
CGM.getObjCRuntime().GetGetStructFunction();
CodeGenTypes &Types = CGM.getTypes();
// objc_copyStruct (ReturnValue, &structIvar,
// sizeof (Type of Ivar), isAtomic, false);
CallArgList Args;
RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue,
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
// sizeof (Type of Ivar)
CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
llvm::Value *SizeVal =
llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
Size.getQuantity());
Args.push_back(std::make_pair(RValue::get(SizeVal),
getContext().LongTy));
llvm::Value *isAtomic =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
IsAtomic ? 1 : 0);
Args.push_back(std::make_pair(RValue::get(isAtomic),
getContext().BoolTy));
llvm::Value *hasStrong =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
IsStrong ? 1 : 0);
Args.push_back(std::make_pair(RValue::get(hasStrong),
getContext().BoolTy));
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
FunctionType::ExtInfo()),
GetCopyStructFn, ReturnValueSlot(), Args);
}
/// Generate an Objective-C method. An Objective-C method is a C function with
/// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
@ -214,52 +252,30 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType());
} else {
if (Ivar->getType()->isAnyComplexType()) {
const llvm::Triple &Triple = getContext().Target.getTriple();
QualType IVART = Ivar->getType();
if (IsAtomic &&
IVART->isScalarType() &&
(Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb) &&
(getContext().getTypeSizeInChars(IVART)
> CharUnits::fromQuantity(4)) &&
CGM.getObjCRuntime().GetGetStructFunction()) {
GenerateObjCGetterBody(Ivar, true, false);
}
else if (IVART->isAnyComplexType()) {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(),
LV.isVolatileQualified());
StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
}
else if (hasAggregateLLVMType(Ivar->getType())) {
else if (hasAggregateLLVMType(IVART)) {
bool IsStrong = false;
if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType())))
if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(IVART)))
&& CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
&& CGM.getObjCRuntime().GetGetStructFunction()) {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
llvm::Value *GetCopyStructFn =
CGM.getObjCRuntime().GetGetStructFunction();
CodeGenTypes &Types = CGM.getTypes();
// objc_copyStruct (ReturnValue, &structIvar,
// sizeof (Type of Ivar), isAtomic, false);
CallArgList Args;
RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue,
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
// sizeof (Type of Ivar)
CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
llvm::Value *SizeVal =
llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
Size.getQuantity());
Args.push_back(std::make_pair(RValue::get(SizeVal),
getContext().LongTy));
llvm::Value *isAtomic =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
IsAtomic ? 1 : 0);
Args.push_back(std::make_pair(RValue::get(isAtomic),
getContext().BoolTy));
llvm::Value *hasStrong =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
IsStrong ? 1 : 0);
Args.push_back(std::make_pair(RValue::get(hasStrong),
getContext().BoolTy));
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
FunctionType::ExtInfo()),
GetCopyStructFn, ReturnValueSlot(), Args);
GenerateObjCGetterBody(Ivar, IsAtomic, IsStrong);
}
else {
if (PID->getGetterCXXConstructor()) {
@ -272,23 +288,61 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
else {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
EmitAggregateCopy(ReturnValue, LV.getAddress(), IVART);
}
}
} else {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
}
else {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
CodeGenTypes &Types = CGM.getTypes();
RValue RV = EmitLoadOfLValue(LV, Ivar->getType());
RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType());
CodeGenTypes &Types = CGM.getTypes();
RValue RV = EmitLoadOfLValue(LV, IVART);
RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType());
}
}
FinishFunction();
}
void CodeGenFunction::GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD,
ObjCIvarDecl *Ivar) {
// objc_copyStruct (&structIvar, &Arg,
// sizeof (struct something), true, false);
llvm::Value *GetCopyStructFn =
CGM.getObjCRuntime().GetSetStructFunction();
CodeGenTypes &Types = CGM.getTypes();
CallArgList Args;
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
RValue RV =
RValue::get(Builder.CreateBitCast(LV.getAddress(),
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
llvm::Value *ArgAsPtrTy =
Builder.CreateBitCast(Arg,
Types.ConvertType(getContext().VoidPtrTy));
RV = RValue::get(ArgAsPtrTy);
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
// sizeof (Type of Ivar)
CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
llvm::Value *SizeVal =
llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
Size.getQuantity());
Args.push_back(std::make_pair(RValue::get(SizeVal),
getContext().LongTy));
llvm::Value *True =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
llvm::Value *False =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
FunctionType::ExtInfo()),
GetCopyStructFn, ReturnValueSlot(), Args);
}
/// GenerateObjCSetter - Generate an Objective-C property setter
/// function. The given Decl must be an ObjCImplementationDecl. @synthesize
/// is illegal within a category.
@ -360,62 +414,46 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
&& CGM.getObjCRuntime().GetSetStructFunction()) {
// objc_copyStruct (&structIvar, &Arg,
// sizeof (struct something), true, false);
llvm::Value *GetCopyStructFn =
CGM.getObjCRuntime().GetSetStructFunction();
CodeGenTypes &Types = CGM.getTypes();
CallArgList Args;
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
Types.ConvertType(getContext().VoidPtrTy)));
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
llvm::Value *ArgAsPtrTy =
Builder.CreateBitCast(Arg,
Types.ConvertType(getContext().VoidPtrTy));
RV = RValue::get(ArgAsPtrTy);
Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
// sizeof (Type of Ivar)
CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
llvm::Value *SizeVal =
llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
Size.getQuantity());
Args.push_back(std::make_pair(RValue::get(SizeVal),
getContext().LongTy));
llvm::Value *True =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
llvm::Value *False =
llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
FunctionType::ExtInfo()),
GetCopyStructFn, ReturnValueSlot(), Args);
GenerateObjCAtomicSetterBody(OMD, Ivar);
} else if (PID->getSetterCXXAssignment()) {
EmitIgnoredExpr(PID->getSetterCXXAssignment());
} else {
// FIXME: Find a clean way to avoid AST node creation.
SourceLocation Loc = PD->getLocation();
ValueDecl *Self = OMD->getSelfDecl();
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc);
ParmVarDecl *ArgDecl = *OMD->param_begin();
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc);
ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
const llvm::Triple &Triple = getContext().Target.getTriple();
QualType IVART = Ivar->getType();
if (IsAtomic &&
IVART->isScalarType() &&
(Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb) &&
(getContext().getTypeSizeInChars(IVART)
> CharUnits::fromQuantity(4)) &&
CGM.getObjCRuntime().GetGetStructFunction()) {
GenerateObjCAtomicSetterBody(OMD, Ivar);
}
else {
// FIXME: Find a clean way to avoid AST node creation.
SourceLocation Loc = PD->getLocation();
ValueDecl *Self = OMD->getSelfDecl();
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc);
ParmVarDecl *ArgDecl = *OMD->param_begin();
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc);
ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
// The property type can differ from the ivar type in some situations with
// Objective-C pointer types, we can always bit cast the RHS in these cases.
if (getContext().getCanonicalType(Ivar->getType()) !=
getContext().getCanonicalType(ArgDecl->getType())) {
ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
Ivar->getType(), CK_BitCast, &Arg,
VK_RValue);
BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign);
} else {
BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign);
// The property type can differ from the ivar type in some situations with
// Objective-C pointer types, we can always bit cast the RHS in these cases.
if (getContext().getCanonicalType(Ivar->getType()) !=
getContext().getCanonicalType(ArgDecl->getType())) {
ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
Ivar->getType(), CK_BitCast, &Arg,
VK_RValue);
BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign);
} else {
BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign);
}
}
}

View File

@ -1069,6 +1069,10 @@ public:
/// GenerateObjCGetter - Synthesize an Objective-C property getter function.
void GenerateObjCGetter(ObjCImplementationDecl *IMP,
const ObjCPropertyImplDecl *PID);
void GenerateObjCGetterBody(ObjCIvarDecl *Ivar, bool IsAtomic, bool IsStrong);
void GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD,
ObjCIvarDecl *Ivar);
void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
ObjCMethodDecl *MD, bool ctor);

View File

@ -0,0 +1,13 @@
// RUN: %clang_cc1 -triple armv7-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ARM %s
// rdar://7761305
@interface I
@property long long LONG_PROP;
@end
@implementation I
@synthesize LONG_PROP;
@end
// CHECK-ARM: call arm_aapcscc void @objc_copyStruct(i8* %{{.*}}, i8* %{{.*}}, i32 8, i1 zeroext true, i1 zeroext false)
// CHECK-ARM: call arm_aapcscc void @objc_copyStruct(i8* %{{.*}}, i8* %{{.*}}, i32 8, i1 zeroext true, i1 zeroext false)