diff options
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 165 |
1 files changed, 129 insertions, 36 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 1cc5cffb82..dd0eaa3b7c 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1,4 +1,4 @@ -//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// +//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// // // The LLVM Compiler Infrastructure // @@ -17,60 +17,124 @@ #include "llvm/Support/LLVMBuilder.h" #include "llvm/ADT/SmallVector.h" -using namespace clang::CodeGen; -using namespace clang; -CGObjCRuntime::~CGObjCRuntime() {} +clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {} namespace { -class CGObjCGNU : public CGObjCRuntime { +class CGObjCGNU : public clang::CodeGen::CGObjCRuntime { private: llvm::Module &TheModule; + const llvm::Type *SelectorTy; + const llvm::Type *PtrToInt8Ty; + const llvm::Type *IMPTy; + const llvm::Type *IdTy; + const llvm::Type *IntTy; + const llvm::Type *PtrTy; + const llvm::Type *LongTy; + const llvm::Type *PtrToIntTy; public: - CGObjCGNU(llvm::Module &M) : TheModule(M) {}; + CGObjCGNU(llvm::Module &Mp, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType); virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, const llvm::Type *ReturnTy, + llvm::Value *Sender, llvm::Value *Receiver, - llvm::Constant *Selector, + llvm::Value *Selector, llvm::Value** ArgV, unsigned ArgC); + llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder, + llvm::Value *SelName, + llvm::Value *SelTypes); + virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy, + const llvm::Type *SelfTy, + const llvm::Type **ArgTy, + unsigned ArgC, + bool isVarArg); }; } // end anonymous namespace -// Generate code for a message send expression on the GNU runtime. -// BIG FAT WARNING: Much of this code will need factoring out later. -// FIXME: This currently only handles id returns. Other return types -// need some explicit casting. +CGObjCGNU::CGObjCGNU(llvm::Module &M, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType) : + TheModule(M), + IntTy(LLVMIntType), + LongTy(LLVMLongType) +{ + // C string type. Used in lots of places. + PtrToInt8Ty = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + // Get the selector Type. + const llvm::Type *SelStructTy = llvm::StructType::get( + PtrToInt8Ty, + PtrToInt8Ty, + NULL); + SelectorTy = llvm::PointerType::getUnqual(SelStructTy); + PtrToIntTy = llvm::PointerType::getUnqual(IntTy); + PtrTy = PtrToInt8Ty; + + // Object type + llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get(); + llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy); + IdTy = llvm::StructType::get(OpaqueIdTy, NULL); + llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy); + IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get()); + IdTy = 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); + +} + +/// Looks up the selector for the specified name / type pair. +// FIXME: Selectors should be statically cached, not looked up on every call. +llvm::Value *CGObjCGNU::getSelector(llvm::LLVMFoldingBuilder &Builder, + llvm::Value *SelName, + llvm::Value *SelTypes) +{ + // Look up the selector. + llvm::Value *cmd; + if(SelTypes == 0) { + llvm::Constant *SelFunction = TheModule.getOrInsertFunction("sel_get_uid", + SelectorTy, + PtrToInt8Ty, + NULL); + cmd = Builder.CreateCall(SelFunction, SelName); + } + else { + llvm::Constant *SelFunction = + TheModule.getOrInsertFunction("sel_get_typed_uid", + SelectorTy, + PtrToInt8Ty, + PtrToInt8Ty, + NULL); + llvm::Value *Args[] = { SelName, SelTypes }; + cmd = Builder.CreateCall(SelFunction, Args, Args+2); + } + return cmd; +} + + +/// Generate code for a message send expression on the GNU runtime. +// FIXME: Much of this code will need factoring out later. +// TODO: This should take a sender argument (pointer to self in the calling +// context) llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, const llvm::Type *ReturnTy, + llvm::Value *Sender, llvm::Value *Receiver, - llvm::Constant *Selector, + llvm::Value *Selector, llvm::Value** ArgV, unsigned ArgC) { - // Get the selector Type. - const llvm::Type *PtrToInt8Ty = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - const llvm::Type *SelStructTy = - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL); - const llvm::Type *SelTy = llvm::PointerType::getUnqual(SelStructTy); - - // Look up the selector. - // If we haven't got the selector lookup function, look it up now. - // TODO: Factor this out and use it to implement @selector() too. - llvm::Constant *SelFunction = - TheModule.getOrInsertFunction("sel_get_uid", SelTy, PtrToInt8Ty, NULL); - // FIXME: Selectors should be statically cached, not looked up on every call. - - // TODO: Pull this out into the caller. - llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); - llvm::Constant *Ops[] = {Idx0, Idx0}; - llvm::Value *SelStr = llvm::ConstantExpr::getGetElementPtr(Selector, Ops, 2); - llvm::Value *cmd = Builder.CreateCall(SelFunction, &SelStr, &SelStr+1); + llvm::Value *cmd = getSelector(Builder, Selector, 0); // Look up the method implementation. std::vector<const llvm::Type*> impArgTypes; impArgTypes.push_back(Receiver->getType()); - impArgTypes.push_back(SelTy); + impArgTypes.push_back(SelectorTy); // Avoid an explicit cast on the IMP by getting a version that has the right // return type. @@ -79,8 +143,8 @@ llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, llvm::Constant *lookupFunction = TheModule.getOrInsertFunction("objc_msg_lookup", - llvm::PointerType::get(impType, 0), - Receiver->getType(), SelTy, NULL); + llvm::PointerType::getUnqual(impType), + Receiver->getType(), SelectorTy, NULL); llvm::SmallVector<llvm::Value*, 16> lookupArgs; lookupArgs.push_back(Receiver); lookupArgs.push_back(cmd); @@ -92,6 +156,35 @@ llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end()); } -CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) { - return new CGObjCGNU(M); +llvm::Function *CGObjCGNU::MethodPreamble( + const llvm::Type *ReturnTy, + const llvm::Type *SelfTy, + const llvm::Type **ArgTy, + unsigned ArgC, + bool isVarArg) { + std::vector<const llvm::Type*> Args; + Args.push_back(SelfTy); + Args.push_back(SelectorTy); + Args.insert(Args.end(), ArgTy, ArgTy+ArgC); + + llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy, + Args, + isVarArg); + llvm::Function *Method = new llvm::Function(MethodTy, + llvm::GlobalValue::InternalLinkage, + ".objc.method", + &TheModule); + // Set the names of the hidden arguments + llvm::Function::arg_iterator AI = Method->arg_begin(); + AI->setName("self"); + ++AI; + AI->setName("_cmd"); + return Method; +} + +clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime( + llvm::Module &M, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType) { + return new CGObjCGNU(M, LLVMIntType, LLVMLongType); } |