https://github.com/Men-cotton created 
https://github.com/llvm/llvm-project/pull/224237

Propagate failed type and constant conversions through DirectToLLVM so 
unsupported types produce legalization failures instead of invalid LLVM 
operations or a void function result.

Assisted-by: Codex / GPT-6


>From d3cc1d7440fb9e544a93e95131a23f2ba398fbf9 Mon Sep 17 00:00:00 2001
From: mencotton <[email protected]>
Date: Tue, 15 Sep 2026 20:47:50 +0900
Subject: [PATCH] [CIR] Propagate type conversion failures in DirectToLLVM

Propagate failed type and constant conversions through DirectToLLVM so 
unsupported types produce legalization failures instead of invalid LLVM 
operations or a void function result.

Assisted-by: Codex / GPT-6
---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  62 ++++--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |   7 +-
 .../Lowering/unsupported-type-conversions.cir | 178 ++++++++++++++++++
 3 files changed, 231 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/unsupported-type-conversions.cir

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 596c0d72264a0..6280b853d6e79 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -424,10 +424,7 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
                                 LLVMBlockAddressInfo *blockInfoAddr) {
   CIRAttrToValue valueConverter(parentOp, rewriter, symbolTables, converter,
                                 blockInfoAddr);
-  mlir::Value value = valueConverter.visit(attr);
-  if (!value)
-    llvm_unreachable("unhandled attribute type");
-  return value;
+  return valueConverter.visit(attr);
 }
 
 void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow,
@@ -783,6 +780,8 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
   if (auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
     for (auto [idx, elt] : llvm::enumerate(arrayAttr)) {
       mlir::Value init = visit(elt);
+      if (!init)
+        return {};
       result =
           mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
     }
@@ -827,8 +826,11 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
       ++paddingItr;
     }
 
-    result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result,
-                                               visit(elt), insertIdx);
+    mlir::Value init = visit(elt);
+    if (!init)
+      return {};
+    result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init,
+                                               insertIdx);
     ++insertIdx;
   }
 
