Skip to content

Commit

Permalink
[OpenCL] Enable address spaces for references in C++
Browse files Browse the repository at this point in the history
Added references to the addr spaces deduction and enabled
CL2.0 features (program scope variables and storage class
qualifiers) to work in C++ mode too.

Fixed several address space conversion issues in CodeGen 
for references.

Differential Revision: https://reviews.llvm.org/D53764

llvm-svn: 347059
  • Loading branch information
Anastasia Stulova committed Nov 16, 2018
1 parent d125316 commit 0430794
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 31 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -9631,6 +9631,10 @@ class Sema {
AssignmentAction Action,
CheckedConversionKind CCK);

ExprResult PerformQualificationConversion(
Expr *E, QualType Ty, ExprValueKind VK = VK_RValue,
CheckedConversionKind CCK = CCK_ImplicitConversion);

/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).

Expand Down
19 changes: 12 additions & 7 deletions clang/lib/AST/Expr.cpp
Expand Up @@ -1634,13 +1634,18 @@ bool CastExpr::CastConsistency() const {
assert(getSubExpr()->getType()->isFunctionType());
goto CheckNoBasePath;

case CK_AddressSpaceConversion:
assert(getType()->isPointerType() || getType()->isBlockPointerType());
assert(getSubExpr()->getType()->isPointerType() ||
getSubExpr()->getType()->isBlockPointerType());
assert(getType()->getPointeeType().getAddressSpace() !=
getSubExpr()->getType()->getPointeeType().getAddressSpace());
LLVM_FALLTHROUGH;
case CK_AddressSpaceConversion: {
auto Ty = getType();
auto SETy = getSubExpr()->getType();
assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
if (!isGLValue())
Ty = Ty->getPointeeType();
if (!isGLValue())
SETy = SETy->getPointeeType();
assert(!Ty.isNull() && !SETy.isNull() &&
Ty.getAddressSpace() != SETy.getAddressSpace());
goto CheckNoBasePath;
}
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Expand Up @@ -4163,7 +4163,6 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
case CK_FixedPointCast:
case CK_FixedPointToBoolean:
Expand Down Expand Up @@ -4260,6 +4259,14 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(),
CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
case CK_AddressSpaceConversion: {
LValue LV = EmitLValue(E->getSubExpr());
QualType DestTy = getContext().getPointerType(E->getType());
llvm::Value *V = getTargetHooks().performAddrSpaceCast(
*this, LV.getPointer(), E->getSubExpr()->getType().getAddressSpace(),
DestTy.getAddressSpace(), ConvertType(DestTy));
return MakeNaturalAlignPointeeAddrLValue(V, DestTy);
}
case CK_ObjCObjectLValueCast: {
LValue LV = EmitLValue(E->getSubExpr());
Address V = Builder.CreateElementBitCast(LV.getAddress(),
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/DeclSpec.cpp
Expand Up @@ -566,14 +566,16 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
// these storage-class specifiers.
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
// OpenCL C++ v1.0 s2.9 restricts register.
if (S.getLangOpts().OpenCL &&
!S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
case SCS_static:
if (S.getLangOpts().OpenCLVersion < 120) {
DiagID = diag::err_opencl_unknown_type_specifier;
if (S.getLangOpts().OpenCLVersion < 120 &&
!S.getLangOpts().OpenCLCPlusPlus) {
DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = getSpecifierName(SC);
return true;
}
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Expand Up @@ -7352,19 +7352,23 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
}
// OpenCL v1.2 s6.5 - All program scope variables must be declared in the
// OpenCL C v1.2 s6.5 - All program scope variables must be declared in the
// __constant address space.
// OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
// OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static
// variables inside a function can also be declared in the global
// address space.
// OpenCL C++ v1.0 s2.5 inherits rule from OpenCL C v2.0 and allows local
// address space additionally.
// FIXME: Add local AS for OpenCL C++.
if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
NewVD->hasExternalStorage()) {
if (!T->isSamplerT() &&
!(T.getAddressSpace() == LangAS::opencl_constant ||
(T.getAddressSpace() == LangAS::opencl_global &&
getLangOpts().OpenCLVersion == 200))) {
(getLangOpts().OpenCLVersion == 200 ||
getLangOpts().OpenCLCPlusPlus)))) {
int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1;
if (getLangOpts().OpenCLVersion == 200)
if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus)
Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
<< Scope << "global or constant";
else
Expand Down
22 changes: 18 additions & 4 deletions clang/lib/Sema/SemaExprCXX.cpp
Expand Up @@ -4271,10 +4271,24 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Qualification: {
// The qualification keeps the category of the inner expression, unless the
// target type isn't a reference.
ExprValueKind VK = ToType->isReferenceType() ?
From->getValueKind() : VK_RValue;
From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
CK_NoOp, VK, /*BasePath=*/nullptr, CCK).get();
ExprValueKind VK =
ToType->isReferenceType() ? From->getValueKind() : VK_RValue;

CastKind CK = CK_NoOp;

if (ToType->isReferenceType() &&
ToType->getPointeeType().getAddressSpace() !=
From->getType().getAddressSpace())
CK = CK_AddressSpaceConversion;

if (ToType->isPointerType() &&
ToType->getPointeeType().getAddressSpace() !=
From->getType()->getPointeeType().getAddressSpace())
CK = CK_AddressSpaceConversion;

From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), CK, VK,
/*BasePath=*/nullptr, CCK)
.get();

