akhuang updated this revision to Diff 218795.
akhuang added a comment.

- Change existing tests so they still pass
- Fix so that it parses all the __ptr32/64 attributes instead of just the last 
one


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66827/new/

https://reviews.llvm.org/D66827

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/Type.h
  clang/include/clang/Basic/AddressSpaces.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/MicrosoftMangle.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Basic/Targets/AMDGPU.cpp
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Basic/Targets/SPIR.h
  clang/lib/Basic/Targets/TCE.h
  clang/lib/Basic/Targets/X86.h
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/CodeGen/ms-mixed-ptr-sizes.c
  clang/test/Sema/MicrosoftExtensions.c
  clang/test/SemaTemplate/address_space-dependent.cpp
  llvm/lib/Target/X86/X86.h
  llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
  llvm/lib/Target/X86/X86ISelLowering.cpp
  llvm/test/CodeGen/X86/mixed-ptr-sizes.ll

Index: llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
@@ -0,0 +1,110 @@
+; RUN: llc < %s | FileCheck --check-prefixes=CHECK %s
+
+; Source to regenerate:
+; struct Foo {
+;   int * __ptr32 p32;
+;   int * __ptr64 p64;
+; }
+; void test_sign_ext(struct Foo *f, int * __ptr32 i) {
+;   f->p64 = i;
+; }
+; void test_sign_ext2(struct Foo *f, int * __ptr32 __sptr i) {
+;   f->p64 = i;
+; }
+; void test_zero_ext(struct Foo *f, int * __ptr32 __uptr i) {
+;   f->p64 = i;
+; }
+; void test_trunc(struct Foo *f, int * __ptr64 i) {
+;   f->p32 = i;
+; }
+; void test_noop1(struct Foo *f, int * __ptr32 i) {
+;   f->p32 = i;
+; }
+; void test_noop2(struct Foo *f, int * __ptr64 i) {
+;   f->p64 = i;
+; }
+;
+; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -emit-llvm -x c t.cpp
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-msvc"
+
+%struct.Foo = type { i32 addrspace(270)*, i32* }
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_sign_ext(%struct.Foo* nocapture %f, i32 addrspace(270)* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_sign_ext:
+; CHECK:       movslq %edx, %rax
+entry:
+  %0 = addrspacecast i32 addrspace(270)* %i to i32*
+  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
+  store i32* %0, i32** %p64, align 8, !tbaa !2
+  ret void
+}
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_sign_ext2(%struct.Foo* nocapture %f, i32 addrspace(270)* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_sign_ext2:
+; CHECK:       movslq %edx, %rax
+entry:
+  %0 = addrspacecast i32 addrspace(270)* %i to i32*
+  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
+  store i32* %0, i32** %p64, align 8, !tbaa !2
+  ret void
+}
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_zero_ext(%struct.Foo* nocapture %f, i32 addrspace(271)* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_zero_ext:
+; CHECK:       movl %edx, %eax
+entry:
+  %0 = addrspacecast i32 addrspace(271)* %i to i32*
+  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
+  store i32* %0, i32** %p64, align 8, !tbaa !2
+  ret void
+}
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_trunc(%struct.Foo* nocapture %f, i32* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_trunc:
+; CHECK:       movl %edx, (%rcx)
+entry:
+  %0 = addrspacecast i32* %i to i32 addrspace(270)*
+  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
+  store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8, !tbaa !7
+  ret void
+}
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_noop1(%struct.Foo* nocapture %f, i32 addrspace(270)* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_noop1:
+; CHECK:       movl %edx, (%rcx)
+entry:
+  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
+  store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8, !tbaa !7
+  ret void
+}
+
+; Function Attrs: nofree norecurse nounwind writeonly
+define dso_local void @test_noop2(%struct.Foo* nocapture %f, i32* %i) local_unnamed_addr #0 {
+; CHECK-LABEL: test_noop2:
+; CHECK:       movq %rdx, 8(%rcx)
+entry:
+  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
+  store i32* %i, i32** %p64, align 8, !tbaa !2
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 2}
+!1 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git b4887f121b485fb2b6d4c1fa8296724fb78a244d)"}
+!2 = !{!3, !4, i64 8}
+!3 = !{!"Foo", !4, i64 0, !4, i64 8}
+!4 = !{!"any pointer", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C/C++ TBAA"}
+!7 = !{!3, !4, i64 0}
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- llvm/lib/Target/X86/X86ISelLowering.cpp
+++ llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -277,6 +277,10 @@
   setOperationAction(ISD::FP_TO_UINT       , MVT::i8   , Promote);
   setOperationAction(ISD::FP_TO_UINT       , MVT::i16  , Promote);
 
+  // Handle address space casts between mixed sized pointers.
+  setOperationAction(ISD::ADDRSPACECAST, MVT::i32, Custom);
+  setOperationAction(ISD::ADDRSPACECAST, MVT::i64, Custom);
+
   if (Subtarget.is64Bit()) {
     if (!Subtarget.useSoftFloat() && Subtarget.hasAVX512()) {
       // FP_TO_UINT-i32/i64 is legal for f32/f64, but custom for f80.
@@ -2353,10 +2357,21 @@
   return TargetLowering::getSafeStackPointerLocation(IRB);
 }
 
+static bool isPtrSizeOrDefaultAddrSpace(unsigned AS) {
+  return (AS == 0 || AS == X86AS::PTR32_SPTR || AS == X86AS::PTR32_UPTR ||
+          AS == X86AS::PTR64);
+}
+
 bool X86TargetLowering::isNoopAddrSpaceCast(unsigned SrcAS,
                                             unsigned DestAS) const {
   assert(SrcAS != DestAS && "Expected different address spaces!");
 
+  const TargetMachine &TM = getTargetMachine();
+  if ((isPtrSizeOrDefaultAddrSpace(SrcAS) &&
+       isPtrSizeOrDefaultAddrSpace(DestAS)) &&
+      TM.getPointerSize(SrcAS) != TM.getPointerSize(DestAS))
+    return false;
+
   return SrcAS < 256 && DestAS < 256;
 }
 
@@ -27409,6 +27424,33 @@
   return DAG.getMergeValues({Extract, NewGather.getValue(2)}, dl);
 }
 
+static SDValue LowerADDRSPACECAST(SDValue Op, SelectionDAG &DAG) {
+  SDLoc dl(Op);
+  SDValue Src = Op.getOperand(0);
+  MVT DstVT = Op.getSimpleValueType();
+
+  AddrSpaceCastSDNode *N = cast<AddrSpaceCastSDNode>(Op.getNode());
+  unsigned SrcAS = N->getSrcAddressSpace();
+  unsigned DstAS = N->getDestAddressSpace();
+
+  assert(SrcAS != DstAS &&
+         "addrspacecast must be between different address spaces");
+
+  if (isPtrSizeOrDefaultAddrSpace(SrcAS) &&
+      isPtrSizeOrDefaultAddrSpace(DstAS)) {
+    if (SrcAS == X86AS::PTR32_UPTR && DstVT == MVT::i64) {
+      Op = DAG.getNode(ISD::ZERO_EXTEND, dl, DstVT, Src);
+    } else if (DstVT == MVT::i64) {
+      Op = DAG.getNode(ISD::SIGN_EXTEND, dl, DstVT, Src);
+    } else if (DstVT == MVT::i32) {
+      Op = DAG.getNode(ISD::TRUNCATE, dl, DstVT, Src);
+    }
+  } else {
+    report_fatal_error("Bad address space in addrspacecast");
+  }
+  return Op;
+}
+
 SDValue X86TargetLowering::LowerGC_TRANSITION_START(SDValue Op,
                                                     SelectionDAG &DAG) const {
   // TODO: Eventually, the lowering of these nodes should be informed by or
@@ -27571,6 +27613,8 @@
   case ISD::GC_TRANSITION_START:
                                 return LowerGC_TRANSITION_START(Op, DAG);
   case ISD::GC_TRANSITION_END:  return LowerGC_TRANSITION_END(Op, DAG);
+  case ISD::ADDRSPACECAST:
+    return LowerADDRSPACECAST(Op, DAG);
   }
 }
 
@@ -28493,6 +28537,32 @@
     Results.push_back(Res.getValue(1));
     return;
   }
+  case ISD::ADDRSPACECAST: {
+    SDValue Src = N->getOperand(0);
+    EVT DstVT = N->getValueType(0);
+    AddrSpaceCastSDNode *CastN = cast<AddrSpaceCastSDNode>(N);
+    unsigned SrcAS = CastN->getSrcAddressSpace();
+    unsigned DstAS = CastN->getDestAddressSpace();
+
+    assert(SrcAS != DstAS &&
+           "addrspacecast must be between different address spaces");
+
+    SDValue Res;
+    if (isPtrSizeOrDefaultAddrSpace(SrcAS) &&
+        isPtrSizeOrDefaultAddrSpace(DstAS)) {
+      if (SrcAS == X86AS::PTR32_UPTR && DstVT == MVT::i64)
+        Res = DAG.getNode(ISD::ZERO_EXTEND, dl, DstVT, Src);
+      else if (DstVT == MVT::i64)
+        Res = DAG.getNode(ISD::SIGN_EXTEND, dl, DstVT, Src);
+      else
+        Res = DAG.getNode(ISD::TRUNCATE, dl, DstVT, Src);
+    } else {
+      report_fatal_error("Unrecognized addrspacecast type legalization");
+    }
+
+    Results.push_back(Res);
+    return;
+  }
   }
 }
 
Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
===================================================================
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2219,12 +2219,11 @@
   AM.Scale = cast<ConstantSDNode>(Mgs->getScale())->getZExtValue();
 
   unsigned AddrSpace = cast<MemSDNode>(Parent)->getPointerInfo().getAddrSpace();
-  // AddrSpace 256 -> GS, 257 -> FS, 258 -> SS.
-  if (AddrSpace == 256)
+  if (AddrSpace == X86AS::GS)
     AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
-  if (AddrSpace == 257)
+  if (AddrSpace == X86AS::FS)
     AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
-  if (AddrSpace == 258)
+  if (AddrSpace == X86AS::SS)
     AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
 
   SDLoc DL(N);
Index: llvm/lib/Target/X86/X86.h
===================================================================
--- llvm/lib/Target/X86/X86.h
+++ llvm/lib/Target/X86/X86.h
@@ -146,4 +146,15 @@
 void initializeX86SpeculativeLoadHardeningPassPass(PassRegistry &);
 } // End llvm namespace
 
+namespace X86AS {
+enum : unsigned {
+  GS = 256,
+  FS = 257,
+  SS = 258,
+  PTR32_SPTR = 270,
+  PTR32_UPTR = 271,
+  PTR64 = 272
+};
+}
+
 #endif
Index: clang/test/SemaTemplate/address_space-dependent.cpp
===================================================================
--- clang/test/SemaTemplate/address_space-dependent.cpp
+++ clang/test/SemaTemplate/address_space-dependent.cpp
@@ -43,7 +43,7 @@
 
 template <long int I>
 void tooBig() {
-  __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388598)}}
+  __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388595)}}
 }
 
 template <long int I>
@@ -101,7 +101,7 @@
   car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}}
   HasASTemplateFields<1> HASTF;
   neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}}
-  correct<0x7FFFF6>();
+  correct<0x7FFFF3>();
   tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650>' requested here}}
 
   __attribute__((address_space(1))) char *x;
Index: clang/test/Sema/MicrosoftExtensions.c
===================================================================
--- clang/test/Sema/MicrosoftExtensions.c
+++ clang/test/Sema/MicrosoftExtensions.c
@@ -143,12 +143,14 @@
 int * __sptr __sptr wrong3; // expected-warning {{attribute '__sptr' is already applied}}
 
 // It is illegal to overload based on the type attribute.
+// Expect conflicting types warning instead of redefinition warning because
+// pointers with type attributes are lowered to different types.
 void ptr_func(int * __ptr32 i) {}  // expected-note {{previous definition is here}}
-void ptr_func(int * __ptr64 i) {} // expected-error {{redefinition of 'ptr_func'}}
+void ptr_func(int * __ptr64 i) {} // expected-error {{conflicting types for 'ptr_func'}}
 
 // It is also illegal to overload based on the pointer type attribute.
 void ptr_func2(int * __sptr __ptr32 i) {}  // expected-note {{previous definition is here}}