@@ -957,6 +959,8 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
   mlir::Type sourceType = lowered.sourceType;
 
   if (globalAttr.getIndices()) {
+    if (!sourceType)
+      return {};
     llvm::SmallVector<mlir::LLVM::GEPArg> indices;
 
     if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
@@ -1004,6 +1008,8 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
 
   for (auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
     mlir::Value init = visit(elt);
+    if (!init)
+      return {};
     result =
         mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
   }
@@ -1037,6 +1043,8 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr 
vtableArr) {
 
   for (auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
     mlir::Value init = visit(elt);
+    if (!init)
+      return {};
     result =
         mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
   }
@@ -1618,6 +1626,9 @@ mlir::LogicalResult 
CIRToLLVMCastOpLowering::matchAndRewrite(
   // both individual scalars and entire vectors. This lowering pass handles
   // both situations.
 
+  if (!getTypeConverter()->convertType(castOp.getType()))
+    return mlir::failure();
+
   switch (castOp.getKind()) {
   case cir::CastKind::array_to_ptrdecay: {
     const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
@@ -2459,6 +2470,8 @@ mlir::LogicalResult 
CIRToLLVMConstantOpLowering::matchAndRewrite(
     cir::ConstantOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Attribute attr = op.getValue();
+  if (!getTypeConverter()->convertType(op.getType()))
+    return mlir::failure();
 
   if (mlir::isa<cir::PoisonAttr>(attr)) {
     rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
@@ -2511,6 +2524,8 @@ mlir::LogicalResult 
CIRToLLVMConstantOpLowering::matchAndRewrite(
     if (mlir::isa<cir::GlobalViewAttr, cir::GlobalOffsetAttr>(op.getValue())) {
       auto newOp = lowerCirAttrAsValue(op, op.getValue(), rewriter,
                                        symbolTables, getTypeConverter());
+      if (!newOp)
+        return mlir::failure();
       rewriter.replaceOp(op, newOp);
       return mlir::success();
     }
@@ -2527,6 +2542,8 @@ mlir::LogicalResult 
CIRToLLVMConstantOpLowering::matchAndRewrite(
     } else {
       const mlir::Value initVal = lowerCirAttrAsValue(
           op, op.getValue(), rewriter, symbolTables, typeConverter);
+      if (!initVal)
+        return mlir::failure();
       rewriter.replaceOp(op, initVal);
       return mlir::success();
     }
@@ -2534,17 +2551,23 @@ mlir::LogicalResult 
CIRToLLVMConstantOpLowering::matchAndRewrite(
                  mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
     auto initVal = lowerCirAttrAsValue(op, recordAttr, rewriter, symbolTables,
                                        typeConverter);
+    if (!initVal)
+      return mlir::failure();
     rewriter.replaceOp(op, initVal);
     return mlir::success();
   } else if (const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) 
{
-    rewriter.replaceOp(op,
-                       lowerCirAttrAsValue(op, op.getValue(), rewriter,
-                                           symbolTables, getTypeConverter()));
+    mlir::Value initVal = lowerCirAttrAsValue(op, op.getValue(), rewriter,
+                                              symbolTables, 
getTypeConverter());
+    if (!initVal)
+      return mlir::failure();
+    rewriter.replaceOp(op, initVal);
     return mlir::success();
   } else if (mlir::isa<cir::RecordType>(op.getType())) {
     if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
       mlir::Value initVal =
           lowerCirAttrAsValue(op, attr, rewriter, symbolTables, typeConverter);
+      if (!initVal)
+        return mlir::failure();
       rewriter.replaceOp(op, initVal);
       return mlir::success();
     }
@@ -2777,11 +2800,12 @@ mlir::LogicalResult 
CIRToLLVMFuncOpLowering::matchAndRewrite(
 
   mlir::Type resultType =
       getTypeConverter()->convertType(fnType.getReturnType());
+  if (!resultType)
+    return mlir::failure();
 
   // Create the LLVM function operation.
   mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
-      resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
-      signatureConversion.getConvertedTypes(),
+      resultType, signatureConversion.getConvertedTypes(),
       /*isVarArg=*/fnType.isVarArg());
 
   // If this is an alias, it needs to be lowered to llvm::AliasOp.
@@ -3000,6 +3024,8 @@ 
CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
   CIRAttrToValue valueConverter(op, rewriter, symbolTables, typeConverter,
                                 &blockInfoAddr);
   mlir::Value value = valueConverter.visit(init);
+  if (!value)
+    return mlir::failure();
   mlir::LLVM::ReturnOp::create(rewriter, loc, value);
   return mlir::success();
 }
@@ -3958,6 +3984,8 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
   });
   converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> 
{
     auto result = converter.convertType(type.getReturnType());
+    if (!result)
+      return std::nullopt;
     llvm::SmallVector<mlir::Type> arguments;
     arguments.reserve(type.getNumInputs());
     if (converter.convertTypes(type.getInputs(), arguments).failed())
@@ -4801,6 +4829,9 @@ getValueForVTableSymbol(mlir::Operation *op,
     return {};
   }
 
+  if (!eltType)
+    return {};
+
   return mlir::LLVM::AddressOfOp::create(
       rewriter, op->getLoc(),
       mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
@@ -4816,7 +4847,7 @@ mlir::LogicalResult 
CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
   mlir::Value symAddr = getValueForVTableSymbol(
       op, rewriter, symbolTables, converter, op.getNameAttr(), eltType);
   if (!symAddr)
-    return op.emitError() << "Unable to get value for vtable symbol";
+    return mlir::failure();
 
   offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{
       0, op.getAddressPointAttr().getIndex(),
@@ -4874,6 +4905,8 @@ mlir::LogicalResult 
CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
     llvmAddr =
         getValueForVTableSymbol(op, rewriter, symbolTables, getTypeConverter(),
                                 op.getNameAttr(), eltType);
+    if (!llvmAddr)
+      return mlir::failure();
     assert(eltType && "Shouldn't ever be missing an eltType here");
     offsets.push_back(0);
     offsets.push_back(adaptor.getOffset());
@@ -5421,8 +5454,11 @@ mlir::LogicalResult 
CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
     cir::InlineAsmOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Type llResTy;
-  if (op.getNumResults())
+  if (op.getNumResults()) {
     llResTy = getTypeConverter()->convertType(op.getType(0));
+    if (!llResTy)
+      return mlir::failure();
+  }
 
   cir::AsmFlavor dialect = op.getAsmFlavor();
   mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 146b31b907fcc..c48722fec38fc 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -24,9 +24,10 @@ namespace direct {
 
 struct LLVMBlockAddressInfo;
 
-/// Convert a CIR attribute to an LLVM attribute. May use the datalayout for
-/// lowering attributes to-be-stored in memory. When the attribute may contain
-/// block address attributes, `blockInfoAddr` is used to resolve them.
+/// Convert a CIR attribute to an LLVM value, or return null on failure.
+/// May use the datalayout for lowering attributes to-be-stored in memory. When
+/// the attribute may contain block address attributes, `blockInfoAddr` is used
+/// to resolve them.
 mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute 
attr,
                                 mlir::ConversionPatternRewriter &rewriter,
                                 mlir::SymbolTableCollection &symbolTables,
diff --git a/clang/test/CIR/Lowering/unsupported-type-conversions.cir 
b/clang/test/CIR/Lowering/unsupported-type-conversions.cir
new file mode 100644
index 0000000000000..d4d43bf49919e
--- /dev/null
+++ b/clang/test/CIR/Lowering/unsupported-type-conversions.cir
@@ -0,0 +1,178 @@
+// RUN: cir-opt %s --split-input-file --cir-to-llvm -verify-diagnostics
+
+// Vector-of-_BitInt conversion is unsupported; propagate its failure to the
+// enclosing operation instead of constructing invalid LLVM operations.
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // expected-error @below {{failed to legalize operation 'cir.func'}}
+  cir.func private @function_result() -> !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // The initializer requests FuncType conversion before the function lowers.
+  cir.global external @function_view = #cir.global_view<@callee> : 
!cir.ptr<!cir.void>
+
+  // expected-error @below {{failed to legalize operation 'cir.func'}}
+  cir.func private @callee() -> !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @constant_result() {
+    // expected-error @below {{failed to legalize operation 'cir.const'}}
+    %0 = cir.const #cir.zero : !vec
+    cir.return
+  }
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @cast_result() {
+    %0 = cir.const #cir.zero : !cir.vector<4 x !cir.int<s, 7>>
+    // expected-error @below {{failed to legalize operation 'cir.cast'}}
+    %1 = cir.cast bitcast %0 : !cir.vector<4 x !cir.int<s, 7>> -> !vec
+    cir.return
+  }
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @asm_result() {
+    // expected-error @below {{failed to legalize operation 'cir.asm'}}
+    %0 = cir.asm(x86_att, out = [], in = [], in_out = [], {"" "=r"}) -> !vec
+    cir.return
+  }
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the constant before its target to exercise symbol-type failure.
+  cir.func @constant_global_view() {
+    // 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 : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the constant before its target to exercise symbol-type failure.
+  cir.func @constant_array_view() {
+    // 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 : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Lower the constant before its target to exercise symbol-type failure.
+  cir.func @constant_record_view() {
+    // 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 : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Propagate initializer failure before lowering the referenced global.
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @global_view = #cir.global_view<@target, [0 : i32]> : 
!ptr
+
+  cir.global external @target = #cir.zero : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Propagate initializer failure before lowering the referenced global.
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @typeinfo_view = 
#cir.typeinfo<{#cir.global_view<@target, [0 : i32]> : !ptr}> : 
!cir.struct<{data !ptr}>
+
+  cir.global external @target = #cir.zero : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Propagate initializer failure before lowering the referenced global.
+  // expected-error @below {{failed to legalize operation 'cir.global'}}
+  cir.global external @vtable_view = 
#cir.vtable<{#cir.const_array<[#cir.global_view<@target, [0 : i32]> : !ptr]> : 
!cir.array<!ptr x 1>}> : !cir.struct<{data !cir.array<!ptr x 1>}>
+
+  cir.global external @target = #cir.zero : !vec
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // The address point requests the symbol type before the global lowers.
+  cir.func @vtable_symbol() {
+    // 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 !cir.array<!vec x 
1>}>
+}
+
+// -----
+
+!vec = !cir.vector<4 x !cir.int<s, 7, bitint>>
+!ptr = !cir.ptr<!cir.void>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // The address point requests the symbol type before the global lowers.
+  cir.func @vtt_symbol() {
+    // 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 : !cir.array<!vec x 1>
+}

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

Reply via email to