diff options
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 103 |
1 files changed, 97 insertions, 6 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index d69477852a..e068b68b3f 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -55,6 +55,7 @@ private: const llvm::PointerType *PtrToInt8Ty; const llvm::FunctionType *IMPTy; const llvm::PointerType *IdTy; + const llvm::PointerType *PtrToIdTy; QualType ASTIdTy; const llvm::IntegerType *IntTy; const llvm::PointerType *PtrTy; @@ -71,6 +72,11 @@ private: typedef std::pair<std::string, std::string> TypedSelector; std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors; llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors; + // Selectors that we don't emit in GC mode + Selector RetainSel, ReleaseSel, AutoreleaseSel; + // Functions used for GC. + llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn, + *WeakAssignFn, *GlobalAssignFn; // Some zeros used for GEPs in lots of places. llvm::Constant *Zeros[2]; llvm::Constant *NULLPtr; @@ -123,6 +129,10 @@ private: llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar); void EmitClassRef(const std::string &className); + llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){ + if (V->getType() == Ty) return V; + return B.CreateBitCast(V, Ty); + } public: CGObjCGNU(CodeGen::CodeGenModule &cgm); virtual llvm::Constant *GenerateConstantString(const StringLiteral *); @@ -266,12 +276,54 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) } else { IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); } + PtrToIdTy = llvm::PointerType::getUnqual(IdTy); // IMP type std::vector<const llvm::Type*> IMPArgs; IMPArgs.push_back(IdTy); IMPArgs.push_back(SelectorTy); IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); + + if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { + // Get selectors needed in GC mode + RetainSel = GetNullarySelector("retain", CGM.getContext()); + ReleaseSel = GetNullarySelector("release", CGM.getContext()); + AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext()); + + // Get functions needed in GC mode + + // id objc_assign_ivar(id, id, ptrdiff_t); + std::vector<const llvm::Type*> Args(1, IdTy); + Args.push_back(PtrToIdTy); + // FIXME: ptrdiff_t + Args.push_back(LongTy); + llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false); + IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); + // id objc_assign_strongCast (id, id*) + Args.pop_back(); + FTy = llvm::FunctionType::get(IdTy, Args, false); + StrongCastAssignFn = + CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); + // id objc_assign_global(id, id*); + FTy = llvm::FunctionType::get(IdTy, Args, false); + GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); + // id objc_assign_weak(id, id*); + FTy = llvm::FunctionType::get(IdTy, Args, false); + WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); + // id objc_read_weak(id*); + Args.clear(); + Args.push_back(PtrToIdTy); + FTy = llvm::FunctionType::get(IdTy, Args, false); + WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); + // void *objc_memmove_collectable(void*, void *, size_t); + Args.clear(); + Args.push_back(PtrToInt8Ty); + Args.push_back(PtrToInt8Ty); + // FIXME: size_t + Args.push_back(LongTy); + FTy = llvm::FunctionType::get(IdTy, Args, false); + MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); + } } // This has to perform the lookup every time, since posing and related @@ -400,6 +452,14 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, bool IsClassMessage, const CallArgList &CallArgs, const ObjCMethodDecl *Method) { + if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { + if (Sel == RetainSel || Sel == AutoreleaseSel) { + return RValue::get(Receiver); + } + if (Sel == ReleaseSel) { + return RValue::get(0); + } + } llvm::Value *cmd = GetSelector(CGF.Builder, Sel); CallArgList ActualArgs; @@ -494,6 +554,14 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, bool IsClassMessage, const CallArgList &CallArgs, const ObjCMethodDecl *Method) { + if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { + if (Sel == RetainSel || Sel == AutoreleaseSel) { + return RValue::get(Receiver); + } + if (Sel == ReleaseSel) { + return RValue::get(0); + } + } CGBuilderTy &Builder = CGF.Builder; IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); llvm::Value *cmd; @@ -1918,35 +1986,58 @@ void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, llvm::Value *AddrWeakObj) { - return 0; + CGBuilderTy B = CGF.Builder; + AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy); + return B.CreateCall(WeakReadFn, AddrWeakObj); } void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { - return; + CGBuilderTy B = CGF.Builder; + src = EnforceType(B, src, IdTy); + dst = EnforceType(B, dst, PtrToIdTy); + B.CreateCall2(WeakAssignFn, src, dst); } void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { - return; + CGBuilderTy B = CGF.Builder; + src = EnforceType(B, src, IdTy); + dst = EnforceType(B, dst, PtrToIdTy); + B.CreateCall2(GlobalAssignFn, src, dst); } void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst, llvm::Value *ivarOffset) { - return; + CGBuilderTy B = CGF.Builder; + src = EnforceType(B, src, IdTy); + dst = EnforceType(B, dst, PtrToIdTy); + B.CreateCall3(IvarAssignFn, src, dst, ivarOffset); } void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { - return; + CGBuilderTy B = CGF.Builder; + src = EnforceType(B, src, IdTy); + dst = EnforceType(B, dst, PtrToIdTy); + B.CreateCall2(StrongCastAssignFn, src, dst); } void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty) { - return; + CGBuilderTy B = CGF.Builder; + DestPtr = EnforceType(B, DestPtr, IdTy); + SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy); + + std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); + unsigned long size = TypeInfo.first/8; + // FIXME: size_t + llvm::Value *N = llvm::ConstantInt::get(LongTy, size); + + B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, N); } llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( |