From: Mon P Wang Date: Wed, 22 Jul 2009 03:08:17 +0000 (+0000) Subject: Preserve address space information through member accesses, e.g., X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6a38a47bf3908ab2183d7946498138d8b07c886;p=clang 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 346b6703d3..de44e69721 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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(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()); } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index e4192d66f3..32e5afce51 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -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; } diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 820e1bd6c3..9e937085a9 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -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; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 145a928716..6ad2040b9d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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::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); diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c new file mode 100644 index 0000000000..e7c655a8fe --- /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 0000000000..8b09d57b38 --- /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 0000000000..f0b9dba982 --- /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 0000000000..d258f614e6 --- /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; +}