Fix pointer addressing and array subscripting of Objective-C interface
types. - I broke this in the switch to representing interfaces with opaque types. - <rdar://problem/6822660> clang crashes on subscript of interface in 32-bit mode llvm-svn: 70009
This commit is contained in:
parent
e75de95408
commit
ef2ffbc390
|
@ -809,8 +809,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
|
||||||
Idx = Builder.CreateIntCast(Idx, llvm::IntegerType::get(LLVMPointerWidth),
|
Idx = Builder.CreateIntCast(Idx, llvm::IntegerType::get(LLVMPointerWidth),
|
||||||
IdxSigned, "idxprom");
|
IdxSigned, "idxprom");
|
||||||
|
|
||||||
// We know that the pointer points to a type of the correct size, unless the
|
// We know that the pointer points to a type of the correct size,
|
||||||
// size is a VLA.
|
// unless the size is a VLA or Objective-C interface.
|
||||||
|
llvm::Value *Address = 0;
|
||||||
if (const VariableArrayType *VAT =
|
if (const VariableArrayType *VAT =
|
||||||
getContext().getAsVariableArrayType(E->getType())) {
|
getContext().getAsVariableArrayType(E->getType())) {
|
||||||
llvm::Value *VLASize = VLASizeMap[VAT];
|
llvm::Value *VLASize = VLASizeMap[VAT];
|
||||||
|
@ -823,10 +824,25 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
|
||||||
Idx = Builder.CreateUDiv(Idx,
|
Idx = Builder.CreateUDiv(Idx,
|
||||||
llvm::ConstantInt::get(Idx->getType(),
|
llvm::ConstantInt::get(Idx->getType(),
|
||||||
BaseTypeSize));
|
BaseTypeSize));
|
||||||
|
Address = Builder.CreateGEP(Base, Idx, "arrayidx");
|
||||||
|
} else if (const ObjCInterfaceType *OIT =
|
||||||
|
dyn_cast<ObjCInterfaceType>(E->getType())) {
|
||||||
|
llvm::Value *InterfaceSize =
|
||||||
|
llvm::ConstantInt::get(Idx->getType(),
|
||||||
|
getContext().getTypeSize(OIT) / 8);
|
||||||
|
|
||||||
|
Idx = Builder.CreateMul(Idx, InterfaceSize);
|
||||||
|
|
||||||
|
llvm::Type *i8PTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||||
|
Address = Builder.CreateGEP(Builder.CreateBitCast(Base, i8PTy),
|
||||||
|
Idx, "arrayidx");
|
||||||
|
Address = Builder.CreateBitCast(Address, Base->getType());
|
||||||
|
} else {
|
||||||
|
Address = Builder.CreateGEP(Base, Idx, "arrayidx");
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType T = E->getBase()->getType()->getAsPointerType()->getPointeeType();
|
QualType T = E->getBase()->getType()->getAsPointerType()->getPointeeType();
|
||||||
LValue LV = LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx"),
|
LValue LV = LValue::MakeAddr(Address,
|
||||||
T.getCVRQualifiers(),
|
T.getCVRQualifiers(),
|
||||||
getContext().getObjCGCAttrKind(T));
|
getContext().getObjCGCAttrKind(T));
|
||||||
if (getContext().getLangOptions().ObjC1 &&
|
if (getContext().getLangOptions().ObjC1 &&
|
||||||
|
|
|
@ -968,14 +968,27 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
|
||||||
Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
|
Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QualType ElementType = PT->getPointeeType();
|
||||||
|
// Handle interface types, which are not represented with a concrete
|
||||||
|
// type.
|
||||||
|
if (const ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(ElementType)) {
|
||||||
|
llvm::Value *InterfaceSize =
|
||||||
|
llvm::ConstantInt::get(Idx->getType(),
|
||||||
|
CGF.getContext().getTypeSize(OIT) / 8);
|
||||||
|
Idx = Builder.CreateMul(Idx, InterfaceSize);
|
||||||
|
const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||||
|
Value *Casted = Builder.CreateBitCast(Ptr, i8Ty);
|
||||||
|
Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr");
|
||||||
|
return Builder.CreateBitCast(Res, Ptr->getType());
|
||||||
|
}
|
||||||
|
|
||||||
// Explicitly handle GNU void* and function pointer arithmetic
|
// Explicitly handle GNU void* and function pointer arithmetic
|
||||||
// extensions. The GNU void* casts amount to no-ops since our void*
|
// extensions. The GNU void* casts amount to no-ops since our void*
|
||||||
// type is i8*, but this is future proof.
|
// type is i8*, but this is future proof.
|
||||||
const QualType ElementType = PT->getPointeeType();
|
|
||||||
if (ElementType->isVoidType() || ElementType->isFunctionType()) {
|
if (ElementType->isVoidType() || ElementType->isFunctionType()) {
|
||||||
const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||||
Value *Casted = Builder.CreateBitCast(Ptr, i8Ty);
|
Value *Casted = Builder.CreateBitCast(Ptr, i8Ty);
|
||||||
Value *Res = Builder.CreateGEP(Casted, Idx, "sub.ptr");
|
Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr");
|
||||||
return Builder.CreateBitCast(Res, Ptr->getType());
|
return Builder.CreateBitCast(Res, Ptr->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,6 +1028,20 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
|
||||||
}
|
}
|
||||||
Idx = Builder.CreateNeg(Idx, "sub.ptr.neg");
|
Idx = Builder.CreateNeg(Idx, "sub.ptr.neg");
|
||||||
|
|
||||||
|
// Handle interface types, which are not represented with a concrete
|
||||||
|
// type.
|
||||||
|
if (const ObjCInterfaceType *OIT =
|
||||||
|
dyn_cast<ObjCInterfaceType>(LHSElementType)) {
|
||||||
|
llvm::Value *InterfaceSize =
|
||||||
|
llvm::ConstantInt::get(Idx->getType(),
|
||||||
|
CGF.getContext().getTypeSize(OIT) / 8);
|
||||||
|
Idx = Builder.CreateMul(Idx, InterfaceSize);
|
||||||
|
const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||||
|
Value *LHSCasted = Builder.CreateBitCast(Ops.LHS, i8Ty);
|
||||||
|
Value *Res = Builder.CreateGEP(LHSCasted, Idx, "add.ptr");
|
||||||
|
return Builder.CreateBitCast(Res, Ops.LHS->getType());
|
||||||
|
}
|
||||||
|
|
||||||
// Explicitly handle GNU void* and function pointer arithmetic
|
// Explicitly handle GNU void* and function pointer arithmetic
|
||||||
// extensions. The GNU void* casts amount to no-ops since our
|
// extensions. The GNU void* casts amount to no-ops since our
|
||||||
// void* type is i8*, but this is future proof.
|
// void* type is i8*, but this is future proof.
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// RUN: clang-cc -triple i386-apple-darwin9 -O3 -emit-llvm -o %t %s &&
|
||||||
|
// RUN: grep 'ret i32 385' %t
|
||||||
|
|
||||||
|
void *alloca();
|
||||||
|
|
||||||
|
@interface I0 {
|
||||||
|
@public
|
||||||
|
int iv0;
|
||||||
|
int iv1;
|
||||||
|
int iv2;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
static int f0(I0 *a0) {
|
||||||
|
return (*(a0 + 2)).iv0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f1(I0 *a0) {
|
||||||
|
return a0[2].iv1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f2(I0 *a0) {
|
||||||
|
return (*(a0 - 1)).iv2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int g0(void) {
|
||||||
|
I0 *a = alloca(sizeof(*a) * 4);
|
||||||
|
a[2].iv0 = 5;
|
||||||
|
a[2].iv1 = 7;
|
||||||
|
a[2].iv2 = 11;
|
||||||
|
return f0(a) * f1(a) * f2(&a[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue