From f384fbb54f9562470ad85f38d9e4a98b83297e45 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Thu, 7 Mar 2019 16:43:41 +0000 Subject: [PATCH] [PR40778][Sema] Adjust addr space of operands in builtin operators. Adjust address space for references and pointer operands of builtin operators. Currently this change only fixes addr space in assignment (= and |=) operator, that is needed for the test case reported in the bug. Wider support for all other operations will follow. Differential Revision: https://reviews.llvm.org/D58719 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@355608 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 19 +++++--- test/CodeGenOpenCLCXX/addrspace-operators.cl | 46 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 test/CodeGenOpenCLCXX/addrspace-operators.cl diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ad56994df8..284642b976 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -7659,6 +7659,12 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, } } } +/// Helper function for adjusting address spaces for the pointer or reference +/// operands of builtin operators depending on the argument. +static QualType AdjustAddressSpaceForBuiltinOperandType(Sema &S, QualType T, + Expr *Arg) { + return S.Context.getAddrSpaceQualType(T, Arg->getType().getAddressSpace()); +} /// Helper function for AddBuiltinOperatorCandidates() that adds /// the volatile- and non-volatile-qualified assignment operators for the @@ -7670,15 +7676,17 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, QualType ParamTypes[2]; // T& operator=(T&, T) - ParamTypes[0] = S.Context.getLValueReferenceType(T); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, T, Args[0])); ParamTypes[1] = T; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); if (!S.Context.getCanonicalType(T).isVolatileQualified()) { // volatile T& operator=(volatile T&, T) - ParamTypes[0] - = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, S.Context.getVolatileType(T), + Args[0])); ParamTypes[1] = T; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); @@ -8573,8 +8581,9 @@ public: ParamTypes[1] = ArithmeticTypes[Right]; // Add this built-in operator as a candidate (VQ is empty). - ParamTypes[0] = - S.Context.getLValueReferenceType(ArithmeticTypes[Left]); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, ArithmeticTypes[Left], + Args[0])); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (VisibleTypeConversionsQuals.hasVolatile()) { // Add this built-in operator as a candidate (VQ is 'volatile'). diff --git a/test/CodeGenOpenCLCXX/addrspace-operators.cl b/test/CodeGenOpenCLCXX/addrspace-operators.cl new file mode 100644 index 0000000000..d212c233d1 --- /dev/null +++ b/test/CodeGenOpenCLCXX/addrspace-operators.cl @@ -0,0 +1,46 @@ +//RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s + +enum E { + a, + b, +}; + +class C { +public: + void Assign(E e) { me = e; } + void OrAssign(E e) { mi |= e; } + E me; + int mi; +}; + +__global E globE; +//CHECK-LABEL: define spir_func void @_Z3barv() +void bar() { + C c; + //CHECK: addrspacecast %class.C* %c to %class.C addrspace(4)* + //CHECK: call void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* %{{[0-9]+}}, i32 0) + c.Assign(a); + //CHECK: addrspacecast %class.C* %c to %class.C addrspace(4)* + //CHECK: call void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* %{{[0-9]+}}, i32 0) + c.OrAssign(a); + + E e; + // CHECK: store i32 1, i32* %e + e = b; + // CHECK: store i32 0, i32 addrspace(1)* @globE + globE = a; + // FIXME: Sema fails here because it thinks the types are incompatible. + //e = b; + //globE = a; +} + +//CHECK: define linkonce_odr void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* %this, i32 %e) +//CHECK: [[E:%[0-9]+]] = load i32, i32* %e.addr +//CHECK: %me = getelementptr inbounds %class.C, %class.C addrspace(4)* %this1, i32 0, i32 0 +//CHECK: store i32 [[E]], i32 addrspace(4)* %me + +//CHECK define linkonce_odr void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* %this, i32 %e) +//CHECK: [[E:%[0-9]+]] = load i32, i32* %e.addr +//CHECK: %mi = getelementptr inbounds %class.C, %class.C addrspace(4)* %this1, i32 0, i32 1 +//CHECK: [[MI:%[0-9]+]] = load i32, i32 addrspace(4)* %mi +//CHECK: %or = or i32 [[MI]], [[E]] -- 2.40.0