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()); 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 /// Generate an Objective-C method. An Objective-C method is a C function with
/// its pointer, name, and types registered in the class struture. /// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
@ -214,52 +252,30 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
Types.ConvertType(PD->getType()))); Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType()); EmitReturnOfRValue(RV, PD->getType());
} else { } 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(), LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0); Ivar, 0);
ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(),
LV.isVolatileQualified()); LV.isVolatileQualified());
StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
} }
else if (hasAggregateLLVMType(Ivar->getType())) { else if (hasAggregateLLVMType(IVART)) {
bool IsStrong = false; bool IsStrong = false;
if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType()))) if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(IVART)))
&& CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
&& CGM.getObjCRuntime().GetGetStructFunction()) { && CGM.getObjCRuntime().GetGetStructFunction()) {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), GenerateObjCGetterBody(Ivar, IsAtomic, IsStrong);
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);
} }
else { else {
if (PID->getGetterCXXConstructor()) { if (PID->getGetterCXXConstructor()) {
@ -272,23 +288,61 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
else { else {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0); 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); Ivar, 0);
CodeGenTypes &Types = CGM.getTypes(); CodeGenTypes &Types = CGM.getTypes();
RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); RValue RV = EmitLoadOfLValue(LV, IVART);
RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
Types.ConvertType(PD->getType()))); Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType()); EmitReturnOfRValue(RV, PD->getType());
} }
} }
FinishFunction(); 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 /// GenerateObjCSetter - Generate an Objective-C property setter
/// function. The given Decl must be an ObjCImplementationDecl. @synthesize /// function. The given Decl must be an ObjCImplementationDecl. @synthesize
/// is illegal within a category. /// is illegal within a category.
@ -360,62 +414,46 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
&& CGM.getObjCRuntime().GetSetStructFunction()) { && CGM.getObjCRuntime().GetSetStructFunction()) {
// objc_copyStruct (&structIvar, &Arg, // objc_copyStruct (&structIvar, &Arg,
// sizeof (struct something), true, false); // sizeof (struct something), true, false);
llvm::Value *GetCopyStructFn = GenerateObjCAtomicSetterBody(OMD, Ivar);
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);
} else if (PID->getSetterCXXAssignment()) { } else if (PID->getSetterCXXAssignment()) {
EmitIgnoredExpr(PID->getSetterCXXAssignment()); EmitIgnoredExpr(PID->getSetterCXXAssignment());
} else { } else {
// FIXME: Find a clean way to avoid AST node creation. const llvm::Triple &Triple = getContext().Target.getTriple();
SourceLocation Loc = PD->getLocation(); QualType IVART = Ivar->getType();
ValueDecl *Self = OMD->getSelfDecl(); if (IsAtomic &&
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); IVART->isScalarType() &&
DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc); (Triple.getArch() == llvm::Triple::arm ||
ParmVarDecl *ArgDecl = *OMD->param_begin(); Triple.getArch() == llvm::Triple::thumb) &&
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc); (getContext().getTypeSizeInChars(IVART)
ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); > 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 // 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. // Objective-C pointer types, we can always bit cast the RHS in these cases.
if (getContext().getCanonicalType(Ivar->getType()) != if (getContext().getCanonicalType(Ivar->getType()) !=
getContext().getCanonicalType(ArgDecl->getType())) { getContext().getCanonicalType(ArgDecl->getType())) {
ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack, ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
Ivar->getType(), CK_BitCast, &Arg, Ivar->getType(), CK_BitCast, &Arg,
VK_RValue); VK_RValue);
BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign, BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc); Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign); EmitStmt(&Assign);
} else { } else {
BinaryOperator Assign(&IvarRef, &Arg, BO_Assign, BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
Ivar->getType(), VK_RValue, OK_Ordinary, Loc); Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
EmitStmt(&Assign); EmitStmt(&Assign);
}
} }
} }

View File

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