-void ptr_func2(int * __uptr __ptr32 i) {} // expected-error {{redefinition of 'ptr_func2'}}
+void ptr_func2(int * __uptr __ptr32 i) {} // expected-error {{conflicting types for 'ptr_func2'}}
 
 int * __sptr __ptr32 __sptr wrong4; // expected-warning {{attribute '__sptr' is already applied}}
 
Index: clang/test/CodeGen/ms-mixed-ptr-sizes.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/ms-mixed-ptr-sizes.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -fms-extensions -O0 \
+// RUN:    -emit-llvm -o - %s | FileCheck %s --check-prefix=X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fms-extensions -O0 \
+// RUN:    -emit-llvm -o - %s | FileCheck %s --check-prefix=X64
+
+// X86: %p32 = alloca i32*, align 4
+// X86: %p64 = alloca i32 addrspace(272)*, align 8
+// X86: %p32s = alloca i32*, align 4
+// X86: %p32u = alloca i32 addrspace(271)*, align 4
+// X86: %p64s = alloca i32 addrspace(272)*, align 8
+// X86: %p64u = alloca i32 addrspace(272)*, align 8
+// X86: %ps = alloca i32*, align 4
+// X86: %pu = alloca i32 addrspace(271)*, align 4
+
+// X64: %p32 = alloca i32 addrspace(270)*, align 4
+// X64: %p64 = alloca i32*, align 8
+// X64: %p32s = alloca i32 addrspace(270)*, align 4
+// X64: %p32u = alloca i32 addrspace(271)*, align 4
+// X64: %p64s = alloca i32*, align 8
+// X64: %p64u = alloca i32*, align 8
+// X64: %ps = alloca i32*, align 8
+// X64: %pu = alloca i32*, align 8
+
+void test() {
+  int * __ptr32 p32;
+  int * __ptr64 p64;
+  int * __ptr32 __sptr p32s;
+  int * __ptr32 __uptr p32u;
+  int * __ptr64 __sptr p64s;
+  int * __ptr64 __uptr p64u;
+  int * __sptr ps;
+  int * __uptr pu;
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -6462,6 +6462,8 @@
   attr::Kind NewAttrKind = A->getKind();
   QualType Desugared = Type;
   const AttributedType *AT = dyn_cast<AttributedType>(Type);
+  llvm::SmallSet<attr::Kind, 2> Attrs;
+  Attrs.insert(NewAttrKind);
   while (AT) {
     attr::Kind CurAttrKind = AT->getAttrKind();
 
@@ -6488,7 +6490,8 @@
     }
 
     Desugared = AT->getEquivalentType();
-    AT = dyn_cast<AttributedType>(Desugared);
+    AT = dyn_cast<AttributedType>(AT->getModifiedType());
+    Attrs.insert(CurAttrKind);
   }
 
   // Pointer type qualifiers can only operate on pointer types, but not
@@ -6506,7 +6509,26 @@
     return true;
   }
 
