CGObjCGNU.cpp revision 391d77a26382dddf25da73e29fc1fa5aaaea4c6f
1//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This provides Objective-C code generation targetting the GNU runtime. 11// 12//===----------------------------------------------------------------------===// 13 14#include "CGObjCRuntime.h" 15#include "llvm/Module.h" 16#include "llvm/Support/Compiler.h" 17#include "llvm/Support/LLVMBuilder.h" 18#include "llvm/ADT/SmallVector.h" 19 20 21clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {} 22 23namespace { 24class CGObjCGNU : public clang::CodeGen::CGObjCRuntime { 25private: 26 llvm::Module &TheModule; 27 const llvm::Type *SelectorTy; 28 const llvm::Type *PtrToInt8Ty; 29 const llvm::Type *IMPTy; 30 const llvm::Type *IdTy; 31 const llvm::Type *IntTy; 32 const llvm::Type *PtrTy; 33 const llvm::Type *LongTy; 34 const llvm::Type *PtrToIntTy; 35public: 36 CGObjCGNU(llvm::Module &Mp, 37 const llvm::Type *LLVMIntType, 38 const llvm::Type *LLVMLongType); 39 virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, 40 const llvm::Type *ReturnTy, 41 llvm::Value *Sender, 42 llvm::Value *Receiver, 43 llvm::Value *Selector, 44 llvm::Value** ArgV, 45 unsigned ArgC); 46 llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder, 47 llvm::Value *SelName, 48 llvm::Value *SelTypes); 49 virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy, 50 const llvm::Type *SelfTy, 51 const llvm::Type **ArgTy, 52 unsigned ArgC, 53 bool isVarArg); 54}; 55} // end anonymous namespace 56 57CGObjCGNU::CGObjCGNU(llvm::Module &M, 58 const llvm::Type *LLVMIntType, 59 const llvm::Type *LLVMLongType) : 60 TheModule(M), 61 IntTy(LLVMIntType), 62 LongTy(LLVMLongType) 63{ 64 // C string type. Used in lots of places. 65 PtrToInt8Ty = 66 llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 67 // Get the selector Type. 68 const llvm::Type *SelStructTy = llvm::StructType::get( 69 PtrToInt8Ty, 70 PtrToInt8Ty, 71 NULL); 72 SelectorTy = llvm::PointerType::getUnqual(SelStructTy); 73 PtrToIntTy = llvm::PointerType::getUnqual(IntTy); 74 PtrTy = PtrToInt8Ty; 75 76 // Object type 77 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get(); 78 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy); 79 IdTy = llvm::StructType::get(OpaqueIdTy, NULL); 80 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy); 81 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get()); 82 IdTy = llvm::PointerType::getUnqual(IdTy); 83 84 // IMP type 85 std::vector<const llvm::Type*> IMPArgs; 86 IMPArgs.push_back(IdTy); 87 IMPArgs.push_back(SelectorTy); 88 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); 89 90} 91 92/// Looks up the selector for the specified name / type pair. 93// FIXME: Selectors should be statically cached, not looked up on every call. 94llvm::Value *CGObjCGNU::getSelector(llvm::LLVMFoldingBuilder &Builder, 95 llvm::Value *SelName, 96 llvm::Value *SelTypes) 97{ 98 // Look up the selector. 99 llvm::Value *cmd; 100 if(SelTypes == 0) { 101 llvm::Constant *SelFunction = TheModule.getOrInsertFunction("sel_get_uid", 102 SelectorTy, 103 PtrToInt8Ty, 104 NULL); 105 cmd = Builder.CreateCall(SelFunction, SelName); 106 } 107 else { 108 llvm::Constant *SelFunction = 109 TheModule.getOrInsertFunction("sel_get_typed_uid", 110 SelectorTy, 111 PtrToInt8Ty, 112 PtrToInt8Ty, 113 NULL); 114 llvm::Value *Args[] = { SelName, SelTypes }; 115 cmd = Builder.CreateCall(SelFunction, Args, Args+2); 116 } 117 return cmd; 118} 119 120 121/// Generate code for a message send expression on the GNU runtime. 122// FIXME: Much of this code will need factoring out later. 123// TODO: This should take a sender argument (pointer to self in the calling 124// context) 125llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, 126 const llvm::Type *ReturnTy, 127 llvm::Value *Sender, 128 llvm::Value *Receiver, 129 llvm::Value *Selector, 130 llvm::Value** ArgV, 131 unsigned ArgC) { 132 llvm::Value *cmd = getSelector(Builder, Selector, 0); 133 134 // Look up the method implementation. 135 std::vector<const llvm::Type*> impArgTypes; 136 impArgTypes.push_back(Receiver->getType()); 137 impArgTypes.push_back(SelectorTy); 138 139 // Avoid an explicit cast on the IMP by getting a version that has the right 140 // return type. 141 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes, 142 true); 143 144 llvm::Constant *lookupFunction = 145 TheModule.getOrInsertFunction("objc_msg_lookup", 146 llvm::PointerType::getUnqual(impType), 147 Receiver->getType(), SelectorTy, NULL); 148 llvm::SmallVector<llvm::Value*, 16> lookupArgs; 149 lookupArgs.push_back(Receiver); 150 lookupArgs.push_back(cmd); 151 llvm::Value *imp = Builder.CreateCall(lookupFunction, 152 lookupArgs.begin(), lookupArgs.end()); 153 154 // Call the method. 155 lookupArgs.insert(lookupArgs.end(), ArgV, ArgV+ArgC); 156 return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end()); 157} 158 159llvm::Function *CGObjCGNU::MethodPreamble( 160 const llvm::Type *ReturnTy, 161 const llvm::Type *SelfTy, 162 const llvm::Type **ArgTy, 163 unsigned ArgC, 164 bool isVarArg) { 165 std::vector<const llvm::Type*> Args; 166 Args.push_back(SelfTy); 167 Args.push_back(SelectorTy); 168 Args.insert(Args.end(), ArgTy, ArgTy+ArgC); 169 170 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy, 171 Args, 172 isVarArg); 173 llvm::Function *Method = new llvm::Function(MethodTy, 174 llvm::GlobalValue::InternalLinkage, 175 ".objc.method", 176 &TheModule); 177 // Set the names of the hidden arguments 178 llvm::Function::arg_iterator AI = Method->arg_begin(); 179 AI->setName("self"); 180 ++AI; 181 AI->setName("_cmd"); 182 return Method; 183} 184 185clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime( 186 llvm::Module &M, 187 const llvm::Type *LLVMIntType, 188 const llvm::Type *LLVMLongType) { 189 return new CGObjCGNU(M, LLVMIntType, LLVMLongType); 190} 191