Preserve address space information through member accesses, e.g.,

__attribute__((address_space(1))) struct {int arr[ 3 ]; }  *p1;
   ... = p1->arr[2];  // load from address space 1

llvm-svn: 76717
This commit is contained in:
Mon P Wang
2009-07-22 03:08:17 +00:00
parent 18366cbe97
commit acedf7768f
8 changed files with 148 additions and 27 deletions

View File

@@ -143,7 +143,8 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
llvm::Type *Ty = VMContext.getPointerTypeUnqual(ConvertType(E->getType()));
return LValue::MakeAddr(VMContext.getUndef(Ty),
E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
/// EmitLValue - Emit code to compute a designator that specifies the location
@@ -676,7 +677,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
else {
llvm::Value *V = LocalDeclMap[VD];
@@ -699,7 +701,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr);
LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr,
E->getType().getAddressSpace());
}
LValue::SetObjCNonGC(LV, NonGCable);
return LV;
@@ -708,7 +711,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
if (LV.isObjCStrong())
LV.SetGlobalObjCRef(LV, true);
return LV;
@@ -727,14 +731,16 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
}
return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
else if (const ImplicitParamDecl *IPD =
dyn_cast<ImplicitParamDecl>(E->getDecl())) {
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
@@ -745,7 +751,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
return LValue::MakeAddr(GetAddrOfBlockDecl(E),
E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
@@ -763,7 +770,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
T.getCVRQualifiers(),
getContext().getObjCGCAttrKind(T));
getContext().getObjCGCAttrKind(T),
ExprTy.getAddressSpace());
// We should not generate __weak write barrier on indirect reference
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
@@ -780,7 +788,9 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
Idx, "idx"),
ExprTy.getCVRQualifiers());
ExprTy.getCVRQualifiers(),
QualType::GCNone,
ExprTy.getAddressSpace());
}
}
@@ -906,7 +916,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
LValue LV = LValue::MakeAddr(Address,
T.getCVRQualifiers(),
getContext().getObjCGCAttrKind(T));
getContext().getObjCGCAttrKind(T),
E->getBase()->getType().getAddressSpace());
if (getContext().getLangOptions().ObjC1 &&
getContext().getLangOptions().getGCMode() != LangOptions::NonGC)
LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
@@ -936,7 +947,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
} else {
const PointerType *PT = E->getBase()->getType()->getAsPointerType();
llvm::Value *Ptr = EmitScalarExpr(E->getBase());
Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers());
Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers(),
QualType::GCNone,
PT->getPointeeType().getAddressSpace());
}
// Encode the element access list into a vector of unsigned indices.
@@ -1076,7 +1089,8 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
LValue LV =
LValue::MakeAddr(V,
Field->getType().getCVRQualifiers()|CVRQualifiers,
attr);
attr,
Field->getType().getAddressSpace());
return LV;
}
@@ -1085,7 +1099,9 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral");
const Expr* InitExpr = E->getInitializer();
LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers());
LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers(),
QualType::GCNone,
E->getType().getAddressSpace());
if (E->getType()->isComplexType()) {
EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
@@ -1112,7 +1128,8 @@ LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) {
EmitAggExpr(E, Temp, false);
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
@@ -1136,7 +1153,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
EmitAnyExpr(E->getSubExpr(), Temp, false);
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
//===--------------------------------------------------------------------===//
@@ -1187,7 +1205,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
EmitAggExpr(E, Temp, false);
// FIXME: Are these qualifiers correct?
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
@@ -1199,19 +1218,22 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
"reference type!");
return LValue::MakeAddr(RV.getScalarVal(), E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
return LValue::MakeAddr(RV.getAggregateAddr(),
E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
// FIXME: This shouldn't require another copy.
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers());
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
QualType::GCNone, E->getType().getAddressSpace());
}
LValue
@@ -1223,7 +1245,8 @@ CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) {
LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp");
EmitCXXConstructExpr(Temp, E);
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers());
return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
QualType::GCNone, E->getType().getAddressSpace());
}
LValue
@@ -1241,7 +1264,8 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
// FIXME: can this be volatile?
return LValue::MakeAddr(RV.getAggregateAddr(),
E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -1304,7 +1328,8 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
// FIXME: can this be volatile?
return LValue::MakeAddr(RV.getAggregateAddr(),
E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
}

View File

@@ -173,7 +173,8 @@ void AggExprEmitter::VisitCStyleCastExpr(CStyleCastExpr *E) {
CGF.getContext().getPointerType(E->getSubExpr()->getType());
llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr,
CGF.ConvertType(PtrTy));
EmitInitializationToLValue(E->getSubExpr(), LValue::MakeAddr(CastPtr, 0));
EmitInitializationToLValue(E->getSubExpr(),
LValue::MakeAddr(CastPtr, 0));
return;
}

View File

