forked from OSchip/llvm-project
objc++: more code gen stuff for atomic property api,
currently turned off. // rdar://6137845 Also, fixes a test case which should be nonatomic under new API. llvm-svn: 147691
This commit is contained in:
parent
68a922c0e9
commit
7ff610b62d
|
@ -776,6 +776,44 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
|
|||
copyStructFn, ReturnValueSlot(), args);
|
||||
}
|
||||
|
||||
/// emitCPPObjectAtomicSetterCall - Call the runtime function to store
|
||||
/// the value from the first formal parameter into the given ivar, using
|
||||
/// the Cpp API for atomic Cpp objects with non-trivial copy assignment.
|
||||
static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
|
||||
ObjCMethodDecl *OMD,
|
||||
ObjCIvarDecl *ivar,
|
||||
llvm::Constant *AtomicHelperFn) {
|
||||
// objc_copyCppObjectAtomic (&CppObjectIvar, &Arg,
|
||||
// AtomicHelperFn);
|
||||
CallArgList args;
|
||||
|
||||
// The first argument is the address of the ivar.
|
||||
llvm::Value *ivarAddr =
|
||||
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
|
||||
CGF.LoadObjCSelf(), ivar, 0).getAddress();
|
||||
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
|
||||
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
|
||||
|
||||
// The second argument is the address of the parameter variable.
|
||||
ParmVarDecl *argVar = *OMD->param_begin();
|
||||
DeclRefExpr argRef(argVar, argVar->getType().getNonReferenceType(),
|
||||
VK_LValue, SourceLocation());
|
||||
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getAddress();
|
||||
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
|
||||
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
|
||||
|
||||
// Third argument is the helper function.
|
||||
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
|
||||
|
||||
llvm::Value *copyCppAtomicObjectFn =
|
||||
CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction();
|
||||
CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args,
|
||||
FunctionType::ExtInfo()),
|
||||
copyCppAtomicObjectFn, ReturnValueSlot(), args);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) {
|
||||
Expr *setter = PID->getSetterCXXAssignment();
|
||||
if (!setter) return true;
|
||||
|
@ -802,17 +840,24 @@ static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) {
|
|||
|
||||
void
|
||||
CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
||||
const ObjCPropertyImplDecl *propImpl) {
|
||||
// Just use the setter expression if Sema gave us one and it's
|
||||
// non-trivial. There's no way to do this atomically.
|
||||
if (!hasTrivialSetExpr(propImpl)) {
|
||||
EmitStmt(propImpl->getSetterCXXAssignment());
|
||||
return;
|
||||
}
|
||||
|
||||
const ObjCPropertyImplDecl *propImpl,
|
||||
llvm::Constant *AtomicHelperFn) {
|
||||
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
|
||||
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
|
||||
ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl();
|
||||
|
||||
// Just use the setter expression if Sema gave us one and it's
|
||||
// non-trivial.
|
||||
if (!hasTrivialSetExpr(propImpl)) {
|
||||
if (!AtomicHelperFn)
|
||||
// If non-atomic, assignment is called directly.
|
||||
EmitStmt(propImpl->getSetterCXXAssignment());
|
||||
else
|
||||
// If atomic, assignment is called via a locking api.
|
||||
emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar,
|
||||
AtomicHelperFn);
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyImplStrategy strategy(CGM, propImpl);
|
||||
switch (strategy.getKind()) {
|
||||
|
@ -944,13 +989,13 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
|||
/// is illegal within a category.
|
||||
void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID) {
|
||||
GenerateObjCAtomicCopyHelperFunction(PID);
|
||||
llvm::Constant *AtomicHelperFn = GenerateObjCAtomicCopyHelperFunction(PID);
|
||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
||||
ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
|
||||
assert(OMD && "Invalid call to generate setter (empty method)");
|
||||
StartObjCMethod(OMD, IMP->getClassInterface(), PID->getLocStart());
|
||||
|
||||
generateObjCSetterBody(IMP, PID);
|
||||
generateObjCSetterBody(IMP, PID, AtomicHelperFn);
|
||||
|
||||
FinishFunction();
|
||||
}
|
||||
|
@ -2489,15 +2534,21 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
|
|||
llvm::Constant *
|
||||
CodeGenFunction::GenerateObjCAtomicCopyHelperFunction(
|
||||
const ObjCPropertyImplDecl *PID) {
|
||||
if (!getLangOptions().CPlusPlus)
|
||||
// FIXME. This api is for NeXt runtime only for now.
|
||||
if (!getLangOptions().CPlusPlus || !getLangOptions().NeXTRuntime)
|
||||
return 0;
|
||||
QualType Ty = PID->getPropertyIvarDecl()->getType();
|
||||
if (!Ty->isRecordType())
|
||||
return 0;
|
||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
||||
if (!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic) ||
|
||||
hasTrivialSetExpr(PID))
|
||||
hasTrivialSetExpr(PID) || /* temporary */ true)
|
||||
return 0;
|
||||
|
||||
llvm::Constant * HelperFn = CGM.getAtomicHelperFnMap(Ty);
|
||||
if (HelperFn)
|
||||
return HelperFn;
|
||||
|
||||
assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
|
||||
|
||||
ASTContext &C = getContext();
|
||||
|
@ -2562,8 +2613,9 @@ CodeGenFunction::GenerateObjCAtomicCopyHelperFunction(
|
|||
EmitStmt(TheCall);
|
||||
|
||||
FinishFunction();
|
||||
|
||||
return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
|
||||
HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
|
||||
CGM.setAtomicHelperFnMap(Ty, HelperFn);
|
||||
return HelperFn;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1310,7 +1310,8 @@ public:
|
|||
void GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID);
|
||||
void generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
||||
const ObjCPropertyImplDecl *propImpl);
|
||||
const ObjCPropertyImplDecl *propImpl,
|
||||
llvm::Constant *AtomicHelperFn);
|
||||
bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
|
||||
bool IvarTypeWithAggrGCObjects(QualType Ty);
|
||||
|
||||
|
|
|
@ -276,6 +276,8 @@ class CodeGenModule : public CodeGenTypeCache {
|
|||
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
|
||||
llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
|
||||
llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap;
|
||||
|
||||
llvm::DenseMap<QualType, llvm::Constant *> AtomicHelperFnMap;
|
||||
|
||||
/// CXXGlobalInits - Global variables with initializers that need to run
|
||||
/// before main.
|
||||
|
@ -398,6 +400,14 @@ public:
|
|||
StaticLocalDeclMap[D] = GV;
|
||||
}
|
||||
|
||||
llvm::Constant *getAtomicHelperFnMap(QualType Ty) {
|
||||
return AtomicHelperFnMap[Ty];
|
||||
}
|
||||
void setAtomicHelperFnMap(QualType Ty,
|
||||
llvm::Constant *Fn) {
|
||||
AtomicHelperFnMap[Ty] = Fn;
|
||||
}
|
||||
|
||||
CGDebugInfo *getModuleDebugInfo() { return DebugInfo; }
|
||||
|
||||
ASTContext &getContext() const { return Context; }
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace test1 {
|
|||
@interface Test1 {
|
||||
test1::A ivar;
|
||||
}
|
||||
@property const test1::A &prop1;
|
||||
@property (nonatomic) const test1::A &prop1;
|
||||
@end
|
||||
@implementation Test1
|
||||
@synthesize prop1 = ivar;
|
||||
|
|
Loading…
Reference in New Issue