-  Type = State.getAttributedType(A, Type, Type);
+  // Add address space qualifier.
+  LangAS ASIdx = LangAS::Default;
+  uint64_t PtrWidth = S.Context.getTargetInfo().getPointerWidth(0);
+  if (PtrWidth == 32) {
+    if (Attrs.count(attr::Ptr64))
+      ASIdx = LangAS::ptr64;
+    else if (Attrs.count(attr::UPtr))
+      ASIdx = LangAS::ptr32_uptr;
+  } else if (PtrWidth == 64 && Attrs.count(attr::Ptr32)) {
+    if (Attrs.count(attr::UPtr))
+      ASIdx = LangAS::ptr32_uptr;
+    else
+      ASIdx = LangAS::ptr32_sptr;
+  }
+
+  QualType Pointee = Type->getPointeeType();
+  if (ASIdx != LangAS::Default)
+    Pointee = S.Context.getAddrSpaceQualType(
+        S.Context.removeAddrSpaceQualType(Pointee), ASIdx);
+  Type = State.getAttributedType(A, Type, S.Context.getPointerType(Pointee));
   return false;
 }
 
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -2871,6 +2871,14 @@
        O && (O != E); ++O, ++N) {
     if (!Context.hasSameType(O->getUnqualifiedType(),
                              N->getUnqualifiedType())) {
+
+      // Treat pointers with pointer size qualifiers as equivalent to pointers
+      // without those qualifiers, so pointer size qualifiers cannot be used to
+      // overload.
+      if (Context.hasPtrSizeSimilarType(O->getUnqualifiedType(),
+                                        N->getUnqualifiedType()))
+        continue;
+
       if (ArgPos)
         *ArgPos = O - OldType->param_type_begin();
       return false;
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -22,6 +22,21 @@
 namespace clang {
 namespace targets {
 
+static const unsigned X86AddrSpaceMap[] = {
+    0,   // Default
+    0,   // opencl_global
+    0,   // opencl_local
+    0,   // opencl_constant
+    0,   // opencl_private
+    0,   // opencl_generic
+    0,   // cuda_device
+    0,   // cuda_constant
+    0,   // cuda_shared
+    270, // ptr32_sptr
+    271, // ptr32_uptr
+    272  // ptr64
+};
+
 // X86 target abstract base class; x86-32 and x86-64 are very close, so
 // most of the implementation can be shared.
 class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
@@ -45,6 +60,7 @@
     AMD3DNowAthlon
   } MMX3DNowLevel = NoMMX3DNow;
   enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
+  enum AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 };
 
   bool HasAES = false;
   bool HasVAES = false;
@@ -130,6 +146,7 @@
   X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
       : TargetInfo(Triple) {
     LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+    AddrSpaceMap = &X86AddrSpaceMap;
   }
 
   const char *getLongDoubleMangling() const override {
@@ -328,6 +345,18 @@
   void setSupportedOpenCLOpts() override {
     getSupportedOpenCLOpts().supportAll();
   }
+
+  uint64_t getPointerWidthV(unsigned AddrSpace) const override {
+    if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr)
+      return 32;
+    if (AddrSpace == ptr64)
+      return 64;
+    return PointerWidth;
+  }
+
+  uint64_t getPointerAlignV(unsigned AddrSpace) const override {
+    return getPointerWidthV(AddrSpace);
+  }
 };
 
 // X86-32 generic target
Index: clang/lib/Basic/Targets/TCE.h
===================================================================
--- clang/lib/Basic/Targets/TCE.h
+++ clang/lib/Basic/Targets/TCE.h
@@ -39,7 +39,10 @@
     0, // opencl_generic
     0, // cuda_device
     0, // cuda_constant
-    0  // cuda_shared
+    0, // cuda_shared
+    0, // ptr32_sptr
+    0, // ptr32_uptr
+    0, // ptr64
 };
 
 class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo {
Index: clang/lib/Basic/Targets/SPIR.h
===================================================================
--- clang/lib/Basic/Targets/SPIR.h
+++ clang/lib/Basic/Targets/SPIR.h
@@ -30,7 +30,10 @@
     4, // opencl_generic
     0, // cuda_device
     0, // cuda_constant
-    0  // cuda_shared
+    0, // cuda_shared
+    0, // ptr32_sptr
+    0, // ptr32_uptr
+    0  // ptr64
 };
 
 class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
Index: clang/lib/Basic/Targets/NVPTX.h
===================================================================
--- clang/lib/Basic/Targets/NVPTX.h
+++ clang/lib/Basic/Targets/NVPTX.h
@@ -33,6 +33,9 @@
     1, // cuda_device
     4, // cuda_constant
     3, // cuda_shared
+    0, // ptr32_sptr
+    0, // ptr32_uptr
+    0  // ptr64
 };
 
 /// The DWARF address class. Taken from
Index: clang/lib/Basic/Targets/AMDGPU.cpp
===================================================================
--- clang/lib/Basic/Targets/AMDGPU.cpp
+++ clang/lib/Basic/Targets/AMDGPU.cpp
@@ -46,7 +46,10 @@
     Generic,  // opencl_generic
     Global,   // cuda_device
     Constant, // cuda_constant
