akhuang created this revision.
akhuang added reviewers: rnk, rsmith.
Herald added subscribers: llvm-commits, cfe-commits, erik.pilkington, 
hiraditya, nhaehnle, jvesely, jholewinski.
Herald added projects: clang, LLVM.

Previously, these qualifiers were being parsed but otherwise ignored.
This change makes it so that an address space is added to specify whether the 
pointer is
32-bit or 64-bit and whether it is sign extended or zero extended.

In the backend, the address space casts are lowered to the corresponding
sign/zero extension or truncation.

The data layout for the address spaces was changed in 
https://reviews.llvm.org/D64931

Related to https://bugs.llvm.org/show_bug.cgi?id=42359


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66827

Files:
  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
  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,108 @@
+; RUN: llc < %s | FileCheck --check-prefixes=CHECK %s
+
+; Source to regenerate:
+; struct Foo {
+;   int * __ptr32 p32;
+;   int * __ptr64 p64;
+; }
+; void use_foo(Foo *f);
+; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
+;   f->p64 = i;
+;   use_foo(f);
+; }
+; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
+;   f->p64 = i;
+;   use_foo(f);
+; }
+; void test_trunc(foo *f, int * __ptr64 i) {
+;   f->p32 = i;
+;   use_foo(f);
+; }
+; void test_noop1(foo *f, int * __ptr32 i) {
+;   f->p32 = i;
+;   use_foo(f);
+; }
+; void test_noop2(foo *f, int * __ptr64 i) {
+;   f->p64 = i;
+;   use_foo(f);
+; }
+;
+; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S 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* }
+declare dso_local void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo*) local_unnamed_addr #1
+
+; Function Attrs: nounwind
+define dso_local void @"?test_sign_ext@@YAXPEAUFoo@@PEAU?$_ASPtr32_sptr@$$CAH@__clang@@@Z"(%struct.Foo* %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
+  tail call void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo* %f) #2
+  ret void
+}
+
+; Function Attrs: nounwind
+define dso_local void @"?test_zero_ext@@YAXPEAUFoo@@PEAU?$_ASPtr32_uptr@$$CAH@__clang@@@Z"(%struct.Foo* %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
+  tail call void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo* %f) #2
+  ret void
+}
+
+; Function Attrs: nounwind
+define dso_local void @"?test_trunc@@YAXPEAUFoo@@PEAH@Z"(%struct.Foo* %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
+  tail call void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo* %f) #2
+  ret void
+}
+
+; Function Attrs: nounwind
+define dso_local void @"?test_noop1@@YAXPEAUFoo@@PEAU?$_ASPtr32_sptr@$$CAH@__clang@@@Z"(%struct.Foo* %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
+  tail call void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo* %f) #2
+  ret void
+}
+
+; Function Attrs: nounwind
+define dso_local void @"?test_noop2@@YAXPEAUFoo@@PEAH@Z"(%struct.Foo* %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
+  tail call void @"?use_foo@@YAXPEAUFoo@@@Z"(%struct.Foo* %f) #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 e7b4a1629519fc9910b49e59ea4b13040631b2b5)"}
+!2 = !{!3, !4, i64 8}
+!3 = !{!"?AUFoo@@", !4, i64 0, !4, i64 8}
+!4 = !{!"any pointer", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple 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;
 }
 
@@ -27397,6 +27412,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
@@ -27559,6 +27601,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);
   }
 }
 
@@ -28481,6 +28525,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
@@ -2218,12 +2218,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/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();
 
@@ -6489,6 +6491,7 @@
 
     Desugared = AT->getEquivalentType();
     AT = dyn_cast<AttributedType>(Desugared);
+    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())) {
+      const PointerType *OldTypePtr =
+          dyn_cast<PointerType>(O->getUnqualifiedType());
+      const PointerType *NewTypePtr =
+          dyn_cast<PointerType>(N->getUnqualifiedType());
+      if (OldTypePtr && NewTypePtr)
+        if (OldTypePtr->isAddressSpacePtrSize(*NewTypePtr))
+          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;
@@ -131,6 +147,7 @@
   X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
       : TargetInfo(Triple) {
     LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+    AddrSpaceMap = &X86AddrSpaceMap;
   }
 
   const char *getLongDoubleMangling() const override {
@@ -329,6 +346,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
@@ -1870,6 +1870,15 @@
     case LangAS::cuda_shared:
       Extra.mangleSourceName("_ASCUshared");
       break;
+    case LangAS::ptr32_sptr:
+      Extra.mangleSourceName("_ASPtr32_sptr");
+      break;
+    case LangAS::ptr32_uptr:
+      Extra.mangleSourceName("_ASPtr32_uptr");
+      break;
+    case LangAS::ptr64:
+      Extra.mangleSourceName("_ASPtr64");
+      break;
     }
   }
 
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 {
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
@@ -2588,6 +2591,13 @@
            otherQuals.isAddressSpaceSupersetOf(thisQuals);
   }
 
+  bool isAddressSpacePtrSize(const PointerType &other) const {
+    Qualifiers thisQuals = PointeeType.getQualifiers();
+    Qualifiers otherQuals = other.getPointeeType().getQualifiers();
+    return (isPtrSizeOrDefaultAddressSpace(thisQuals.getAddressSpace()) &&
+            isPtrSizeOrDefaultAddressSpace(otherQuals.getAddressSpace()));
+  }
+
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to