Index: cfe/trunk/lib/AST/MicrosoftMangle.cpp =================================================================== --- cfe/trunk/lib/AST/MicrosoftMangle.cpp +++ cfe/trunk/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("_ASCLglobal"); + break; + case LangAS::opencl_local: + Extra.mangleSourceName("_ASCLlocal"); + break; + case LangAS::opencl_constant: + Extra.mangleSourceName("_ASCLconstant"); + break; + case LangAS::opencl_private: + Extra.mangleSourceName("_ASCLprivate"); + break; + case LangAS::opencl_generic: + Extra.mangleSourceName("_ASCLgeneric"); + break; + case LangAS::cuda_device: + Extra.mangleSourceName("_ASCUdevice"); + break; + case LangAS::cuda_constant: + Extra.mangleSourceName("_ASCUconstant"); + break; + case LangAS::cuda_shared: + Extra.mangleSourceName("_ASCUshared"); + 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: cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-address-space.cpp +++ cfe/trunk/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-msvc -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-msvc -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?$_ASCLgeneric@$$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?$_ASCLprivate@$$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?$_ASCLglobal@$$CAUocl_OpaqueType@@@__clang@@@Z" +void ocl_f0(ocl_OpaqueTypePtr) { } + +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f1PU10CLconstantKc +// WINOCL-LABEL: define {{.*}}void @"?ocl_f1@@YAXPEAU?$_ASCLconstant@$$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?$_ASCLconstant@$$CAM@__clang@@PEAU?$_ASCLgeneric@$$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?$_ASCLgeneric@$$CAM@__clang@@QEAU?$_ASCLgeneric@$$CBD@2@@Z" +__generic float *ocl_f2(__generic char const * const p) { return 0;} +#endif