Author: Akimasa Watanuki
Date: 2026-10-21T13:52:50-05:00
New Revision: a171e0d7dfca389be0f319fea7c8e66e86ac4be3

URL: 
https://github.com/llvm/llvm-project/commit/a171e0d7dfca389be0f319fea7c8e66e86ac4be3
DIFF: 
https://github.com/llvm/llvm-project/commit/a171e0d7dfca389be0f319fea7c8e66e86ac4be3.diff

LOG: [CIR] Reject language address spaces in DirectToLLVM pointer conversion 
(#224239)

Reject unlowered language address spaces in pointer types when bypassing
TargetLowering. Guard pointer-producing lowerings, including generated
patterns, so failed conversions report legalization failures instead of
silently selecting address space zero or constructing invalid LLVM
operations.

Assisted-by: Codex / GPT-6

Added: 
    clang/test/CIR/Lowering/opaque-pointer-address-spaces.cir

Modified: 
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/test/CIR/Lowering/unlowered-address-spaces.cir
    clang/utils/TableGen/CIRLoweringEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index df55be21762547..719ec9ac184ff6 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -359,6 +359,11 @@ convertFramePointerKindToLLVMIR(cir::FramePointerKind 
kind) {
 mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
     cir::CopyOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
+  // Opaque pointer conversion does not validate the pointee's memory layout.
+  mlir::Type pointeeType = op.getType().getPointee();
+  if (!convertTypeForMemory(*getTypeConverter(), dataLayout, pointeeType))
+    return emitTypeConversionError(op, pointeeType);
+
   mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
   const mlir::Value length = mlir::LLVM::ConstantOp::create(
       rewriter, op.getLoc(), rewriter.getI64Type(),
@@ -1932,6 +1937,8 @@ mlir::LogicalResult 
CIRToLLVMCastOpLowering::matchAndRewrite(
     mlir::Type targetType = convertTy(ptrTy);
     mlir::Type elementTy = convertTypeForMemory(*getTypeConverter(), 
dataLayout,
                                                 ptrTy.getPointee());
+    if (!elementTy)
+      return emitTypeConversionError(castOp, ptrTy.getPointee());
     llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
     rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
         castOp, targetType, elementTy, sourceValue, offset);
@@ -2225,6 +2232,8 @@ mlir::LogicalResult 
CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
 
   mlir::Type elementTy =
       convertTypeForMemory(*tc, dataLayout, ptrStrideOp.getElementType());
+  if (!elementTy)
+    return emitTypeConversionError(ptrStrideOp, ptrStrideOp.getElementType());
 
   // void and function types doesn't really have a layout to use in GEPs,
   // make it i8 instead.
@@ -2251,6 +2260,8 @@ mlir::LogicalResult 
CIRToLLVMGetElementOpLowering::matchAndRewrite(
           mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
     const mlir::TypeConverter *converter = getTypeConverter();
     const mlir::Type llArrayTy = converter->convertType(arrayTy);
+    if (!llArrayTy)
+      return emitTypeConversionError(op, arrayTy);
     const mlir::Type llResultTy = converter->convertType(op.getType());
     mlir::Type elementTy =
         convertTypeForMemory(*converter, dataLayout, op.getElementType());
@@ -2285,6 +2296,8 @@ mlir::LogicalResult 
CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type resultType =
       getTypeConverter()->convertType(baseClassOp.getType());
+  if (!resultType)
+    return emitTypeConversionError(baseClassOp, baseClassOp.getType());
   mlir::Value derivedAddr = adaptor.getSrcAddr();
   llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
       adaptor.getOffset().getZExtValue()};
@@ -2317,6 +2330,8 @@ mlir::LogicalResult 
CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type resultType =
       getTypeConverter()->convertType(derivedClassOp.getType());
+  if (!resultType)
+    return emitTypeConversionError(derivedClassOp, derivedClassOp.getType());
   mlir::Value baseAddr = adaptor.getSrcAddr();
   // The offset is set in the operation as an unsigned value, but it must be
   // applied as a negative offset.
@@ -2405,6 +2420,8 @@ mlir::LogicalResult 
CIRToLLVMAllocaOpLowering::matchAndRewrite(
            << "NYI: lowering alloca of a type with no memory representation";
   mlir::Type resultTy = convertTypeForMemory(*getTypeConverter(), dataLayout,
                                              op.getType(), isForHLSL);
+  if (!resultTy)
+    return emitTypeConversionError(op, op.getType());
 
   assert(!cir::MissingFeatures::addressSpace());
   assert(!cir::MissingFeatures::opAllocaAnnotations());
@@ -2661,6 +2678,8 @@ mlir::LogicalResult 
CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
     cir::FrameAddrOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
+  if (!llvmPtrTy)
+    return emitTypeConversionError(op, op.getType());
   replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.frameaddress", 
llvmPtrTy,
                                    adaptor.getOperands());
   return mlir::success();
@@ -2683,6 +2702,8 @@ mlir::LogicalResult 
CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
     cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
+  if (!llvmPtrTy)
+    return emitTypeConversionError(op, op.getType());
   replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.addressofreturnaddress",
                                    llvmPtrTy, adaptor.getOperands());
   return mlir::success();
@@ -2694,8 +2715,7 @@ mlir::LogicalResult 
CIRToLLVMLoadOpLowering::matchAndRewrite(
   const mlir::Type llvmTy =
       convertTypeForLoadStore(*getTypeConverter(), dataLayout, op.getType());
   if (!llvmTy)
-    return op.emitError()
-           << "NYI: lowering load of a type with no memory representation";
+    return emitTypeConversionError(op, op.getType());
   mlir::LLVM::AtomicOrdering ordering = getLLVMMemOrder(op.getMemOrder());
   std::optional<size_t> opAlign = op.getAlignment();
   unsigned alignment = (unsigned)opAlign.value_or(
@@ -2976,6 +2996,10 @@ mlir::LogicalResult 
CIRToLLVMPrefetchOpLowering::matchAndRewrite(
 mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
     cir::PtrDiffOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type pointeeType = op.getLhs().getType().getPointee();
+  if (!convertTypeForMemory(*getTypeConverter(), dataLayout, pointeeType))
+    return emitTypeConversionError(op, pointeeType);
+
   auto dstTy = mlir::cast<cir::IntType>(op.getType());
   mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
 
@@ -2987,9 +3011,8 @@ mlir::LogicalResult 
CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
   auto 
diff  =
       mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
 
-  cir::PointerType ptrTy = op.getLhs().getType();
   assert(!cir::MissingFeatures::llvmLoweringPtrDiffConsidersPointee());
-  uint64_t typeSize = getTypeAllocSize(ptrTy.getPointee(), *op);
+  uint64_t typeSize = getTypeAllocSize(pointeeType, *op);
 
   // Avoid silly division by 1.
   mlir::Value resultVal = 
diff .getResult();
@@ -3265,6 +3288,8 @@ mlir::LogicalResult 
CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
   }
 
   mlir::Type type = getTypeConverter()->convertType(op.getType());
+  if (!type)
+    return emitTypeConversionError(op, op.getType());
   mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
       rewriter, op.getLoc(), type, op.getName());
 
@@ -4306,6 +4331,9 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
     mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
     unsigned numericAS = 0;
 
+    if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(addrSpaceAttr))
+      return {};
+
     if (auto targetAsAttr =
             mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
                 addrSpaceAttr))
@@ -4341,6 +4369,8 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
         intTy && intTy.isBitInt())
       return {};
     const mlir::Type ty = converter.convertType(type.getElementType());