if (SCS.DeprecatedStringLiteralToCharPtr &&
!getLangOpts().WritableStrings) {
Expand Down
31 changes: 19 additions & 12 deletions clang/lib/Sema/SemaInit.cpp
Expand Up @@ -7258,12 +7258,20 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
return CreateMaterializeTemporaryExpr(E->getType(), E, false);
}

ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
QualType *ResultType) {
ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty,
ExprValueKind VK,
CheckedConversionKind CCK) {
CastKind CK = (Ty.getAddressSpace() != E->getType().getAddressSpace())
? CK_AddressSpaceConversion
: CK_NoOp;
return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK);
}

ExprResult InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
QualType *ResultType) {
if (Failed()) {
Diagnose(S, Entity, Kind, Args);
return ExprError();
Expand Down Expand Up @@ -7651,12 +7659,11 @@ InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionRValue: {
// Perform a qualification conversion; these can never go wrong.
ExprValueKind VK =
Step->Kind == SK_QualificationConversionLValue ?
VK_LValue :
(Step->Kind == SK_QualificationConversionXValue ?
VK_XValue :
VK_RValue);
CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK);
Step->Kind == SK_QualificationConversionLValue
? VK_LValue
: (Step->Kind == SK_QualificationConversionXValue ? VK_XValue
: VK_RValue);
CurInit = S.PerformQualificationConversion(CurInit.get(), Step->Type, VK);
break;
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Expand Up @@ -7181,7 +7181,8 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
bool IsPointee =
ChunkIndex > 0 &&
(D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer ||
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer);
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer ||
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference);
bool IsFuncReturnType =
ChunkIndex > 0 &&
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function;
Expand Down
46 changes: 46 additions & 0 deletions clang/test/CodeGenOpenCLCXX/address-space-deduction.cl
@@ -0,0 +1,46 @@
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s -check-prefixes=COMMON,PTR
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - -DREF | FileCheck %s -check-prefixes=COMMON,REF

#ifdef REF
#define PTR &
#define ADR(x) x
#else
#define PTR *
#define ADR(x) &x
#endif

//COMMON: @glob = addrspace(1) global i32
int glob;
//PTR: @glob_p = addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*)
//REF: @glob_p = addrspace(1) global i32 addrspace(4)* null
int PTR glob_p = ADR(glob);

//COMMON: @_ZZ3fooi{{P|R}}U3AS4iE6loc_st = internal addrspace(1) global i32
//PTR: @_ZZ3fooiPU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiPU3AS4iE6loc_st to i32 addrspace(4)*)
//REF: @_ZZ3fooiRU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* null
//COMMON: @loc_ext_p = external addrspace(1) {{global|constant}} i32 addrspace(4)*
//COMMON: @loc_ext = external addrspace(1) global i32

//REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @glob_p

//COMMON: define spir_func i32 @_Z3fooi{{P|R}}U3AS4i(i32 %par, i32 addrspace(4)*{{.*}} %par_p)
int foo(int par, int PTR par_p){
//COMMON: %loc = alloca i32
int loc;
//COMMON: %loc_p = alloca i32 addrspace(4)*
//COMMON: %loc_p_const = alloca i32*
//COMMON: [[GAS:%[0-9]+]] = addrspacecast i32* %loc to i32 addrspace(4)*
//COMMON: store i32 addrspace(4)* [[GAS]], i32 addrspace(4)** %loc_p
int PTR loc_p = ADR(loc);
//COMMON: store i32* %loc, i32** %loc_p_const
const __private int PTR loc_p_const = ADR(loc);

// CHECK directives for the following code are located above.
static int loc_st;
//REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiRU3AS4iE6loc_st to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @_ZZ3fooiRU3AS4iE8loc_st_p
static int PTR loc_st_p = ADR(loc_st);
extern int loc_ext;
extern int PTR loc_ext_p;
(void)loc_ext_p;
return loc_ext;
}

0 comments on commit 0430794

Please sign in to comment.