@@ -163,7 +163,8 @@ class LValue {
// objective-c's gc attributes
unsigned ObjCType : 2;
// address space
unsigned AddressSpace;
private:
static void SetQualifiers(unsigned Qualifiers, LValue& R) {
@@ -195,7 +196,9 @@ public:
bool isGlobalObjCRef() const { return GlobalObjCRef; }
bool isObjCWeak() const { return ObjCType == Weak; }
bool isObjCStrong() const { return ObjCType == Strong; }
unsigned getAddressSpace() const { return AddressSpace; }
static void SetObjCIvar(LValue& R, bool iValue) {
R.Ivar = iValue;
}
@@ -254,11 +257,13 @@ public:
}
static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers,
QualType::GCAttrTypes GCAttrs = QualType::GCNone) {
QualType::GCAttrTypes GCAttrs = QualType::GCNone,
unsigned AddressSpace = 0) {
LValue R;
R.LVType = Simple;
R.V = V;
SetQualifiers(Qualifiers,R);
R.AddressSpace = AddressSpace;
SetObjCType(GCAttrs, R);
return R;
}

View File

@@ -794,6 +794,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *Result = BaseObjectExpr;
unsigned BaseAddrSpace = BaseObjectExpr->getType().getAddressSpace();
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
FI != FIEnd; ++FI) {
@@ -803,6 +804,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
= MemberType.getCVRQualifiers() | ExtraQuals;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
if (BaseAddrSpace != MemberType.getAddressSpace())
MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
MarkDeclarationReferenced(Loc, *FI);
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
@@ -2175,16 +2178,18 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
BaseExpr, OpLoc);
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
// FIXME: Handle address space modifiers
QualType MemberType = FD->getType();
if (const ReferenceType *Ref = MemberType->getAsReferenceType())
MemberType = Ref->getPointeeType();
else {
unsigned BaseAddrSpace = BaseType.getAddressSpace();
unsigned combinedQualifiers =
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
if (FD->isMutable())
combinedQualifiers &= ~QualType::Const;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
if (BaseAddrSpace != MemberType.getAddressSpace())
MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
}
MarkDeclarationReferenced(MemberLoc, FD);

View File

@@ -0,0 +1,20 @@
// RUN: clang-cc -emit-llvm < %s -o %t &&
// RUN: grep addrspace\(1\) %t | count 9 &&
// RUN: grep addrspace\(2\) %t | count 9
// Check that we don't lose the address space when accessing a member
// of a structure.
#define __addr1 __attribute__((address_space(1)))
#define __addr2 __attribute__((address_space(2)))
typedef struct S {
int a;
int b;
} S;
void test_addrspace(__addr1 S* p1, __addr2 S*p2) {
// swap
p1->a = p2->b;
p1->b = p2->a;
}

View File

@@ -0,0 +1,22 @@
// RUN: clang-cc -emit-llvm < %s -o %t &&
// RUN: grep addrspace\(1\) %t | count 8 &&
// RUN: grep addrspace\(2\) %t | count 9
// Check that we don't lose the address space when accessing an array element
// inside a structure.
#define __addr1 __attribute__((address_space(1)))
#define __addr2 __attribute__((address_space(2)))
typedef struct S {
int arr[ 3 ];
} S;
void test_addrspace(__addr1 S* p1, __addr2 S*p2, int* val, int n) {
for (int i=0; i < 3; ++i) {
int t = val[i];
p1->arr[i] = t;
for (int j=0; j < n; ++j)
p2[j].arr[i] = t;
}
}

View File

@@ -0,0 +1,20 @@
// RUN: clang-cc -emit-llvm < %s -o %t &&
// RUN: grep addrspace\(1\) %t | count 8 &&
// RUN: grep addrspace\(2\) %t | count 8
// Check that we don't lose the address space when accessing an array element
// inside a structure.
#define __addr1 __attribute__((address_space(1)))
#define __addr2 __attribute__((address_space(2)))
typedef struct S {
int arr[ 3 ];
} S;
void test_addrspace(__addr1 S* p1, __addr2 S*p2, int* val, int n) {
for (int i=0; i < 3; ++i) {
int t = val[i];
p1->arr[i] = p2->arr[i];
}
}

View File

@@ -0,0 +1,23 @@
// RUN: clang-cc -emit-llvm < %s -o %t &&
// RUN: grep addrspace\(2\) %t | count 4
// RUN: grep addrspace\(3\) %t | count 4
// Check the load and store are using the correct address space to access
// the variables.
#define __addr1 __attribute__((address_space(1)))
#define __addr2 __attribute__((address_space(2)))
#define __addr3 __attribute__((address_space(3)))
typedef struct Pair {
__addr2 int* a;
__addr3 int* b;
} Pair;
typedef struct S {
Pair arr[ 3 ];
} S;
void test_addrspace(__addr1 S* p1, __addr1 S* p2) {
*p1->arr[0].a = *p2->arr[1].b;
}