+    if (!ty)
+      return {};
     return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
   });
   converter.addConversion([&](cir::MatrixType type) -> mlir::Type {
@@ -4943,6 +4973,8 @@ mlir::LogicalResult 
CIRToLLVMGetMemberOpLowering::matchAndRewrite(
     cir::GetMemberOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
+  if (!llResTy)
+    return emitTypeConversionError(op, op.getType());
   mlir::Type pointee = op.getAddrTy().getPointee();
 
   if (mlir::isa<cir::UnionType>(pointee)) {
@@ -4961,6 +4993,8 @@ mlir::LogicalResult 
CIRToLLVMGetMemberOpLowering::matchAndRewrite(
   llvm::SmallVector<mlir::LLVM::GEPArg, 2> offset{
       0, static_cast<int32_t>(structTy.getLLVMFieldIndex(op.getIndex()))};
   const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
+  if (!elementTy)
+    return emitTypeConversionError(op, structTy);
   // Struct member accesses are always inbounds and nuw: the base pointer
   // is valid and the member offset is a positive, constant offset within
   // the struct layout, so it cannot wrap. This matches LLVM's
@@ -5335,6 +5369,8 @@ mlir::LogicalResult 
CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
     cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Type targetType = getTypeConverter()->convertType(op.getType());
+  if (!targetType)
+    return emitTypeConversionError(op, op.getType());
   auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
   llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
       llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
@@ -5348,6 +5384,8 @@ mlir::LogicalResult 
CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
     cir::VTTAddrPointOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
+  if (!resultType)
+    return emitTypeConversionError(op, op.getType());
   llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
   mlir::Type eltType;
   mlir::Value llvmAddr = adaptor.getSymAddr();
@@ -6107,6 +6145,8 @@ mlir::LogicalResult 
CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   cir::PointerType operandTy = op.getOperand().getType();
   mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+  if (!resultLLVMTy)
+    return emitTypeConversionError(op, op.getType());
   mlir::Type elementLLVMTy =
       getTypeConverter()->convertType(operandTy.getPointee());
 
@@ -6124,6 +6164,8 @@ mlir::LogicalResult 
CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   cir::PointerType operandTy = op.getOperand().getType();
   mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+  if (!resultLLVMTy)
+    return emitTypeConversionError(op, op.getType());
   mlir::Type elementLLVMTy =
       getTypeConverter()->convertType(operandTy.getPointee());
 
@@ -6222,8 +6264,11 @@ mlir::LogicalResult 
CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
 
     llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
     cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
-    mlir::TypeAttr typAttr = mlir::TypeAttr::get(convertTypeForMemory(
-        *getTypeConverter(), dataLayout, typ.getPointee()));
+    mlir::Type elementTy =
+        convertTypeForMemory(*getTypeConverter(), dataLayout, 
typ.getPointee());
+    if (!elementTy)
+      return emitTypeConversionError(op, typ.getPointee());
+    mlir::TypeAttr typAttr = mlir::TypeAttr::get(elementTy);
 
     attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
     mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);

diff  --git a/clang/test/CIR/Lowering/opaque-pointer-address-spaces.cir 
b/clang/test/CIR/Lowering/opaque-pointer-address-spaces.cir
new file mode 100644
index 00000000000000..90b6d229621582
--- /dev/null
+++ b/clang/test/CIR/Lowering/opaque-pointer-address-spaces.cir
@@ -0,0 +1,153 @@
+// RUN: cir-opt %s --split-input-file --cir-to-llvm | FileCheck %s
+
+// Only the pointer's own address space is needed for an opaque LLVM pointer.
+// Language address spaces in its pointee do not prevent pointer conversion.
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @nested_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @nested_language_address_space(%arg0: !cir.ptr<!cir.ptr<!s32i, 
lang_address_space(offload_local)>>) {
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>
+!outer = !cir.ptr<!langptr, target_address_space(3)>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @outer_target_address_space
+  // CHECK-SAME: %[[ARG:.*]]: !llvm.ptr<3>) -> !llvm.ptr<3>
+  cir.func @outer_target_address_space(%ptr: !outer) -> !outer {
+    // CHECK: llvm.return %[[ARG]] : !llvm.ptr<3>
+    cir.return %ptr : !outer
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Node = !cir.struct<"Node" {data !cir.ptr<!cir.struct<"Node">>, data 
!cir.ptr<!s32i, lang_address_space(offload_global)>}>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @recursive_struct_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @recursive_struct_language_address_space(%arg0: 
!cir.ptr<!rec_Node>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_U = !cir.union<"U" {data !s32i, data !cir.ptr<!s32i, 
lang_address_space(offload_global)>}>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @union_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @union_language_address_space(%arg0: !cir.ptr<!rec_U>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @function_and_array_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @function_and_array_language_address_space(
+      %arg0: !cir.ptr<!cir.func<(!cir.ptr<!cir.array<!cir.ptr<!s32i, 
lang_address_space(offload_constant)> x 4>>)>>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Foo = !cir.struct<"Foo" {data !s32i}>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @data_member_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @data_member_language_address_space(
+      %arg0: !cir.ptr<!cir.data_member<!cir.ptr<!s32i, 
lang_address_space(offload_global)> in !rec_Foo>>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Foo = !cir.struct<"Foo" {data !s32i}>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // CHECK-LABEL: llvm.func @method_language_address_space
+  // CHECK-SAME: !llvm.ptr
+  cir.func @method_language_address_space(
+      %arg0: !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!s32i, 
lang_address_space(offload_global)>)> in !rec_Foo>>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>
+!ptr = !cir.ptr<!langptr>
+
+module attributes {cir.triple = "amdgcn-amd-amdhsa", llvm.data_layout = 
"e-p:64:64-p3:32:32"} {
+  // The stored pointer has a known layout even though its pointee does not.
+  // CHECK-LABEL: llvm.func @copy_opaque_pointers
+  cir.func @copy_opaque_pointers(%src: !cir.ptr<!ptr>, %dst: !cir.ptr<!ptr>) {
+    // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(8 : i64)
+    // CHECK: "llvm.intr.memcpy"(%{{.*}}, %{{.*}}, %[[SIZE]])
+    cir.copy %src to %dst : !cir.ptr<!ptr>
+    cir.return
+  }
+
+  // CHECK-LABEL: llvm.func @
diff _opaque_pointers
+  cir.func @
diff _opaque_pointers(%lhs: !cir.ptr<!ptr>, %rhs: !cir.ptr<!ptr>) -> !s64i {
+    // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(8 : i64)
+    // CHECK: llvm.sdiv exact %{{.*}}, %[[SIZE]] : i64
+    %
diff  = cir.ptr_
diff  %lhs, %rhs : !cir.ptr<!ptr> -> !s64i
+    cir.return %
diff  : !s64i
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Base = !cir.struct<"Base" {data !s32i}>
+!rec_Derived = !cir.struct<"Derived" {data !cir.ptr<!s32i, 
lang_address_space(offload_global)>, data !rec_Base}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // CHECK-LABEL: llvm.func @derived_class_addr_language_address_space
+  cir.func @derived_class_addr_language_address_space() {
+    %base = cir.alloca "base" align(4) : !cir.ptr<!rec_Base>
+    // CHECK: llvm.getelementptr inbounds {{.*}}[-4] : (!llvm.ptr) -> 
!llvm.ptr, i8
+    %derived = cir.derived_class_addr nonnull %base [4] : !cir.ptr<!rec_Base> 
-> !cir.ptr<!rec_Derived>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+!fn = !cir.func<() -> !langptr>
+!fnptr = !cir.ptr<!fn>
+!fnptrptr = !cir.ptr<!fnptr>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // CHECK-LABEL: llvm.func @virtual_fn_addr_language_address_space
+  cir.func @virtual_fn_addr_language_address_space(%vptr: !cir.vptr) {
+    // CHECK: llvm.getelementptr {{.*}}[0] : (!llvm.ptr) -> !llvm.ptr, 
!llvm.ptr
+    %0 = cir.vtable.get_virtual_fn_addr %vptr[0] : !cir.vptr -> !fnptrptr
+    cir.return
+  }
+}

diff  --git a/clang/test/CIR/Lowering/unlowered-address-spaces.cir 
b/clang/test/CIR/Lowering/unlowered-address-spaces.cir
index 0faf18e5d0067c..32a80f537d503b 100644
--- a/clang/test/CIR/Lowering/unlowered-address-spaces.cir
+++ b/clang/test/CIR/Lowering/unlowered-address-spaces.cir
@@ -2,8 +2,567 @@
 
 !s32i = !cir.int<s, 32>
 
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+  // expected-error @below {{failed to legalize operation 'cir.func'}}
+  cir.func @language_address_space(%arg0: !cir.ptr<!s32i, 
lang_address_space(offload_global)>) {
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+  // expected-error @below {{failed to legalize operation 'cir.func'}}
+  cir.func private @language_address_space_return() -> !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
 module attributes {cir.triple = "spirv64-unknown-unknown"} {
   // expected-error @below {{cannot lower a global with a language address 
space}}
   // expected-error @below {{failed to legalize operation 'cir.global'}}
   cir.global external lang_address_space(offload_global) @global = #cir.int<1> 
: !s32i
 }
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.void, lang_address_space(offload_global)>
+!rec_U = !cir.union<"U" {data !s64i, data !langptr}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // The union's integer storage converts, but its active initializer does not.
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @union_active_initializer_language_address_space = 
#cir.const_record<{#cir.ptr<null> : !langptr}> : !rec_U
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // Unlike direct cir.func lowering, a global view can request FuncType
+  // conversion before its referenced function is lowered.
+  cir.global external @function_pointer = 
#cir.global_view<@global_view_callee> : !cir.ptr<!cir.void>
+
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+  // expected-error @below {{failed to legalize operation 'cir.func'}}
+  cir.func private @global_view_callee() -> !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Keep the view before its target so the initializer is lowered first.
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @view = #cir.global_view<@target, [0 : i32]> : 
!cir.ptr<!cir.void>
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+!ptrarray = !cir.array<!ptr x 1>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @view = #cir.const_array<[#cir.global_view<@target, [0 : 
i32]> : !ptr]> : !ptrarray
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+!record = !cir.struct<{data !ptr}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @view = #cir.const_record<{#cir.global_view<@target, [0 
: i32]> : !ptr}> : !record
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+!record = !cir.struct<{data !ptr}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @view = #cir.typeinfo<{#cir.global_view<@target, [0 : 
i32]> : !ptr}> : !record
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+!ptrarray = !cir.array<!ptr x 1>
+!vtable = !cir.struct<{data !ptrarray}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @view = 
#cir.vtable<{#cir.const_array<[#cir.global_view<@target, [0 : i32]> : !ptr]> : 
!ptrarray}> : !vtable
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // Keep the function before the global so get_global is lowered first.
+  cir.func @get_global_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.get_global'}}
+    %0 = cir.get_global @global : !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+    %1 = cir.load %0 : !cir.ptr<!s32i, lang_address_space(offload_global)>, 
!s32i
+    cir.return
+  }
+
+  cir.global external lang_address_space(offload_global) @global = #cir.int<1> 
: !s32i
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  cir.func @alloca_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_private)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.alloca'}}
+    %0 = cir.alloca "x" align(4) : !cir.ptr<!s32i, 
lang_address_space(offload_private)>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  // The argument lowers to an opaque pointer, but the load needs the inner 
type.
+  cir.func @load_language_address_space(%ptr: !cir.ptr<!langptr>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.load'}}
+    %0 = cir.load %ptr : !cir.ptr<!langptr>, !langptr
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>
+
+module attributes {cir.triple = "amdgcn-amd-amdhsa", llvm.data_layout = 
"e-p:64:64-p3:32:32"} {
+  // The copy needs the local pointer's layout, not the outer opaque pointer's.
+  // The default pointer layout would incorrectly copy 8 bytes with alignment 
8.
+  cir.func @copy_language_address_space(%src: !cir.ptr<!langptr>, %dst: 
!cir.ptr<!langptr>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.copy'}}
+    cir.copy %src to %dst : !cir.ptr<!langptr>
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>
+!record = !cir.struct<{data !langptr}>
+
+module attributes {cir.triple = "amdgcn-amd-amdhsa", llvm.data_layout = 
"e-p:64:64-p3:32:32"} {
+  // Validate the copied layout through aggregate members as well.
+  cir.func @copy_record_language_address_space(%src: !cir.ptr<!record>, %dst: 
!cir.ptr<!record>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.struct<{data !cir.ptr<!cir.int<s, 32>, 
lang_address_space(offload_local)>}>'}}
+    // expected-error @below {{failed to legalize operation 'cir.copy'}}
+    cir.copy %src to %dst : !cir.ptr<!record>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  cir.func @null_constant_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.ptr<null> : !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  cir.func @constant_global_view_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.global_view<@target, [0 : i32]> : !ptr
+    cir.return
+  }
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  cir.func @constant_array_global_view_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.const_array<[#cir.global_view<@target, [0 : i32]> : 
!ptr]> : !cir.array<!ptr x 1>
+    cir.return
+  }
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the view before its target, including through enclosing attributes.
+  cir.func @constant_record_global_view_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for symbol @target}}
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.const_record<{#cir.global_view<@target, [0 : i32]> : 
!ptr}> : !cir.struct<{data !ptr}>
+    cir.return
+  }
+
+  cir.global external @target = #cir.zero : !array
+}
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.void, lang_address_space(offload_global)>
+!rec_U = !cir.union<"U" {data !s64i, data !langptr}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @constant_union_active_initializer_language_address_space() {
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.const_record<{#cir.ptr<null> : !langptr}> : !rec_U
+    cir.return
+  }
+}
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.void, lang_address_space(offload_global)>
+!rec_U = !cir.union<"U" {data !s64i, data !langptr}>
+!rec_Outer = !cir.union<"Outer" {data !s64i, data !rec_U}>
+!rec_S = !cir.struct<"S" {data !rec_Outer}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Propagate adjustment failure through both the enclosing union and struct.
+  cir.func @constant_nested_union_initializer_language_address_space() {
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const 
#cir.const_record<{#cir.const_record<{#cir.const_record<{#cir.ptr<null> : 
!langptr}> : !rec_U}> : !rec_Outer}> : !rec_S
+    cir.return
+  }
+}
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.void, lang_address_space(offload_global)>
+!rec_U = !cir.union<"U" {data !s64i, data !langptr}>
+!array = !cir.array<!rec_U x 1>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @constant_union_array_initializer_language_address_space() {
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.const_array<[#cir.const_record<{#cir.ptr<null> : 
!langptr}> : !rec_U]> : !array
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  cir.func @int_to_ptr_language_address_space(%arg0: !s32i) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.cast'}}
+    %0 = cir.cast int_to_ptr %arg0 : !s32i -> !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "spirv64-unknown-unknown"} {
+  cir.func @address_space_cast_language_address_space(%arg0: !cir.ptr<!s32i>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.cast'}}
+    %0 = cir.cast address_space %arg0 : !cir.ptr<!s32i> -> !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+// These operations need the pointee layout to build a GEP.
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 4>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @array_decay_language_address_space(%ptr: !cir.ptr<!array>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.cast'}}
+    %0 = cir.cast array_to_ptrdecay %ptr : !cir.ptr<!array> -> 
!cir.ptr<!langptr>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @ptr_stride_language_address_space(%ptr: !cir.ptr<!langptr>, %idx: 
!s32i) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.ptr_stride'}}
+    %0 = cir.ptr_stride %ptr, %idx : (!cir.ptr<!langptr>, !s32i) -> 
!cir.ptr<!langptr>
+    cir.return
+  }
+}
+
+// -----
+
+!s64i = !cir.int<s, 64>
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>
+
+module attributes {cir.triple = "amdgcn-amd-amdhsa", llvm.data_layout = 
"e-p:64:64-p3:32:32"} {
+  // Pointer 
diff erences must not divide by the default 8-byte pointer size.
+  cir.func @ptr_
diff _language_address_space(%lhs: !cir.ptr<!langptr>, %rhs: 
!cir.ptr<!langptr>) -> !s64i {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_local)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.ptr_
diff '}}
+    %
diff  = cir.ptr_
diff  %lhs, %rhs : !cir.ptr<!langptr> -> !s64i
+    cir.return %
diff  : !s64i
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 4>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @get_element_language_address_space(%ptr: !cir.ptr<!array>, %idx: 
!s32i) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 
4>'}}
+    // expected-error @below {{failed to legalize operation 'cir.get_element'}}
+    %0 = cir.get_element %ptr[%idx : !s32i] : !cir.ptr<!array> -> 
!cir.ptr<!langptr>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)>
+!record = !cir.struct<{data !langptr}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @get_member_language_address_space(%ptr: !cir.ptr<!record>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.struct<{data !cir.ptr<!cir.int<s, 32>, 
lang_address_space(offload_global)>}>'}}
+    // expected-error @below {{failed to legalize operation 'cir.get_member'}}
+    %0 = cir.get_member %ptr[0] {name = "p"} : !cir.ptr<!record> -> 
!cir.ptr<!langptr>
+    cir.return
+  }
+}
+
+// -----
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @complex_real_ptr_language_address_space(%ptr: 
!cir.ptr<!cir.complex<!cir.double>>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.double, lang_address_space(offload_private)>'}}
+    // expected-error @below {{failed to legalize operation 
'cir.complex.real_ptr'}}
+    %real = cir.complex.real_ptr %ptr : !cir.ptr<!cir.complex<!cir.double>> -> 
!cir.ptr<!cir.double, lang_address_space(offload_private)>
+    cir.return
+  }
+}
+
+// -----
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @complex_imag_ptr_language_address_space(%ptr: 
!cir.ptr<!cir.complex<!cir.double>>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.double, lang_address_space(offload_private)>'}}
+    // expected-error @below {{failed to legalize operation 
'cir.complex.imag_ptr'}}
+    %imag = cir.complex.imag_ptr %ptr : !cir.ptr<!cir.complex<!cir.double>> -> 
!cir.ptr<!cir.double, lang_address_space(offload_private)>
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the address point before its referenced global.
+  cir.func @vtable_symbol_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.struct<{data !cir.array<!cir.ptr<!cir.int<s, 32>, 
lang_address_space(offload_global)> x 1>}>' for vtable symbol @target}}
+    // expected-error @below {{failed to legalize operation 
'cir.vtable.address_point'}}
+    %0 = cir.vtable.address_point(@target, address_point = <index = 0, offset 
= 0>) : !cir.vptr
+    cir.return
+  }
+
+  cir.global "private" external @target : !cir.struct<{data !array}>
+}
+
+// -----
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @vtt_address_point_language_address_space(
+      %vtt: !cir.ptr<!cir.ptr<!cir.void>>) {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.ptr<!cir.void>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 
'cir.vtt.address_point'}}
+    %0 = cir.vtt.address_point %vtt : !cir.ptr<!cir.ptr<!cir.void>>, offset = 
1 -> !cir.ptr<!cir.ptr<!cir.void>, lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+!array = !cir.array<!langptr x 1>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the address point before its referenced global.
+  cir.func @vtt_symbol_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.array<!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)> x 1>' 
for vtable symbol @target}}
+    // expected-error @below {{failed to legalize operation 
'cir.vtt.address_point'}}
+    %0 = cir.vtt.address_point @target, offset = 0 -> !cir.ptr<!ptr>
+    cir.return
+  }
+
+  cir.global "private" external @target : !array
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!u32i = !cir.int<u, 32>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @frame_address_language_address_space() {
+    %level = cir.const #cir.int<0> : !u32i
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<u, 8>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 
'cir.frame_address'}}
+    %0 = cir.frame_address(%level) : !cir.ptr<!u8i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @address_of_return_address_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<u, 8>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 
'cir.address_of_return_address'}}
+    %0 = cir.address_of_return_address : !cir.ptr<!u8i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @stacksave_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<u, 8>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.stacksave'}}
+    %0 = cir.stacksave : !cir.ptr<!u8i, lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @inline_asm_language_address_space() {
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.asm'}}
+    %0 = cir.asm(x86_att,
+      out = [],
+      in = [],
+      in_out = [],
+      {"" "=r"}) -> !cir.ptr<!s32i, lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// -----
+
+!langptr = !cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Memory operands require an LLVM elementtype attribute for the pointee.
+  cir.func @inline_asm_memory_language_address_space(%ptr: !cir.ptr<!langptr>) 
{
+    // expected-error @below {{ClangIR lowering NYI: cannot convert 
'!cir.ptr<!cir.int<s, 32>, lang_address_space(offload_global)>'}}
+    // expected-error @below {{failed to legalize operation 'cir.asm'}}
+    cir.asm(x86_att, out = [], in = [%ptr : !cir.ptr<!langptr> (maybe_memory)],
+      in_out = [], {"" "*m"}) side_effects
+    cir.return
+  }
+}

diff  --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp 
b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index b533c239635a61..46a8dd8bd6ba0d 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -239,6 +239,9 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
     } else {
       Code << "    mlir::Type resTy = "
               "typeConverter->convertType(op.getType());\n";
+      Code << "    if (!resTy)\n";
+      Code << "      return op.emitError() << \"ClangIR lowering NYI: cannot "
+              "convert \" << op.getType();\n";
       Code << "    rewriter.replaceOpWithNewOp<mlir::LLVM::" << LLVMOp
            << ">(op, mlir::TypeRange{resTy}, adaptor.getOperands(), "
            << Properties << ");\n";


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to