CGObjCMac.cpp revision 259d93d1e1f820d5ee7251e875fdb7c883102f16
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" 15 16#include "CodeGenModule.h" 17#include "clang/AST/ASTContext.h" 18#include "clang/AST/Decl.h" 19#include "clang/Basic/LangOptions.h" 20 21#include "llvm/Module.h" 22#include "llvm/Support/IRBuilder.h" 23 24using namespace clang; 25 26namespace { 27 28/// ObjCTypesHelper - Helper class that encapsulates lazy 29/// construction of varies types used during ObjC generation. 30class ObjCTypesHelper { 31private: 32 CodeGen::CodeGenModule &CGM; 33 34 const llvm::StructType *CFStringType; 35 llvm::Constant *CFConstantStringClassReference; 36 llvm::Function *MessageSendFn; 37 38public: 39 const llvm::Type *LongTy; 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 46public: 47 ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 48 ~ObjCTypesHelper(); 49 50 llvm::Constant *getCFConstantStringClassReference(); 51 const llvm::StructType *getCFStringType(); 52 llvm::Function *getMessageSendFn(); 53}; 54 55class CGObjCMac : public CodeGen::CGObjCRuntime { 56private: 57 CodeGen::CodeGenModule &CGM; 58 ObjCTypesHelper ObjCTypes; 59 /// ObjCABI - FIXME: Not sure yet. 60 unsigned ObjCABI; 61 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 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(); 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); 87 88public: 89 CGObjCMac(CodeGen::CodeGenModule &cgm); 90 virtual llvm::Constant *GenerateConstantString(const std::string &String); 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 157 158/* *** Helper Functions *** */ 159 160/// getConstantGEP() - Help routine to construct simple GEPs. 161static 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 *** */ 172 173CGObjCMac::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(); 183} 184 185// This has to perform the lookup every time, since posing and related 186// techniques can modify the name -> class mapping. 187llvm::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. 194llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) { 195 return EmitSelector(Builder, Sel); 196} 197 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 208llvm::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; 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. 248llvm::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. 261llvm::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, 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 } 281} 282 283llvm::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 289void 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 298void 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 309void 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 324llvm::Function *CGObjCMac::ModuleInitFunction() { 325 // Abuse this interface function as a place to finalize. 326 FinishModule(); 327 328 return NULL; 329} 330 331llvm::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) { 340 assert(0 && "Cannot generate method preamble for Mac runtime."); 341 return 0; 342} 343 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/// }; 354enum ImageInfoFlags { 355 eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what this implies 356 eImageInfo_GarbageCollected = (1 << 1), 357 eImageInfo_GCOnly = (1 << 2) 358}; 359 360void 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 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 383 if (ObjCABI == 1) { 384 GV->setSection("__OBJC, __image_info,regular"); 385 } else { 386 GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); 387 } 388 389 UsedGlobals.push_back(GV); 390} 391 392llvm::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 411llvm::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 428void 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 450ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 451 : CGM(cgm), 452 CFStringType(0), 453 CFConstantStringClassReference(0), 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)) 461{ 462 CGM.getModule().addTypeName("struct.__objc_object", ObjectTy); 463 CGM.getModule().addTypeName("struct.__objc_selector", SelectorTy); 464} 465 466ObjCTypesHelper::~ObjCTypesHelper() { 467} 468 469const 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 484llvm::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 500llvm::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 516/* *** */ 517 518CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){ 519 return new CGObjCMac(CGM); 520} 521