diff --git a/gen/objcgen.cpp b/gen/objcgen.cpp index 04b216d686c..4f36d2e7541 100644 --- a/gen/objcgen.cpp +++ b/gen/objcgen.cpp @@ -10,7 +10,8 @@ //===----------------------------------------------------------------------===// #include "gen/objcgen.h" - +#include "dmd/expression.h" +#include "dmd/identifier.h" #include "dmd/mtype.h" #include "dmd/objc.h" #include "gen/irstate.h" @@ -40,6 +41,78 @@ bool objc_isSupported(const llvm::Triple &triple) { return false; } +ObjCState::ObjCState(llvm::Module &module) : module(module) { + llvm::LLVMContext &c = module.getContext(); + _class_t = llvm::StructType::create(c, "_class_t"); + _objc_cache = llvm::StructType::create(c, "_objc_cache"); + _class_ro_t = llvm::StructType::create(c, "_class_ro_t"); + __method_list_t = llvm::StructType::create(c, "__method_list_t"); + _objc_method = llvm::StructType::create(c, "_objc_method"); + _objc_protocol_list = llvm::StructType::create(c, "_objc_protocol_list"); + _protocol_t = llvm::StructType::create(c, "_protocol_t"); + _ivar_t = llvm::StructType::create(c, "_ivar_t"); + _ivar_list_t = llvm::StructType::create(c, "_ivar_list_t"); + _prop_t = llvm::StructType::create(c, "_prop_t"); + + _class_t->setBody( + {_class_t->getPointerTo(), _class_t->getPointerTo(), + _objc_cache->getPointerTo(), _class_t->getPointerTo(), + /// i8* (i8*, i8*)** + llvm::FunctionType::get( + llvm::Type::getInt8PtrTy(c), + {llvm::Type::getInt8PtrTy(c), llvm::Type::getInt8PtrTy(c)}, false) + ->getPointerTo() + ->getPointerTo(), + _class_ro_t->getPointerTo()}); + + _class_ro_t->setBody( + {llvm::Type::getInt32Ty(c), llvm::Type::getInt32Ty(c), + llvm::Type::getInt32Ty(c), llvm::Type::getInt8PtrTy(c), + llvm::Type::getInt8PtrTy(c), __method_list_t->getPointerTo(), + _objc_protocol_list->getPointerTo(), _ivar_list_t->getPointerTo(), + llvm::Type::getInt8PtrTy(c), _prop_list_t->getPointerTo()}); + + __method_list_t->setBody({llvm::Type::getInt32Ty(c), + llvm::Type::getInt32Ty(c), + llvm::ArrayType::get(_objc_method, 0)}); + + _objc_method->setBody({llvm::Type::getInt8PtrTy(c), + llvm::Type::getInt8PtrTy(c), + llvm::Type::getInt8PtrTy(c)}); + + _objc_protocol_list->setBody( + {llvm::Type::getInt64Ty(c), + llvm::ArrayType::get(_protocol_t->getPointerTo(), 0)}); + + _protocol_t->setBody({ + llvm::Type::getInt8PtrTy(c), + llvm::Type::getInt8PtrTy(c), + _objc_protocol_list->getPointerTo(), + __method_list_t->getPointerTo(), + __method_list_t->getPointerTo(), + __method_list_t->getPointerTo(), + __method_list_t->getPointerTo(), + _prop_list_t->getPointerTo(), + llvm::Type::getInt32Ty(c), + llvm::Type::getInt32Ty(c), + llvm::Type::getInt8PtrTy(c)->getPointerTo(), + llvm::Type::getInt8PtrTy(c), + _prop_list_t->getPointerTo(), + }); + + _ivar_list_t->setBody({llvm::Type::getInt32Ty(c), llvm::Type::getInt32Ty(c), + llvm::ArrayType::get(_ivar_t, 0)}); + + _ivar_t->setBody({llvm::Type::getInt64PtrTy(c), llvm::Type::getInt8PtrTy(c), + llvm::Type::getInt8PtrTy(c), llvm::Type::getInt32Ty(c), + llvm::Type::getInt32Ty(c)}); + + _prop_list_t->setBody({llvm::Type::getInt32Ty(c), llvm::Type::getInt32Ty(c), + llvm::ArrayType::get(_prop_t, 0)}); + + _prop_t->setBody({llvm::Type::getInt8PtrTy(c), llvm::Type::getInt8PtrTy(c)}); +} + LLGlobalVariable *ObjCState::getCStringVar(const char *symbol, const llvm::StringRef &str, const char *section) { @@ -91,6 +164,22 @@ LLGlobalVariable *ObjCState::getMethVarRef(const ObjcSelector &sel) { return selref; } +LLGlobalVariable *ObjCState::classVarRef(const ObjcClassReferenceExp &cre) { + llvm::StringRef s(std::string("OBJC_CLASS_$_") + + cre.classDeclaration->objc.identifier->toChars()); + + auto it = methVarRefMap.find(s); + if (it != methVarRefMap.end()) { + return it->second; + } + auto selref = new LLGlobalVariable(module, _class_t, false, LLGlobalValue::ExternalLinkage, llvm::ConstantPointerNull::get(_class_t->getPointerTo()), s); + selref->setSection("__DATA,__objc_classrefs"); + methVarRefMap[s] = selref; + retain(selref); + + return selref; +} + void ObjCState::retain(LLConstant *sym) { retainedSymbols.push_back(DtoBitCast(sym, getVoidPtrType())); } diff --git a/gen/objcgen.h b/gen/objcgen.h index a050a091077..b677565ecd1 100644 --- a/gen/objcgen.h +++ b/gen/objcgen.h @@ -15,6 +15,8 @@ #include #include "llvm/ADT/StringMap.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/DerivedTypes.h" struct ObjcSelector; namespace llvm { @@ -23,13 +25,14 @@ class GlobalVariable; class Module; class Triple; } +class ObjcClassReferenceExp; bool objc_isSupported(const llvm::Triple &triple); // Objective-C state tied to an LLVM module (object file). class ObjCState { public: - ObjCState(llvm::Module &module) : module(module) {} + ObjCState(llvm::Module &module); llvm::GlobalVariable *getMethVarRef(const ObjcSelector &sel); void finalize(); @@ -37,6 +40,18 @@ class ObjCState { private: llvm::Module &module; + llvm::StructType* _class_t; + llvm::StructType* _objc_cache; + llvm::StructType* _class_ro_t; + llvm::StructType* __method_list_t; + llvm::StructType* _objc_method; + llvm::StructType* _objc_protocol_list; + llvm::StructType* _protocol_t; + llvm::StructType* _ivar_list_t; + llvm::StructType* _ivar_t; + llvm::StructType* _prop_list_t; + llvm::StructType* _prop_t; + // symbols that shouldn't be optimized away std::vector retainedSymbols; @@ -47,6 +62,7 @@ class ObjCState { const llvm::StringRef &str, const char *section); llvm::GlobalVariable *getMethVarName(const llvm::StringRef &name); + llvm::GlobalVariable *classVarRef(const ObjcClassReferenceExp& cre); void retain(llvm::Constant *sym); void genImageInfo(); diff --git a/gen/toir.cpp b/gen/toir.cpp index 6a2c00052e0..061a4d01d15 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2805,6 +2805,17 @@ class ToElemVisitor : public Visitor { llvm_unreachable("Unknown TypeidExp argument kind"); } + void visit(ObjcClassReferenceExp *e) override { + IF_LOG Logger::print("ObjcClassReferenceExp::toElem() %s\n", e->toChars()); + LOG_SCOPE; + + auto name = std::string("OBJC_CLASS_$_") + e->classDeclaration->objc.identifier->toChars(); + + IF_LOG Logger::print("%s\n", name.data()); + // result = DtoLoad(llvm::StructType::get(gIR->context(), "_class_t")->getPointerTo(), name); + + } + //////////////////////////////////////////////////////////////////////////////// #define STUB(x) \