diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-27 19:38:51 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-27 19:38:51 +0000 |
commit | 98abf4bd3526a00a0e5cf71a9462c181f97b1c81 (patch) | |
tree | 5e2453d62d16cfe9907912368875a1ea25af6d0f /lib/CodeGen/CGObjCMac.cpp | |
parent | bac51fa0fd4b9adf20d3c4a65bbbb67061fe7266 (diff) |
ivar meta-data generation for nonfragile-abi.
Still more work to do in this area.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63126 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 9365535079..eef74083da 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -562,7 +562,13 @@ private: /// implementation. The return value has type MethodListnfABITy. llvm::Constant *EmitMethodList(const std::string &Name, const char *Section, - const ConstantVector &Methods); + const ConstantVector &Methods); + /// EmitIvarList - Emit the ivar list for the given + /// implementation. If ForClass is true the list of class ivars + /// (i.e. metaclass ivars) is emitted, otherwise the list of + /// interface ivars will be emitted. The return value has type + /// IvarListnfABIPtrTy. + llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); @@ -3157,7 +3163,10 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( Values[ 5] = EmitMethodList(MethodListName, ".section __DATA,__data,regular,no_dead_strip", Methods); Values[ 6] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); - Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); + if (flags & CLS_META) + Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); + else + Values[ 7] = EmitIvarList(ID); Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, @@ -3505,6 +3514,82 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList( return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); } + +/// EmitIvarList - Emit the ivar list for the given +/// implementation. If ForClass is true the list of class ivars +/// (i.e. metaclass ivars) is emitted, otherwise the list of +/// interface ivars will be emitted. The return value has type +/// IvarListnfABIPtrTy. +/// struct _ivar_t { +/// unsigned long int *offset; // pointer to ivar offset location +/// char *name; +/// char *type; +/// uint32_t alignment; +/// uint32_t size; +/// } +/// struct _ivar_list_t { +/// uint32 entsize; // sizeof(struct _ivar_t) +/// uint32 count; +/// struct _iver_t list[count]; +/// } +/// +llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( + const ObjCImplementationDecl *ID) { + + std::vector<llvm::Constant*> Ivars, Ivar(5); + + const ObjCInterfaceDecl *OID = ID->getClassInterface(); + assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); + + for(ObjCInterfaceDecl::ivar_iterator i = OID->ivar_begin(), + e = OID->ivar_end(); i != e; ++i) { + FieldDecl *Field = *i; + // FIXME. Put the offset symbol address after code gen. + // for non-fragile ivar access is in. + Ivar[0] = llvm::Constant::getNullValue( + llvm::PointerType::getUnqual(ObjCTypes.LongTy)); + if (Field->getIdentifier()) + Ivar[1] = GetMethodVarName(Field->getIdentifier()); + else + Ivar[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); + std::string TypeStr; + CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); + Ivar[2] = GetMethodVarType(TypeStr); + const llvm::Type *FieldTy = + CGM.getTypes().ConvertTypeForMem(Field->getType()); + unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy); + unsigned Align = CGM.getContext().getPreferredTypeAlign( + Field->getType().getTypePtr()) >> 3; + Align = llvm::Log2_32(Align); + Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); + Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); + Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar)); + } + // Return null for empty list. + if (Ivars.empty()) + return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); + std::vector<llvm::Constant*> Values(3); + unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.IvarnfABITy); + Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); + Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); + llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, + Ivars.size()); + Values[2] = llvm::ConstantArray::get(AT, Ivars); + llvm::Constant *Init = llvm::ConstantStruct::get(Values); + const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(Init->getType(), false, + llvm::GlobalValue::InternalLinkage, + Init, + Prefix + OID->getNameAsString(), + &CGM.getModule()); + + GV->setSection(".section __DATA,__data,regular,no_dead_strip"); + + UsedGlobals.push_back(GV); + return llvm::ConstantExpr::getBitCast(GV, + ObjCTypes.IvarListnfABIPtrTy); +} /* *** */ CodeGen::CGObjCRuntime * |