public:
llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
+ llvm::Type *IvarOffsetVarTy;
/// ObjectPtrTy - LLVM type for object handles (typeof(id))
llvm::Type *ObjectPtrTy;
Int8PtrTy = CGM.Int8PtrTy;
Int8PtrPtrTy = CGM.Int8PtrPtrTy;
+ // arm64 targets use "int" ivar offset variables. All others,
+ // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
+ if (CGM.getTarget().getTriple().getArch() == llvm::Triple::arm64)
+ IvarOffsetVarTy = IntTy;
+ else
+ IvarOffsetVarTy = LongTy;
+
ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
// struct _ivar_t {
- // unsigned long int *offset; // pointer to ivar offset location
+ // unsigned [long] int *offset; // pointer to ivar offset location
// char *name;
// char *type;
// uint32_t alignment;
// uint32_t size;
// }
- IvarnfABITy =
- llvm::StructType::create("struct._ivar_t",
- llvm::PointerType::getUnqual(LongTy),
- Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
+ IvarnfABITy = llvm::StructType::create(
+ "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
+ Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
// struct _ivar_list_t {
// uint32 entsize; // sizeof(struct _ivar_t)
llvm::GlobalVariable *IvarOffsetGV =
CGM.getModule().getGlobalVariable(Name);
if (!IvarOffsetGV)
- IvarOffsetGV =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- Name);
+ IvarOffsetGV = new llvm::GlobalVariable(
+ CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
+ llvm::GlobalValue::ExternalLinkage, 0, Name);
return IvarOffsetGV;
}
const ObjCIvarDecl *Ivar,
unsigned long int Offset) {
llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
- IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
- Offset));
+ IvarOffsetGV->setInitializer(
+ llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
IvarOffsetGV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
+ CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy));
// FIXME: This matches gcc, but shouldn't the visibility be set on the use as
// well (i.e., in ObjCIvarOffsetVariable).
/// implementation. The return value has type
/// IvarListnfABIPtrTy.
/// struct _ivar_t {
-/// unsigned long int *offset; // pointer to ivar offset location
+/// unsigned [long] int *offset; // pointer to ivar offset location
/// char *name;
/// char *type;
/// uint32_t alignment;
unsigned CVRQualifiers) {
ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
-
- if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
- if (llvm::LoadInst *LI = cast<llvm::LoadInst>(Offset))
- LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
- llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>()));
-
return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Offset);
}
CodeGen::CodeGenFunction &CGF,
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) {
- return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
+ llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
+ IvarOffsetValue = CGF.Builder.CreateLoad(IvarOffsetValue, "ivar");
+ if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
+ cast<llvm::LoadInst>(IvarOffsetValue)
+ ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
+ llvm::MDNode::get(VMContext, ArrayRef<llvm::Value *>()));
+
+ // This could be 32bit int or 64bit integer depending on the architecture.
+ // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
+ // as this is what caller always expectes.
+ if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
+ IvarOffsetValue = CGF.Builder.CreateIntCast(
+ IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
+ return IvarOffsetValue;
}
static void appendSelectorForMessageRefTable(std::string &buffer,