Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -311,6 +311,7 @@ void mangleTagTypeKind(TagTypeKind TK); void mangleArtificialTagType(TagTypeKind TK, StringRef UnqualifiedName, ArrayRef NestedNames = None); + void mangleAddressSpaceType(QualType T, Qualifiers Quals, SourceRange Range); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); void mangleFunctionType(const FunctionType *T, @@ -1777,12 +1778,77 @@ } } +void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T, + Qualifiers Quals, + SourceRange Range) { + // Address space is mangled as an unqualified templated type in the __clang + // namespace. The demangled version of this is: + // In the case of a language specific address space: + // __clang::struct AS_[language_addr_space] + // where: + // ::= | + // ::= "CL" [ "global" | "local" | "constant" | + // "private"| "generic" ] + // ::= "CU" [ "device" | "constant" | "shared" ] + // Note that the above were chosen to match the Itanium mangling for this. + // + // In the case of a non-language specific address space: + // __clang::struct AS_ + assert(Quals.hasAddressSpace() && "Not valid without address space"); + llvm::SmallString<32> ASMangling; + llvm::raw_svector_ostream Stream(ASMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Stream << "?$"; + + LangAS AS = Quals.getAddressSpace(); + if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { + unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); + Extra.mangleSourceName("AS_"); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS), + /*IsBoolean*/ false); + } else { + switch (AS) { + default: + llvm_unreachable("Not a language specific address space"); + case LangAS::opencl_global: + Extra.mangleSourceName("AS_CLglobal"); + break; + case LangAS::opencl_local: + Extra.mangleSourceName("AS_CLlocal"); + break; + case LangAS::opencl_constant: + Extra.mangleSourceName("AS_CLconstant"); + break; + case LangAS::opencl_private: + Extra.mangleSourceName("AS_CLprivate"); + break; + case LangAS::opencl_generic: + Extra.mangleSourceName("AS_CLgeneric"); + break; + case LangAS::cuda_device: + Extra.mangleSourceName("AS_CUdevice"); + break; + case LangAS::cuda_constant: + Extra.mangleSourceName("AS_CUconstant"); + break; + case LangAS::cuda_shared: + Extra.mangleSourceName("AS_CUshared"); + break; + } + } + + Extra.mangleType(T, Range, QMM_Escape); + mangleQualifiers(Qualifiers(), false); + mangleArtificialTagType(TTK_Struct, ASMangling, {"__clang"}); +} + void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { // Don't use the canonical types. MSVC includes things like 'const' on // pointer arguments to function pointers that canonicalization strips away. T = T.getDesugaredType(getASTContext()); Qualifiers Quals = T.getLocalQualifiers(); + if (const ArrayType *AT = getASTContext().getAsArrayType(T)) { // If there were any Quals, getAsArrayType() pushed them onto the array // element type. @@ -2488,7 +2554,11 @@ QualType PointeeType = T->getPointeeType(); manglePointerCVQualifiers(Quals); manglePointerExtQualifiers(Quals, PointeeType); - mangleType(PointeeType, Range); + + if (PointeeType.getQualifiers().hasAddressSpace()) + mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range); + else + mangleType(PointeeType, Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, Index: test/CodeGenCXX/mangle-address-space.cpp =================================================================== --- test/CodeGenCXX/mangle-address-space.cpp +++ test/CodeGenCXX/mangle-address-space.cpp @@ -1,15 +1,64 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKNOOCL +// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-pc -o - %s | FileCheck %s --check-prefixes=WIN,WINNOOCL +// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKOCL +// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple x86_64-windows-pc -o - %s | FileCheck %s --check-prefixes=WIN,WINOCL -// CHECK-LABEL: define {{.*}}void @_Z2f0Pc +// CHECKNOOCL-LABEL: define {{.*}}void @_Z2f0Pc +// WINNOOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAD@Z" +// CHECKOCL-LABEL: define {{.*}}void @_Z2f0PU9CLgenericc +// WINOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$AS_CLgeneric@$$CAD@__clang@@@Z" void f0(char *p) { } // CHECK-LABEL: define {{.*}}void @_Z2f0PU3AS1c +// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$AS_@$00$$CAD@__clang@@@Z" void f0(char __attribute__((address_space(1))) *p) { } struct OpaqueType; typedef OpaqueType __attribute__((address_space(100))) * OpaqueTypePtr; // CHECK-LABEL: define {{.*}}void @_Z2f0PU5AS10010OpaqueType +// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$AS_@$0GE@$$CAUOpaqueType@@@__clang@@@Z" void f0(OpaqueTypePtr) { } // CHECK-LABEL: define {{.*}}void @_Z2f1PU3AS1Kc -void f1(char __attribute__((address_space(1))) const *p) {} \ No newline at end of file +// WIN-LABEL: define {{.*}}void @"?f1@@YAXPEAU?$AS_@$00$$CBD@__clang@@@Z" +void f1(char __attribute__((address_space(1))) const *p) {} + +// Ensure we can do return values, which change in MS mode. +// CHECK-LABEL: define {{.*}}float addrspace(1)* @_Z2f1PU3AS2Kc +// WIN-LABEL: define {{.*}}float addrspace(1)* @"?f1@@YAPEAU?$AS_@$00$$CAM@__clang@@PEAU?$AS_@$01$$CBD@2@@Z" +__attribute__((address_space(1))) float *f1(char __attribute__((address_space(2))) const *p) { return 0;} + +#if !defined(__OPENCL_CPP_VERSION__) +// Return value of address space without a pointer is invalid in opencl. +// Ensure we skip return values, since non-pointers aren't supposed to have an AS. +// CHECKNOOCL-LABEL: define {{.*}}float @_Z2f2PU3AS2Kc +// WINNOOCL-LABEL: define {{.*}}float @"?f2@@YA?AMQEAU?$AS_@$01$$CBD@__clang@@@Z" +__attribute__((address_space(1))) float f2(char __attribute__((address_space(2))) const * const p) { return 0;} +#endif + +#ifdef __OPENCL_CPP_VERSION__ +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU9CLprivatec +// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$AS_CLprivate@$$CAD@__clang@@@Z" +void ocl_f0(char __private *p) { } + +struct ocl_OpaqueType; +typedef ocl_OpaqueType __global * ocl_OpaqueTypePtr; + +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU8CLglobal14ocl_OpaqueType +// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$AS_CLglobal@$$CAUocl_OpaqueType@@@__clang@@@Z" +void ocl_f0(ocl_OpaqueTypePtr) { } + +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f1PU10CLconstantKc +// WINOCL-LABEL: define {{.*}}void @"?ocl_f1@@YAXPEAU?$AS_CLconstant@$$CBD@__clang@@@Z" +void ocl_f1(char __constant const *p) {} + +// Ensure we can do return values, which change in MS mode. +// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f1PU9CLgenericKc +// WINOCL-LABEL: define {{.*}}float* @"?ocl_f1@@YAPEAU?$AS_CLconstant@$$CAM@__clang@@PEAU?$AS_CLgeneric@$$CBD@2@@Z" +__constant float *ocl_f1(char __generic const *p) { return 0;} + +// Ensure we skip return values, since non-pointers aren't supposed to have an AS. +// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f2PU9CLgenericKc +// WINOCL-LABEL: define {{.*}}float* @"?ocl_f2@@YAPEAU?$AS_CLgeneric@$$CAM@__clang@@QEAU?$AS_CLgeneric@$$CBD@2@@Z" +__generic float *ocl_f2(__generic char const * const p) { return 0;} +#endif Index: test/CodeGenOpenCL/address-spaces-mangling.cl =================================================================== --- test/CodeGenOpenCL/address-spaces-mangling.cl +++ test/CodeGenOpenCL/address-spaces-mangling.cl @@ -3,6 +3,11 @@ // RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=NOASMANG,NOASMAN10 %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=NOASMANG,NOASMAN20 %s +// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=yes -triple x86_64-windows-pc -emit-llvm -o - | FileCheck -check-prefixes=MS_ASMANG,MS_ASMAN10 %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=yes -triple x86_64-windows-pc -emit-llvm -o - | FileCheck -check-prefixes=MS_ASMANG,MS_ASMAN20 %s +// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple x86_64-windows-pc -emit-llvm -o - | FileCheck -check-prefixes=MS_NOASMANG,MS_NOASMAN10 %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=no -triple x86_64-windows-pc -emit-llvm -o - | FileCheck -check-prefixes=MS_NOASMANG,MS_NOASMAN20 %s + // We check that the address spaces are mangled the same in both version of OpenCL // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s @@ -16,6 +21,10 @@ // ASMANG20: @_Z2ffPU3AS4i // NOASMANG10: @_Z2ffPi // NOASMANG20: @_Z2ffPU9CLgenerici +// MS_ASMANG10: @_Z2ffPi +// MS_ASMANG20: @_Z2ffPU3AS4i +// MS_NOASMANG10: @_Z2ffPi +// MS_NOASMANG20: @_Z2ffPU9CLgenerici // OCL-20-DAG: @_Z2ffPU3AS4i // OCL-12-DAG: @_Z2ffPi @@ -23,6 +32,8 @@ void f(private int *arg) { } // ASMANG: @_Z1fPi // NOASMANG: @_Z1fPU9CLprivatei +// MS_ASMANG: @_Z1fPi +// MS_NOASMANG: @_Z1fPU9CLprivatei // OCL-20-DAG: @_Z1fPi // OCL-12-DAG: @_Z1fPi @@ -30,6 +41,8 @@ void f(global int *arg) { } // ASMANG: @_Z1fPU3AS1i // NOASMANG: @_Z1fPU8CLglobali +// MS_ASMANG: @_Z1fPU3AS1i +// MS_NOASMANG: @_Z1fPU8CLglobali // OCL-20-DAG: @_Z1fPU3AS1i // OCL-12-DAG: @_Z1fPU3AS1i @@ -37,6 +50,8 @@ void f(local int *arg) { } // ASMANG: @_Z1fPU3AS3i // NOASMANG: @_Z1fPU7CLlocali +// MS_ASMANG: @_Z1fPU3AS3i +// MS_NOASMANG: @_Z1fPU7CLlocali // OCL-20-DAG: @_Z1fPU3AS3i // OCL-12-DAG: @_Z1fPU3AS3i @@ -44,6 +59,8 @@ void f(constant int *arg) { } // ASMANG: @_Z1fPU3AS2i // NOASMANG: @_Z1fPU10CLconstanti +// MS_ASMANG: @_Z1fPU3AS2i +// MS_NOASMANG: @_Z1fPU10CLconstanti // OCL-20-DAG: @_Z1fPU3AS2i // OCL-12-DAG: @_Z1fPU3AS2i @@ -52,5 +69,7 @@ void f(generic int *arg) { } // ASMANG20: @_Z1fPU3AS4i // NOASMANG20: @_Z1fPU9CLgenerici +// MS_ASMANG20: @_Z1fPU3AS4i +// MS_NOASMANG20: @_Z1fPU9CLgenerici // OCL-20-DAG: @_Z1fPU3AS4i #endif