https://github.com/Men-cotton updated https://github.com/llvm/llvm-project/pull/224239
>From 3999f6e6b4f3d7dd3142b921709fdd3a326c1ebf Mon Sep 17 00:00:00 2001 From: mencotton <[email protected]> Date: Tue, 15 Sep 2026 20:52:07 +0900 Subject: [PATCH 1/2] [CIR] Reject language address spaces in DirectToLLVM pointer conversion 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 --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 64 +++ .../CIR/Lowering/unlowered-address-spaces.cir | 504 ++++++++++++++++++ clang/utils/TableGen/CIRLoweringEmitter.cpp | 2 + 3 files changed, 570 insertions(+) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 66d87b7ee35c7..a8d9672cf0867 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -49,6 +49,7 @@ #include "clang/CIR/LoweringHelpers.h" #include "clang/CIR/MissingFeatures.h" #include "clang/CIR/Passes.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/TypeSwitch.h" @@ -2285,6 +2286,8 @@ mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { const mlir::Type resultType = getTypeConverter()->convertType(baseClassOp.getType()); + if (!resultType) + return mlir::failure(); mlir::Value derivedAddr = adaptor.getSrcAddr(); llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = { adaptor.getOffset().getZExtValue()}; @@ -2317,6 +2320,8 @@ mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { const mlir::Type resultType = getTypeConverter()->convertType(derivedClassOp.getType()); + if (!resultType) + return mlir::failure(); 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. @@ -2391,6 +2396,8 @@ mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite( << "NYI: lowering alloca of a type with no memory representation"; mlir::Type resultTy = convertTypeForMemory(*getTypeConverter(), dataLayout, op.getType()); + if (!resultTy) + return mlir::failure(); assert(!cir::MissingFeatures::addressSpace()); assert(!cir::MissingFeatures::opAllocaAnnotations()); @@ -2647,6 +2654,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 mlir::failure(); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.frameaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); @@ -2669,6 +2678,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 mlir::failure(); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.addressofreturnaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); @@ -3251,6 +3262,8 @@ mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite( } mlir::Type type = getTypeConverter()->convertType(op.getType()); + if (!type) + return mlir::failure(); mlir::Operation *newop = mlir::LLVM::AddressOfOp::create( rewriter, op.getLoc(), type, op.getName()); @@ -4286,12 +4299,51 @@ mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite( return mlir::success(); } +static bool +containsLangAddressSpace(mlir::Type type, + llvm::SmallDenseSet<mlir::Type, 4> &visited) { + if (!visited.insert(type).second) + return false; + + if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) + return mlir::isa_and_present<cir::LangAddressSpaceAttr>( + ptrTy.getAddrSpace()) || + containsLangAddressSpace(ptrTy.getPointee(), visited); + if (auto arrayTy = mlir::dyn_cast<cir::ArrayType>(type)) + return containsLangAddressSpace(arrayTy.getElementType(), visited); + if (auto vectorTy = mlir::dyn_cast<cir::VectorType>(type)) + return containsLangAddressSpace(vectorTy.getElementType(), visited); + if (auto funcTy = mlir::dyn_cast<cir::FuncType>(type)) + return llvm::any_of(funcTy.getInputs(), + [&](mlir::Type input) { + return containsLangAddressSpace(input, visited); + }) || + containsLangAddressSpace(funcTy.getReturnType(), visited); + if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(type)) + return containsLangAddressSpace(dataMemberTy.getMemberTy(), visited); + if (auto methodTy = mlir::dyn_cast<cir::MethodType>(type)) + return containsLangAddressSpace(methodTy.getMemberFuncTy(), visited); + if (auto recordTy = mlir::dyn_cast<cir::RecordType>(type)) + return llvm::any_of(recordTy.getMembers(), [&](mlir::Type member) { + return containsLangAddressSpace(member, visited); + }); + return false; +} + +static bool containsLangAddressSpace(mlir::Type type) { + llvm::SmallDenseSet<mlir::Type, 4> visited; + return containsLangAddressSpace(type, visited); +} + static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout) { converter.addConversion([&](cir::PointerType type) -> mlir::Type { mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace(); unsigned numericAS = 0; + if (containsLangAddressSpace(type)) + return {}; + if (auto targetAsAttr = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>( addrSpaceAttr)) @@ -4327,6 +4379,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 { @@ -4927,6 +4981,8 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite( cir::GetMemberOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type llResTy = getTypeConverter()->convertType(op.getType()); + if (!llResTy) + return mlir::failure(); mlir::Type pointee = op.getAddrTy().getPointee(); if (mlir::isa<cir::UnionType>(pointee)) { @@ -5319,6 +5375,8 @@ mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite( cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type targetType = getTypeConverter()->convertType(op.getType()); + if (!targetType) + return mlir::failure(); auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); llvm::SmallVector<mlir::LLVM::GEPArg> offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()}; @@ -5332,6 +5390,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 mlir::failure(); llvm::SmallVector<mlir::LLVM::GEPArg> offsets; mlir::Type eltType; mlir::Value llvmAddr = adaptor.getSymAddr(); @@ -6064,6 +6124,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 mlir::failure(); mlir::Type elementLLVMTy = getTypeConverter()->convertType(operandTy.getPointee()); @@ -6081,6 +6143,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 mlir::failure(); mlir::Type elementLLVMTy = getTypeConverter()->convertType(operandTy.getPointee()); diff --git a/clang/test/CIR/Lowering/unlowered-address-spaces.cir b/clang/test/CIR/Lowering/unlowered-address-spaces.cir index 0faf18e5d0067..3220e55e24c6d 100644 --- a/clang/test/CIR/Lowering/unlowered-address-spaces.cir +++ b/clang/test/CIR/Lowering/unlowered-address-spaces.cir @@ -2,8 +2,512 @@ !s32i = !cir.int<s, 32> +module attributes {cir.triple = "spirv64-unknown-unknown"} { + // 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 {{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 {{failed to legalize operation 'cir.func'}} + cir.func @nested_language_address_space(%arg0: !cir.ptr<!cir.ptr<!s32i, lang_address_space(offload_local)>>) { + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> + +module attributes {cir.triple = "spirv64-unknown-unknown"} { + // expected-error @below {{failed to legalize operation 'cir.func'}} + 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> +// Keep walking after the recursive member to find the language address space. +!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"} { + // expected-error @below {{failed to legalize operation 'cir.func'}} + 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"} { + // expected-error @below {{failed to legalize operation 'cir.func'}} + cir.func @union_language_address_space(%arg0: !cir.ptr<!rec_U>) { + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!rec_Foo = !cir.struct<"Foo" {data !s32i}> + +module attributes {cir.triple = "spirv64-unknown-unknown"} { + // expected-error @below {{failed to legalize operation 'cir.func'}} + 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"} { + // expected-error @below {{failed to legalize operation 'cir.func'}} + 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 + } +} + +// ----- + +!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 {{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 {{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 {{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 {{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 {{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 {{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 {{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 {{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> + +module attributes {cir.triple = "spirv64-unknown-unknown"} { + cir.func @null_constant_language_address_space() { + // 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 {{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 {{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 {{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 {{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 {{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 + } +} + +// ----- + +!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"} { + cir.func @derived_class_addr_language_address_space() { + %base = cir.alloca "base" align(4) : !cir.ptr<!rec_Base> + // expected-error @below {{failed to legalize operation 'cir.derived_class_addr'}} + %derived = cir.derived_class_addr nonnull %base [4] : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> + 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 {{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 {{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 {{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}> +} + +// ----- + +!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"} { + cir.func @virtual_fn_addr_language_address_space(%vptr: !cir.vptr) { + // expected-error @below {{failed to legalize operation 'cir.vtable.get_virtual_fn_addr'}} + %0 = cir.vtable.get_virtual_fn_addr %vptr[0] : !cir.vptr -> !fnptrptr + cir.return + } +} + +// ----- + +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 {{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 {{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 {{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 {{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 {{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 {{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 + } +} diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp b/clang/utils/TableGen/CIRLoweringEmitter.cpp index b533c239635a6..62a2411c66c0f 100644 --- a/clang/utils/TableGen/CIRLoweringEmitter.cpp +++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp @@ -239,6 +239,8 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName, } else { Code << " mlir::Type resTy = " "typeConverter->convertType(op.getType());\n"; + Code << " if (!resTy)\n"; + Code << " return mlir::failure();\n"; Code << " rewriter.replaceOpWithNewOp<mlir::LLVM::" << LLVMOp << ">(op, mlir::TypeRange{resTy}, adaptor.getOperands(), " << Properties << ");\n"; >From c4cf0482ef05468f1bee73a21aab463ad4acf01c Mon Sep 17 00:00:00 2001 From: mencotton <[email protected]> Date: Fri, 16 Oct 2026 11:55:28 -0500 Subject: [PATCH 2/2] fix: [CIR] Check only the converted pointer's address space Limit opaque pointer conversion to its own address space and diagnose unsupported pointee types where their layout is required. Emit type-specific errors for failed pointer conversions. Validate pointee memory conversion before deriving copy sizes, alignments, or pointer-difference strides from CIR layout. Keep deeper pointee types opaque when their layouts are not needed. Assisted-by: Codex / GPT-6 --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 91 +++---- .../opaque-pointer-address-spaces.cir | 153 +++++++++++ .../CIR/Lowering/unlowered-address-spaces.cir | 247 +++++++++++------- clang/utils/TableGen/CIRLoweringEmitter.cpp | 3 +- 4 files changed, 342 insertions(+), 152 deletions(-) create mode 100644 clang/test/CIR/Lowering/opaque-pointer-address-spaces.cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index a8d9672cf0867..abd781ed03baa 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -49,7 +49,6 @@ #include "clang/CIR/LoweringHelpers.h" #include "clang/CIR/MissingFeatures.h" #include "clang/CIR/Passes.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/TypeSwitch.h" @@ -360,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(), @@ -1933,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); @@ -2226,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. @@ -2252,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()); @@ -2287,7 +2297,7 @@ mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite( const mlir::Type resultType = getTypeConverter()->convertType(baseClassOp.getType()); if (!resultType) - return mlir::failure(); + return emitTypeConversionError(baseClassOp, baseClassOp.getType()); mlir::Value derivedAddr = adaptor.getSrcAddr(); llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = { adaptor.getOffset().getZExtValue()}; @@ -2321,7 +2331,7 @@ mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite( const mlir::Type resultType = getTypeConverter()->convertType(derivedClassOp.getType()); if (!resultType) - return mlir::failure(); + 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. @@ -2397,7 +2407,7 @@ mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite( mlir::Type resultTy = convertTypeForMemory(*getTypeConverter(), dataLayout, op.getType()); if (!resultTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); assert(!cir::MissingFeatures::addressSpace()); assert(!cir::MissingFeatures::opAllocaAnnotations()); @@ -2655,7 +2665,7 @@ mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType()); if (!llvmPtrTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.frameaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); @@ -2679,7 +2689,7 @@ mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType()); if (!llvmPtrTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.addressofreturnaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); @@ -2691,8 +2701,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( @@ -2973,6 +2982,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); @@ -2984,9 +2997,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(); @@ -3263,7 +3275,7 @@ mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite( mlir::Type type = getTypeConverter()->convertType(op.getType()); if (!type) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); mlir::Operation *newop = mlir::LLVM::AddressOfOp::create( rewriter, op.getLoc(), type, op.getName()); @@ -4299,49 +4311,13 @@ mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite( return mlir::success(); } -static bool -containsLangAddressSpace(mlir::Type type, - llvm::SmallDenseSet<mlir::Type, 4> &visited) { - if (!visited.insert(type).second) - return false; - - if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) - return mlir::isa_and_present<cir::LangAddressSpaceAttr>( - ptrTy.getAddrSpace()) || - containsLangAddressSpace(ptrTy.getPointee(), visited); - if (auto arrayTy = mlir::dyn_cast<cir::ArrayType>(type)) - return containsLangAddressSpace(arrayTy.getElementType(), visited); - if (auto vectorTy = mlir::dyn_cast<cir::VectorType>(type)) - return containsLangAddressSpace(vectorTy.getElementType(), visited); - if (auto funcTy = mlir::dyn_cast<cir::FuncType>(type)) - return llvm::any_of(funcTy.getInputs(), - [&](mlir::Type input) { - return containsLangAddressSpace(input, visited); - }) || - containsLangAddressSpace(funcTy.getReturnType(), visited); - if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(type)) - return containsLangAddressSpace(dataMemberTy.getMemberTy(), visited); - if (auto methodTy = mlir::dyn_cast<cir::MethodType>(type)) - return containsLangAddressSpace(methodTy.getMemberFuncTy(), visited); - if (auto recordTy = mlir::dyn_cast<cir::RecordType>(type)) - return llvm::any_of(recordTy.getMembers(), [&](mlir::Type member) { - return containsLangAddressSpace(member, visited); - }); - return false; -} - -static bool containsLangAddressSpace(mlir::Type type) { - llvm::SmallDenseSet<mlir::Type, 4> visited; - return containsLangAddressSpace(type, visited); -} - static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout) { converter.addConversion([&](cir::PointerType type) -> mlir::Type { mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace(); unsigned numericAS = 0; - if (containsLangAddressSpace(type)) + if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(addrSpaceAttr)) return {}; if (auto targetAsAttr = @@ -4982,7 +4958,7 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { mlir::Type llResTy = getTypeConverter()->convertType(op.getType()); if (!llResTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); mlir::Type pointee = op.getAddrTy().getPointee(); if (mlir::isa<cir::UnionType>(pointee)) { @@ -5001,6 +4977,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 @@ -5376,7 +5354,7 @@ mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { mlir::Type targetType = getTypeConverter()->convertType(op.getType()); if (!targetType) - return mlir::failure(); + 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()}; @@ -5391,7 +5369,7 @@ mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { const mlir::Type resultType = getTypeConverter()->convertType(op.getType()); if (!resultType) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); llvm::SmallVector<mlir::LLVM::GEPArg> offsets; mlir::Type eltType; mlir::Value llvmAddr = adaptor.getSymAddr(); @@ -6125,7 +6103,7 @@ mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite( cir::PointerType operandTy = op.getOperand().getType(); mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType()); if (!resultLLVMTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); mlir::Type elementLLVMTy = getTypeConverter()->convertType(operandTy.getPointee()); @@ -6144,7 +6122,7 @@ mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite( cir::PointerType operandTy = op.getOperand().getType(); mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType()); if (!resultLLVMTy) - return mlir::failure(); + return emitTypeConversionError(op, op.getType()); mlir::Type elementLLVMTy = getTypeConverter()->convertType(operandTy.getPointee()); @@ -6243,8 +6221,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 0000000000000..90b6d22962158 --- /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 3220e55e24c6d..32a80f537d503 100644 --- a/clang/test/CIR/Lowering/unlowered-address-spaces.cir +++ b/clang/test/CIR/Lowering/unlowered-address-spaces.cir @@ -3,6 +3,7 @@ !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 @@ -14,6 +15,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { !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)> } @@ -22,80 +24,6 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { !s32i = !cir.int<s, 32> -module attributes {cir.triple = "spirv64-unknown-unknown"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - cir.func @nested_language_address_space(%arg0: !cir.ptr<!cir.ptr<!s32i, lang_address_space(offload_local)>>) { - cir.return - } -} - -// ----- - -!s32i = !cir.int<s, 32> - -module attributes {cir.triple = "spirv64-unknown-unknown"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - 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> -// Keep walking after the recursive member to find the language address space. -!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"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - 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"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - cir.func @union_language_address_space(%arg0: !cir.ptr<!rec_U>) { - cir.return - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!rec_Foo = !cir.struct<"Foo" {data !s32i}> - -module attributes {cir.triple = "spirv64-unknown-unknown"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - 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"} { - // expected-error @below {{failed to legalize operation 'cir.func'}} - 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 - } -} - -// ----- - -!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'}} @@ -123,6 +51,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { // 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)> } @@ -135,6 +64,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { 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> @@ -150,6 +80,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -165,6 +96,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -180,6 +112,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -196,6 +129,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -209,6 +143,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -224,6 +159,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { 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 @@ -232,10 +168,56 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { // ----- +!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 @@ -251,6 +233,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { 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 @@ -268,6 +251,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -285,6 +269,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -345,6 +330,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -357,6 +343,7 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { 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 @@ -365,15 +352,75 @@ module attributes {cir.triple = "spirv64-unknown-unknown"} { // ----- +// 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> -!rec_Base = !cir.struct<"Base" {data !s32i}> -!rec_Derived = !cir.struct<"Derived" {data !cir.ptr<!s32i, lang_address_space(offload_global)>, data !rec_Base}> +!langptr = !cir.ptr<!s32i, lang_address_space(offload_global)> module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { - cir.func @derived_class_addr_language_address_space() { - %base = cir.alloca "base" align(4) : !cir.ptr<!rec_Base> - // expected-error @below {{failed to legalize operation 'cir.derived_class_addr'}} - %derived = cir.derived_class_addr nonnull %base [4] : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> + 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 differences 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 } } @@ -382,6 +429,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -392,6 +440,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -406,6 +455,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -416,25 +466,10 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { // ----- -!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"} { - cir.func @virtual_fn_addr_language_address_space(%vptr: !cir.vptr) { - // expected-error @below {{failed to legalize operation 'cir.vtable.get_virtual_fn_addr'}} - %0 = cir.vtable.get_virtual_fn_addr %vptr[0] : !cir.vptr -> !fnptrptr - cir.return - } -} - -// ----- - 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 @@ -450,6 +485,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -466,6 +502,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -478,6 +515,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -490,6 +528,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 @@ -502,6 +541,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 = [], @@ -511,3 +551,18 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { 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 62a2411c66c0f..46a8dd8bd6ba0 100644 --- a/clang/utils/TableGen/CIRLoweringEmitter.cpp +++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp @@ -240,7 +240,8 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName, Code << " mlir::Type resTy = " "typeConverter->convertType(op.getType());\n"; Code << " if (!resTy)\n"; - Code << " return mlir::failure();\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"; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
