mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
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:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
20
clang/test/CodeGen/address-space-field1.c
Normal file
20
clang/test/CodeGen/address-space-field1.c
Normal 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;
|
||||
}
|
||||
22
clang/test/CodeGen/address-space-field2.c
Normal file
22
clang/test/CodeGen/address-space-field2.c
Normal 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;
|
||||
}
|
||||
}
|
||||
20
clang/test/CodeGen/address-space-field3.c
Normal file
20
clang/test/CodeGen/address-space-field3.c
Normal 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];
|
||||
}
|
||||
}
|
||||
23
clang/test/CodeGen/address-space-field4.c
Normal file
23
clang/test/CodeGen/address-space-field4.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user