| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 1 | //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===// | 
|  | 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 Apple runtime. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "CGObjCRuntime.h" | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 15 |  | 
|  | 16 | #include "CodeGenModule.h" | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 17 | #include "clang/AST/ASTContext.h" | 
| Daniel Dunbar | e91593e | 2008-08-11 04:54:23 +0000 | [diff] [blame] | 18 | #include "clang/AST/Decl.h" | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 19 | #include "clang/Basic/LangOptions.h" | 
|  | 20 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 21 | #include "llvm/Module.h" | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 22 | #include "llvm/Support/IRBuilder.h" | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 23 |  | 
|  | 24 | using namespace clang; | 
|  | 25 |  | 
|  | 26 | namespace { | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 27 |  | 
|  | 28 | /// ObjCTypesHelper - Helper class that encapsulates lazy | 
|  | 29 | /// construction of varies types used during ObjC generation. | 
|  | 30 | class ObjCTypesHelper { | 
|  | 31 | private: | 
|  | 32 | CodeGen::CodeGenModule &CGM; | 
|  | 33 |  | 
|  | 34 | const llvm::StructType *CFStringType; | 
|  | 35 | llvm::Constant *CFConstantStringClassReference; | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 36 | llvm::Function *MessageSendFn; | 
|  | 37 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 38 | public: | 
|  | 39 | const llvm::Type *LongTy; | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 40 |  | 
|  | 41 | /// ObjectTy - Opaque type for Objective-C objects | 
|  | 42 | const llvm::Type *ObjectTy, *ObjectPtrTy; | 
|  | 43 | /// SelectorTy - Opaque type for Objective-C selectors | 
|  | 44 | const llvm::Type *SelectorTy, *SelectorPtrTy; | 
|  | 45 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 46 | public: | 
|  | 47 | ObjCTypesHelper(CodeGen::CodeGenModule &cgm); | 
|  | 48 | ~ObjCTypesHelper(); | 
|  | 49 |  | 
|  | 50 | llvm::Constant *getCFConstantStringClassReference(); | 
|  | 51 | const llvm::StructType *getCFStringType(); | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 52 | llvm::Function *getMessageSendFn(); | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 53 | }; | 
|  | 54 |  | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 55 | class CGObjCMac : public CodeGen::CGObjCRuntime { | 
|  | 56 | private: | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 57 | CodeGen::CodeGenModule &CGM; | 
|  | 58 | ObjCTypesHelper ObjCTypes; | 
|  | 59 | /// ObjCABI - FIXME: Not sure yet. | 
|  | 60 | unsigned ObjCABI; | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 61 |  | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 62 | /// MethodVarNames - uniqued method variable names. | 
|  | 63 | llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; | 
|  | 64 |  | 
|  | 65 | /// SelectorReferences - uniqued selector references. | 
|  | 66 | llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; | 
|  | 67 |  | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 68 | /// UsedGlobals - list of globals to pack into the llvm.used metadata | 
|  | 69 | /// to prevent them from being clobbered. | 
|  | 70 | std::vector<llvm::GlobalValue*> UsedGlobals; | 
|  | 71 |  | 
|  | 72 | /// EmitImageInfo - Emit the image info marker used to encode some module | 
|  | 73 | /// level information. | 
|  | 74 | void EmitImageInfo(); | 
|  | 75 |  | 
|  | 76 | /// FinishModule - Write out global data structures at the end of | 
|  | 77 | /// processing a translation unit. | 
|  | 78 | void FinishModule(); | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 79 |  | 
|  | 80 | /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, | 
|  | 81 | /// for the given selector. | 
|  | 82 | llvm::Value *EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel); | 
|  | 83 |  | 
|  | 84 | /// GetMethodVarName - Return a unique constant for the given | 
|  | 85 | /// selector's name. | 
|  | 86 | llvm::Constant *GetMethodVarName(Selector Sel); | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 87 |  | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 88 | public: | 
|  | 89 | CGObjCMac(CodeGen::CodeGenModule &cgm); | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 90 | virtual llvm::Constant *GenerateConstantString(const std::string &String); | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 91 |  | 
|  | 92 | virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder, | 
|  | 93 | const llvm::Type *ReturnTy, | 
|  | 94 | llvm::Value *Sender, | 
|  | 95 | llvm::Value *Receiver, | 
|  | 96 | Selector Sel, | 
|  | 97 | llvm::Value** ArgV, | 
|  | 98 | unsigned ArgC); | 
|  | 99 |  | 
|  | 100 | virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, | 
|  | 101 | const llvm::Type *ReturnTy, | 
|  | 102 | llvm::Value *Sender, | 
|  | 103 | const char *SuperClassName, | 
|  | 104 | llvm::Value *Receiver, | 
|  | 105 | Selector Sel, | 
|  | 106 | llvm::Value** ArgV, | 
|  | 107 | unsigned ArgC); | 
|  | 108 |  | 
|  | 109 | virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder, | 
|  | 110 | llvm::Value *ClassName); | 
|  | 111 |  | 
|  | 112 | virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel); | 
|  | 113 |  | 
|  | 114 | virtual llvm::Function *MethodPreamble(const std::string &ClassName, | 
|  | 115 | const std::string &CategoryName, | 
|  | 116 | const std::string &MethodName, | 
|  | 117 | const llvm::Type *ReturnTy, | 
|  | 118 | const llvm::Type *SelfTy, | 
|  | 119 | const llvm::Type **ArgTy, | 
|  | 120 | unsigned ArgC, | 
|  | 121 | bool isClassMethod, | 
|  | 122 | bool isVarArg); | 
|  | 123 |  | 
|  | 124 | virtual void GenerateCategory(const char *ClassName, const char *CategoryName, | 
|  | 125 | const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels, | 
|  | 126 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 127 | const llvm::SmallVectorImpl<Selector>  &ClassMethodSels, | 
|  | 128 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes, | 
|  | 129 | const llvm::SmallVectorImpl<std::string> &Protocols); | 
|  | 130 |  | 
|  | 131 | virtual void GenerateClass( | 
|  | 132 | const char *ClassName, | 
|  | 133 | const char *SuperClassName, | 
|  | 134 | const int instanceSize, | 
|  | 135 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames, | 
|  | 136 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes, | 
|  | 137 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets, | 
|  | 138 | const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels, | 
|  | 139 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 140 | const llvm::SmallVectorImpl<Selector>  &ClassMethodSels, | 
|  | 141 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes, | 
|  | 142 | const llvm::SmallVectorImpl<std::string> &Protocols); | 
|  | 143 |  | 
|  | 144 | virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder, | 
|  | 145 | const char *ProtocolName); | 
|  | 146 |  | 
|  | 147 | virtual void GenerateProtocol(const char *ProtocolName, | 
|  | 148 | const llvm::SmallVectorImpl<std::string> &Protocols, | 
|  | 149 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodNames, | 
|  | 150 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 151 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodNames, | 
|  | 152 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes); | 
|  | 153 |  | 
|  | 154 | virtual llvm::Function *ModuleInitFunction(); | 
|  | 155 | }; | 
|  | 156 | } // end anonymous namespace | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 157 |  | 
|  | 158 | /* *** Helper Functions *** */ | 
|  | 159 |  | 
|  | 160 | /// getConstantGEP() - Help routine to construct simple GEPs. | 
|  | 161 | static llvm::Constant *getConstantGEP(llvm::Constant *C, | 
|  | 162 | unsigned idx0, | 
|  | 163 | unsigned idx1) { | 
|  | 164 | llvm::Value *Idxs[] = { | 
|  | 165 | llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0), | 
|  | 166 | llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1) | 
|  | 167 | }; | 
|  | 168 | return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | /* *** CGObjCMac Public Interface *** */ | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 172 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 173 | CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) | 
|  | 174 | : CGM(cgm), | 
|  | 175 | ObjCTypes(cgm), | 
|  | 176 | ObjCABI(1) | 
|  | 177 | { | 
|  | 178 | // FIXME: How does this get set in GCC? And what does it even mean? | 
|  | 179 | if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy)) | 
|  | 180 | ObjCABI = 2; | 
|  | 181 |  | 
|  | 182 | EmitImageInfo(); | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 183 | } | 
|  | 184 |  | 
|  | 185 | // This has to perform the lookup every time, since posing and related | 
|  | 186 | // techniques can modify the name -> class mapping. | 
|  | 187 | llvm::Value *CGObjCMac::LookupClass(llvm::IRBuilder<> &Builder, | 
|  | 188 | llvm::Value *ClassName) { | 
|  | 189 | assert(0 && "Cannot lookup classes on Mac runtime."); | 
|  | 190 | return 0; | 
|  | 191 | } | 
|  | 192 |  | 
|  | 193 | /// GetSelector - Return the pointer to the unique'd string for this selector. | 
|  | 194 | llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) { | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 195 | return EmitSelector(Builder, Sel); | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 196 | } | 
|  | 197 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 198 | /// Generate a constant CFString object. | 
|  | 199 | /* | 
|  | 200 | struct __builtin_CFString { | 
|  | 201 | const int *isa; // point to __CFConstantStringClassReference | 
|  | 202 | int flags; | 
|  | 203 | const char *str; | 
|  | 204 | long length; | 
|  | 205 | }; | 
|  | 206 | */ | 
|  | 207 |  | 
|  | 208 | llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) { | 
|  | 209 | // FIXME: I have no idea what this constant is (it is a magic | 
|  | 210 | // constant in GCC as well). Most likely the encoding of the string | 
|  | 211 | // and at least one part of it relates to UTF-16. Is this just the | 
|  | 212 | // code for UTF-8? Where is this handled for us? | 
|  | 213 | //  See: <rdr://2996215> | 
|  | 214 | unsigned flags = 0x07c8; | 
|  | 215 |  | 
|  | 216 | // FIXME: Use some machinery to unique this. We can't reuse the CGM | 
|  | 217 | // one since we put them in a different section. | 
|  | 218 | llvm::Constant *StringC = llvm::ConstantArray::get(String); | 
|  | 219 | llvm::Constant *StringGV = | 
|  | 220 | new llvm::GlobalVariable(StringC->getType(), true, | 
|  | 221 | llvm::GlobalValue::InternalLinkage, | 
|  | 222 | StringC, ".str", &CGM.getModule()); | 
|  | 223 | llvm::Constant *Values[4] = { | 
|  | 224 | ObjCTypes.getCFConstantStringClassReference(), | 
|  | 225 | llvm::ConstantInt::get(llvm::Type::Int32Ty, flags), | 
|  | 226 | getConstantGEP(StringGV, 0, 0), // Decay array -> ptr | 
|  | 227 | llvm::ConstantInt::get(ObjCTypes.LongTy, String.size()) | 
|  | 228 | }; | 
|  | 229 |  | 
|  | 230 | llvm::Constant *CFStringC = | 
|  | 231 | llvm::ConstantStruct::get(ObjCTypes.getCFStringType(), | 
|  | 232 | std::vector<llvm::Constant*>(Values, Values+4)); | 
|  | 233 |  | 
|  | 234 | llvm::GlobalVariable *CFStringGV = | 
|  | 235 | new llvm::GlobalVariable(CFStringC->getType(), true, | 
|  | 236 | llvm::GlobalValue::InternalLinkage, | 
|  | 237 | CFStringC, "", | 
|  | 238 | &CGM.getModule()); | 
|  | 239 |  | 
|  | 240 | CFStringGV->setSection("__DATA, __cfstring"); | 
|  | 241 |  | 
|  | 242 | return CFStringGV; | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 243 | } | 
|  | 244 |  | 
|  | 245 | /// Generates a message send where the super is the receiver.  This is | 
|  | 246 | /// a message send to self with special delivery semantics indicating | 
|  | 247 | /// which class's method should be called. | 
|  | 248 | llvm::Value *CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, | 
|  | 249 | const llvm::Type *ReturnTy, | 
|  | 250 | llvm::Value *Sender, | 
|  | 251 | const char *SuperClassName, | 
|  | 252 | llvm::Value *Receiver, | 
|  | 253 | Selector Sel, | 
|  | 254 | llvm::Value** ArgV, | 
|  | 255 | unsigned ArgC) { | 
|  | 256 | assert(0 && "Cannot generate message send to super for Mac runtime."); | 
|  | 257 | return 0; | 
|  | 258 | } | 
|  | 259 |  | 
|  | 260 | /// Generate code for a message send expression. | 
|  | 261 | llvm::Value *CGObjCMac::GenerateMessageSend(llvm::IRBuilder<> &Builder, | 
|  | 262 | const llvm::Type *ReturnTy, | 
|  | 263 | llvm::Value *Sender, | 
|  | 264 | llvm::Value *Receiver, | 
|  | 265 | Selector Sel, | 
|  | 266 | llvm::Value** ArgV, | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 267 | unsigned ArgC) { | 
|  | 268 | if (!Sender) { | 
|  | 269 | llvm::Function *F = ObjCTypes.getMessageSendFn(); | 
|  | 270 | llvm::Value **Args = new llvm::Value*[ArgC+2]; | 
|  | 271 | Args[0] = Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp"); | 
|  | 272 | Args[1] = EmitSelector(Builder, Sel); | 
|  | 273 | std::copy(ArgV, ArgV+ArgC, Args+2); | 
|  | 274 | llvm::CallInst *CI = Builder.CreateCall(F, Args, Args+ArgC+2, "tmp"); | 
|  | 275 | delete[] Args; | 
|  | 276 | return Builder.CreateBitCast(CI, ReturnTy, "tmp"); | 
|  | 277 | } else { | 
|  | 278 | assert(0 && "cannot generate message sends with sender"); | 
|  | 279 | return 0; | 
|  | 280 | } | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 281 | } | 
|  | 282 |  | 
|  | 283 | llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder, | 
|  | 284 | const char *ProtocolName) { | 
|  | 285 | assert(0 && "Cannot get protocol reference on Mac runtime."); | 
|  | 286 | return 0; | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | void CGObjCMac::GenerateProtocol(const char *ProtocolName, | 
|  | 290 | const llvm::SmallVectorImpl<std::string> &Protocols, | 
|  | 291 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodNames, | 
|  | 292 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 293 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodNames, | 
|  | 294 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes) { | 
|  | 295 | assert(0 && "Cannot generate protocol for Mac runtime."); | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | void CGObjCMac::GenerateCategory( | 
|  | 299 | const char *ClassName, | 
|  | 300 | const char *CategoryName, | 
|  | 301 | const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels, | 
|  | 302 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 303 | const llvm::SmallVectorImpl<Selector>  &ClassMethodSels, | 
|  | 304 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes, | 
|  | 305 | const llvm::SmallVectorImpl<std::string> &Protocols) { | 
|  | 306 | assert(0 && "Cannot generate category for Mac runtime."); | 
|  | 307 | } | 
|  | 308 |  | 
|  | 309 | void CGObjCMac::GenerateClass( | 
|  | 310 | const char *ClassName, | 
|  | 311 | const char *SuperClassName, | 
|  | 312 | const int instanceSize, | 
|  | 313 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames, | 
|  | 314 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes, | 
|  | 315 | const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets, | 
|  | 316 | const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels, | 
|  | 317 | const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes, | 
|  | 318 | const llvm::SmallVectorImpl<Selector>  &ClassMethodSels, | 
|  | 319 | const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes, | 
|  | 320 | const llvm::SmallVectorImpl<std::string> &Protocols) { | 
|  | 321 | assert(0 && "Cannot generate class for Mac runtime."); | 
|  | 322 | } | 
|  | 323 |  | 
|  | 324 | llvm::Function *CGObjCMac::ModuleInitFunction() { | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 325 | // Abuse this interface function as a place to finalize. | 
|  | 326 | FinishModule(); | 
|  | 327 |  | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 328 | return NULL; | 
|  | 329 | } | 
|  | 330 |  | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 331 | llvm::Function *CGObjCMac::MethodPreamble(const std::string &ClassName, | 
|  | 332 | const std::string &CategoryName, | 
|  | 333 | const std::string &MethodName, | 
|  | 334 | const llvm::Type *ReturnTy, | 
|  | 335 | const llvm::Type *SelfTy, | 
|  | 336 | const llvm::Type **ArgTy, | 
|  | 337 | unsigned ArgC, | 
|  | 338 | bool isClassMethod, | 
|  | 339 | bool isVarArg) { | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 340 | assert(0 && "Cannot generate method preamble for Mac runtime."); | 
|  | 341 | return 0; | 
|  | 342 | } | 
|  | 343 |  | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 344 | /* *** Private Interface *** */ | 
|  | 345 |  | 
|  | 346 | /// EmitImageInfo - Emit the image info marker used to encode some module | 
|  | 347 | /// level information. | 
|  | 348 | /// | 
|  | 349 | /// See: <rdr://4810609&4810587&4810587> | 
|  | 350 | /// struct IMAGE_INFO { | 
|  | 351 | ///   unsigned version; | 
|  | 352 | ///   unsigned flags; | 
|  | 353 | /// }; | 
|  | 354 | enum ImageInfoFlags { | 
|  | 355 | eImageInfo_FixAndContinue   = (1 << 0), // FIXME: Not sure what this implies | 
|  | 356 | eImageInfo_GarbageCollected = (1 << 1), | 
|  | 357 | eImageInfo_GCOnly           = (1 << 2) | 
|  | 358 | }; | 
|  | 359 |  | 
|  | 360 | void CGObjCMac::EmitImageInfo() { | 
|  | 361 | unsigned version = 0; // Version is unused? | 
|  | 362 | unsigned flags = 0; | 
|  | 363 |  | 
|  | 364 | // FIXME: Fix and continue? | 
|  | 365 | if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) | 
|  | 366 | flags |= eImageInfo_GarbageCollected; | 
|  | 367 | if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) | 
|  | 368 | flags |= eImageInfo_GCOnly; | 
|  | 369 |  | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 370 | // Emitted as int[2]; | 
|  | 371 | llvm::Constant *values[2] = { | 
|  | 372 | llvm::ConstantInt::get(llvm::Type::Int32Ty, version), | 
|  | 373 | llvm::ConstantInt::get(llvm::Type::Int32Ty, flags) | 
|  | 374 | }; | 
|  | 375 | llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2); | 
|  | 376 | llvm::GlobalValue *GV = | 
|  | 377 | new llvm::GlobalVariable(AT, true, | 
|  | 378 | llvm::GlobalValue::InternalLinkage, | 
|  | 379 | llvm::ConstantArray::get(AT, values, 2), | 
|  | 380 | "\01L_OBJC_IMAGE_INFO", | 
|  | 381 | &CGM.getModule()); | 
|  | 382 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 383 | if (ObjCABI == 1) { | 
|  | 384 | GV->setSection("__OBJC, __image_info,regular"); | 
|  | 385 | } else { | 
|  | 386 | GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); | 
|  | 387 | } | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 388 |  | 
|  | 389 | UsedGlobals.push_back(GV); | 
|  | 390 | } | 
|  | 391 |  | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 392 | llvm::Value *CGObjCMac::EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel) { | 
|  | 393 | llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; | 
|  | 394 |  | 
|  | 395 | if (!Entry) { | 
|  | 396 | llvm::Constant *Casted = | 
|  | 397 | llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), | 
|  | 398 | ObjCTypes.SelectorPtrTy); | 
|  | 399 | Entry = | 
|  | 400 | new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false, | 
|  | 401 | llvm::GlobalValue::InternalLinkage, | 
|  | 402 | Casted, "\01L_OBJC_SELECTOR_REFERENCES_", | 
|  | 403 | &CGM.getModule()); | 
|  | 404 | Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip"); | 
|  | 405 | UsedGlobals.push_back(Entry); | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | return Builder.CreateLoad(Entry, false, "tmp"); | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | llvm::Constant *CGObjCMac::GetMethodVarName(Selector Sel) { | 
|  | 412 | llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; | 
|  | 413 |  | 
|  | 414 | if (!Entry) { | 
|  | 415 | llvm::Constant *C = llvm::ConstantArray::get(Sel.getName()); | 
|  | 416 | Entry = | 
|  | 417 | new llvm::GlobalVariable(C->getType(), true, | 
|  | 418 | llvm::GlobalValue::InternalLinkage, | 
|  | 419 | C, "\01L_OBJC_METH_VAR_NAME_", | 
|  | 420 | &CGM.getModule()); | 
|  | 421 | Entry->setSection("__TEXT,__cstring,cstring_literals"); | 
|  | 422 | UsedGlobals.push_back(Entry); | 
|  | 423 | } | 
|  | 424 |  | 
|  | 425 | return Entry; | 
|  | 426 | } | 
|  | 427 |  | 
| Daniel Dunbar | f77ac86 | 2008-08-11 21:35:06 +0000 | [diff] [blame] | 428 | void CGObjCMac::FinishModule() { | 
|  | 429 | std::vector<llvm::Constant*> Used; | 
|  | 430 |  | 
|  | 431 | llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); | 
|  | 432 | for (std::vector<llvm::GlobalValue*>::iterator i = UsedGlobals.begin(), | 
|  | 433 | e = UsedGlobals.end(); i != e; ++i) { | 
|  | 434 | Used.push_back(llvm::ConstantExpr::getBitCast(*i, I8Ptr)); | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | llvm::ArrayType *AT = llvm::ArrayType::get(I8Ptr, Used.size()); | 
|  | 438 | llvm::GlobalValue *GV = | 
|  | 439 | new llvm::GlobalVariable(AT, false, | 
|  | 440 | llvm::GlobalValue::AppendingLinkage, | 
|  | 441 | llvm::ConstantArray::get(AT, Used), | 
|  | 442 | "llvm.used", | 
|  | 443 | &CGM.getModule()); | 
|  | 444 |  | 
|  | 445 | GV->setSection("llvm.metadata"); | 
|  | 446 | } | 
|  | 447 |  | 
|  | 448 | /* *** */ | 
|  | 449 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 450 | ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) | 
|  | 451 | : CGM(cgm), | 
|  | 452 | CFStringType(0), | 
|  | 453 | CFConstantStringClassReference(0), | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 454 | MessageSendFn(0), | 
|  | 455 | LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy)), | 
|  | 456 | // FIXME: We want the types from the front-end. | 
|  | 457 | ObjectTy(llvm::OpaqueType::get()), | 
|  | 458 | ObjectPtrTy(llvm::PointerType::getUnqual(ObjectTy)), | 
|  | 459 | SelectorTy(llvm::OpaqueType::get()), | 
|  | 460 | SelectorPtrTy(llvm::PointerType::getUnqual(SelectorTy)) | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 461 | { | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 462 | CGM.getModule().addTypeName("struct.__objc_object", ObjectTy); | 
|  | 463 | CGM.getModule().addTypeName("struct.__objc_selector", SelectorTy); | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 464 | } | 
|  | 465 |  | 
|  | 466 | ObjCTypesHelper::~ObjCTypesHelper() { | 
|  | 467 | } | 
|  | 468 |  | 
|  | 469 | const llvm::StructType *ObjCTypesHelper::getCFStringType() { | 
|  | 470 | if (!CFStringType) { | 
|  | 471 | CFStringType = | 
|  | 472 | llvm::StructType::get(llvm::PointerType::getUnqual(llvm::Type::Int32Ty), | 
|  | 473 | llvm::Type::Int32Ty, | 
|  | 474 | llvm::PointerType::getUnqual(llvm::Type::Int8Ty), | 
|  | 475 | LongTy, | 
|  | 476 | NULL); | 
|  | 477 |  | 
|  | 478 | CGM.getModule().addTypeName("struct.__builtin_CFString", CFStringType); | 
|  | 479 | } | 
|  | 480 |  | 
|  | 481 | return CFStringType; | 
|  | 482 | } | 
|  | 483 |  | 
|  | 484 | llvm::Constant *ObjCTypesHelper::getCFConstantStringClassReference() { | 
|  | 485 | if (!CFConstantStringClassReference) { | 
|  | 486 | llvm::GlobalValue *GV = | 
|  | 487 | new llvm::GlobalVariable(llvm::ArrayType::get(llvm::Type::Int32Ty, 0), | 
|  | 488 | false, | 
|  | 489 | llvm::GlobalValue::ExternalLinkage, | 
|  | 490 | 0, "__CFConstantStringClassReference", | 
|  | 491 | &CGM.getModule()); | 
|  | 492 |  | 
|  | 493 | // Decay to pointer. | 
|  | 494 | CFConstantStringClassReference = getConstantGEP(GV, 0, 0); | 
|  | 495 | } | 
|  | 496 |  | 
|  | 497 | return CFConstantStringClassReference; | 
|  | 498 | } | 
|  | 499 |  | 
| Daniel Dunbar | 259d93d | 2008-08-12 03:39:23 +0000 | [diff] [blame^] | 500 | llvm::Function *ObjCTypesHelper::getMessageSendFn() { | 
|  | 501 | if (!MessageSendFn) { | 
|  | 502 | std::vector<const llvm::Type*> Params; | 
|  | 503 | Params.push_back(ObjectPtrTy); | 
|  | 504 | Params.push_back(SelectorPtrTy); | 
|  | 505 | MessageSendFn = llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy, | 
|  | 506 | Params, | 
|  | 507 | true), | 
|  | 508 | llvm::Function::ExternalLinkage, | 
|  | 509 | "objc_msgSend", | 
|  | 510 | &CGM.getModule()); | 
|  | 511 | } | 
|  | 512 |  | 
|  | 513 | return MessageSendFn; | 
|  | 514 | } | 
|  | 515 |  | 
| Daniel Dunbar | bbce49b | 2008-08-12 00:12:39 +0000 | [diff] [blame] | 516 | /* *** */ | 
|  | 517 |  | 
| Daniel Dunbar | c17a4d3 | 2008-08-11 02:45:11 +0000 | [diff] [blame] | 518 | CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){ | 
|  | 519 | return new CGObjCMac(CGM); | 
|  | 520 | } |