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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76717 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 346b670..de44e69 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -143,7 +143,8 @@
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 @@
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 @@
}
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 @@
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 @@
}
}
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::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 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 @@
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 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 @@
} 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 LV =
LValue::MakeAddr(V,
Field->getType().getCVRQualifiers()|CVRQualifiers,
- attr);
+ attr,
+ Field->getType().getAddressSpace());
return LV;
}
@@ -1085,7 +1099,9 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
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 @@
// 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 @@
// FIXME: can this be volatile?
return LValue::MakeAddr(RV.getAggregateAddr(),
E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()));
+ getContext().getObjCGCAttrKind(E->getType()),
+ E->getType().getAddressSpace());
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index e4192d6..32e5afc 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -173,7 +173,8 @@
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;
}
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 820e1bd..9e93708 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -163,7 +163,8 @@
// objective-c's gc attributes
unsigned ObjCType : 2;
-
+ // address space
+ unsigned AddressSpace;
private:
static void SetQualifiers(unsigned Qualifiers, LValue& R) {
@@ -195,7 +196,9 @@
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 @@
}
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;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 145a928..6ad2040 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -794,6 +794,7 @@
// 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 @@
= 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 @@
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);
diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c
new file mode 100644
index 0000000..e7c655a
--- /dev/null
+++ b/test/CodeGen/address-space-field1.c
@@ -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;
+}
diff --git a/test/CodeGen/address-space-field2.c b/test/CodeGen/address-space-field2.c
new file mode 100644
index 0000000..8b09d57
--- /dev/null
+++ b/test/CodeGen/address-space-field2.c
@@ -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;
+ }
+}
diff --git a/test/CodeGen/address-space-field3.c b/test/CodeGen/address-space-field3.c
new file mode 100644
index 0000000..f0b9dba
--- /dev/null
+++ b/test/CodeGen/address-space-field3.c
@@ -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];
+ }
+}
diff --git a/test/CodeGen/address-space-field4.c b/test/CodeGen/address-space-field4.c
new file mode 100644
index 0000000..d258f61
--- /dev/null
+++ b/test/CodeGen/address-space-field4.c
@@ -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;
+}