-    Local     // cuda_shared
+    Local,    // cuda_shared
+    Generic,  // ptr32_sptr
+    Generic,  // ptr32_uptr
+    Generic   // ptr64
 };
 
 const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
@@ -58,7 +61,11 @@
     Generic,  // opencl_generic
     Global,   // cuda_device
     Constant, // cuda_constant
-    Local     // cuda_shared
+    Local,    // cuda_shared
+    Generic,  // ptr32_sptr
+    Generic,  // ptr32_uptr
+    Generic   // ptr64
+
 };
 } // namespace targets
 } // namespace clang
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1819,6 +1819,15 @@
       case LangAS::cuda_shared:
         OS << "__shared__";
         break;
+      case LangAS::ptr32_sptr:
+        OS << "__ptr32_sptr";
+        break;
+      case LangAS::ptr32_uptr:
+        OS << "__ptr32_uptr";
+        break;
+      case LangAS::ptr64:
+        OS << "__ptr64";
+        break;
       default:
         OS << "__attribute__((address_space(";
         OS << toTargetAddressSpace(addrspace);
Index: clang/lib/AST/MicrosoftMangle.cpp
===================================================================
--- clang/lib/AST/MicrosoftMangle.cpp
+++ clang/lib/AST/MicrosoftMangle.cpp
@@ -279,8 +279,6 @@
 
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
-  // FIXME: If we add support for __ptr32/64 qualifiers, then we should push
-  // this check into mangleQualifiers().
   const bool PointersAre64Bit;
 
 public:
@@ -335,6 +333,13 @@
     return ND == Structor || getStructor(ND) == Structor;
   }
 
+  bool is64BitPointer(Qualifiers Quals) const {
+    LangAS AddrSpace = Quals.getAddressSpace();
+    return AddrSpace == LangAS::ptr64 ||
+           (PointersAre64Bit && !(AddrSpace == LangAS::ptr32_sptr ||
+                                  AddrSpace == LangAS::ptr32_uptr));
+  }
+
   void mangleUnqualifiedName(const NamedDecl *ND) {
     mangleUnqualifiedName(ND, ND->getDeclName());
   }
@@ -1661,6 +1666,7 @@
   //         ::= 3 # ?
   //         ::= 4 # ?
   //         ::= 5 # not really based
+
   bool HasConst = Quals.hasConst(),
        HasVolatile = Quals.hasVolatile();
 
@@ -1709,8 +1715,10 @@
 
 void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
                                                          QualType PointeeType) {
-  if (PointersAre64Bit &&
-      (PointeeType.isNull() || !PointeeType->isFunctionType()))
+  // Check if this is a defulat 64-bit pointer or has __ptr64 qualifier.
+  bool is64Bit = PointeeType.isNull() ? PointersAre64Bit :
+    is64BitPointer(PointeeType.getQualifiers());
+  if (is64Bit && (PointeeType.isNull() || !PointeeType->isFunctionType()))
     Out << 'E';
 
   if (Quals.hasRestrict())
@@ -2603,10 +2611,13 @@
   manglePointerCVQualifiers(Quals);
   manglePointerExtQualifiers(Quals, PointeeType);
 
-  if (PointeeType.getQualifiers().hasAddressSpace())
-    mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
-  else
+  // For pointer size address spaces, go down the same type mangling path as
+  // non address space types.
+  LangAS AddrSpace = PointeeType.getQualifiers().getAddressSpace();
+  if (isPtrSizeOrDefaultAddressSpace(AddrSpace))
     mangleType(PointeeType, Range);
+  else
+    mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
 }
 
 void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -2266,6 +2266,10 @@
       case LangAS::cuda_device:     ASString = "CUdevice";   break;
       case LangAS::cuda_constant:   ASString = "CUconstant"; break;
       case LangAS::cuda_shared:     ASString = "CUshared";   break;
+      //  <ptrsize-addrspace> ::= [ "ptr32_sptr" | "ptr32_uptr" | "ptr64" ]
+      case LangAS::ptr32_sptr: ASString = "ptr32_sptr"; break;
+      case LangAS::ptr32_uptr: ASString = "ptr32_uptr"; break;
+      case LangAS::ptr64: ASString = "ptr64"; break;
       }
     }
     if (!ASString.empty())
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -789,15 +789,18 @@
     // The fake address space map must have a distinct entry for each
     // language-specific address space.
     static const unsigned FakeAddrSpaceMap[] = {
-      0, // Default
-      1, // opencl_global
-      3, // opencl_local
-      2, // opencl_constant
-      0, // opencl_private
-      4, // opencl_generic
-      5, // cuda_device
-      6, // cuda_constant
-      7  // cuda_shared
+        0, // Default
+        1, // opencl_global
+        3, // opencl_local
+        2, // opencl_constant
+        0, // opencl_private
+        4, // opencl_generic
+        5, // cuda_device
+        6, // cuda_constant
+        7, // cuda_shared
+        8, // ptr32_sptr
+        9, // ptr32_uptr
+        10 // ptr64
     };
     return &FakeAddrSpaceMap;
   } else {
@@ -5314,6 +5317,31 @@
   }
 }
 
+bool ASTContext::hasPtrSizeSimilarType(QualType T1, QualType T2) {
+  while (true) {
+    const PointerType *T1Ptr = dyn_cast<PointerType>(T1);
+    const PointerType *T2Ptr = dyn_cast<PointerType>(T2);
+
+    if (!T1Ptr || !T2Ptr)
+      return hasSameType(T1, T2);
+
+    Qualifiers Quals1, Quals2;
+    T1 = getUnqualifiedArrayType(T1Ptr->getPointeeType(), Quals1);
+    T2 = getUnqualifiedArrayType(T2Ptr->getPointeeType(), Quals2);
+
+    if (isPtrSizeOrDefaultAddressSpace(Quals1.getAddressSpace()))
+      Quals1.removeAddressSpace();
+    if (isPtrSizeOrDefaultAddressSpace(Quals2.getAddressSpace()))
+      Quals2.removeAddressSpace();
+
+    if (Quals1 != Quals2)
+      return false;
+
+    if (hasSameType(T1, T2))
+      return true;
+  }
+}
+
 DeclarationNameInfo
 ASTContext::getNameForTemplate(TemplateName Name,
                                SourceLocation NameLoc) const {
Index: clang/include/clang/Basic/AddressSpaces.h
===================================================================
--- clang/include/clang/Basic/AddressSpaces.h
+++ clang/include/clang/Basic/AddressSpaces.h
@@ -42,6 +42,11 @@
   cuda_constant,
   cuda_shared,
 
+  // Pointer size and extension address spaces.
+  ptr32_sptr,
+  ptr32_uptr,
+  ptr64,
+
   // This denotes the count of language-specific address spaces and also
   // the offset added to the target-specific address spaces, which are usually
   // specified by address space attributes __attribute__(address_space(n))).
@@ -68,6 +73,11 @@
                              (unsigned)LangAS::FirstTargetAddressSpace);
 }
 
+inline bool isPtrSizeOrDefaultAddressSpace(LangAS AS) {
+  return (AS == LangAS::Default || AS == LangAS::ptr32_sptr ||
+          AS == LangAS::ptr32_uptr || AS == LangAS::ptr64);
+}
+
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -472,7 +472,10 @@
     return A == B ||
            // Otherwise in OpenCLC v2.0 s6.5.5: every address space except
            // for __constant can be used as __generic.
-           (A == LangAS::opencl_generic && B != LangAS::opencl_constant);
+           (A == LangAS::opencl_generic && B != LangAS::opencl_constant) ||
+           // Consider mixed sized pointers to be equivalent.
+           (isPtrSizeOrDefaultAddressSpace(A) &&
+            isPtrSizeOrDefaultAddressSpace(B));
   }
 
   /// Returns true if the address space in these qualifiers is equal to or
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -2361,6 +2361,10 @@
   /// Determine if two types are similar, ignoring only CVR qualifiers.
   bool hasCvrSimilarType(QualType T1, QualType T2);
 
+  /// Determine if two types are similar, ignoring only pointer size address
+  /// space.
+  bool hasPtrSizeSimilarType(QualType T1, QualType T2);
+
   /// Retrieves the "canonical" nested name specifier for a
   /// given nested name specifier.
   ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to