https://github.com/SharmaRithik updated https://github.com/llvm/llvm-project/pull/217153
>From 830f10430a92c340eaf3b6962414a245dfd9712b Mon Sep 17 00:00:00 2001 From: SharmaRithik <[email protected]> Date: Mon, 17 Aug 2026 23:11:10 +0000 Subject: [PATCH 1/2] [CIR] Use target int and size_t widths in cir.libc.memchr This patch adds support for target sized operands on cir.libc.memchr. The operation previously required a 32 bit pattern and a 64 bit length, which made __builtin_memchr fail verification when size_t was 32 bits. CIRGen now records the target int and size_t widths on the module as cir.int_type_width and cir.size_type_width. The operands take any fundamental width of the matching signedness. The verifier checks them against the record, requires src to be in the default address space and requires the result type to match src. The textual form prints the operand types, so the previous textual form no longer parses. The sizeTypeSize computation uses TargetInfo::getSizeType() now that it feeds cir.size_type_width, which preserves the width while making the source type explicit. DirectToLLVM accepts x86_64 and AArch64 with a 32 bit int and a 64 bit size_t, and x32 with a 32 bit int and size_t. AArch64 with 32 bit pointers is rejected. The Linux and Darwin signatures are checked against classic CodeGen and other target and width combinations are conservatively rejected until their ABI requirements are handled. i686 carries the correct widths in CIR and stays rejected since CIR does not record whether -mregparm was used. Assisted-by: Claude Fable 5 --- .../clang/CIR/Dialect/IR/CIRDialect.td | 6 + clang/include/clang/CIR/Dialect/IR/CIROps.td | 19 ++- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 11 +- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 48 +++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 32 +++++ .../test/CIR/CodeGenBuiltins/builtin-memchr.c | 40 +++++- clang/test/CIR/IR/invalid-memchr.cir | 119 ++++++++++++++++ clang/test/CIR/IR/libc-memchr.cir | 7 +- .../Lowering/memchr-unsupported-target.cir | 127 ++++++++++++++++++ 9 files changed, 397 insertions(+), 12 deletions(-) create mode 100644 clang/test/CIR/IR/invalid-memchr.cir create mode 100644 clang/test/CIR/Lowering/memchr-unsupported-target.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index d974cb1fa4544..cebcbf28c8083 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -36,6 +36,12 @@ def CIR_Dialect : Dialect { let extraClassDeclaration = [{ static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; } static llvm::StringRef getTripleAttrName() { return "cir.triple"; } + static llvm::StringRef getSizeTypeWidthAttrName() { + return "cir.size_type_width"; + } + static llvm::StringRef getIntTypeWidthAttrName() { + return "cir.int_type_width"; + } static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; } static llvm::StringRef getCalleeAttrName() { return "callee"; } static llvm::StringRef getNoThrowAttrName() { return "nothrow"; } diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 8f8159a356b5a..a2204358af525 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -9174,31 +9174,42 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { // MemChrOp //===----------------------------------------------------------------------===// -def CIR_MemChrOp : CIR_Op<"libc.memchr"> { +def CIR_MemChrOp : CIR_Op<"libc.memchr", + [AllTypesMatch<["src", "result"]>]> { let summary = "libc's `memchr`"; let description = [{ Search for `pattern` in data range from `src` to `src` + `len`. `len` provides a bound to the search in `src`. `result` is a pointer to found `pattern` or a null pointer. + `pattern` has the width of the target int and `len` has the width of + the target size_t. The module records these widths as + `cir.int_type_width` and `cir.size_type_width`, each a signless i32 + holding a fundamental integer width, and the verifier checks the + operands against them. `src` must be a void pointer in the default + address space and `result` has the same type as `src`. + Examples: ``` - %p = cir.libc.memchr(%src, %pattern, %len) + %p = cir.libc.memchr(%src, %pattern, %len) : !s32i, !u64i ``` }]; let arguments = (ins Arg<CIR_VoidPtrType, "", [MemRead]>:$src, - CIR_SInt32:$pattern, - CIR_UInt64:$len + CIR_AnyFundamentalSIntType:$pattern, + CIR_AnyFundamentalUIntType:$len ); let results = (outs CIR_VoidPtrType:$result); let assemblyFormat = [{ `(` $src `,` $pattern `,` $len `)` attr-dict + `:` qualified(type($pattern)) `,` qualified(type($len)) }]; + + let hasVerifier = 1; } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 98f6ab9755501..e14d6e863aeef 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -117,13 +117,12 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, astContext.getTargetInfo().getPointerAlign(LangAS::Default)) .getQuantity(); - const unsigned charSize = astContext.getTargetInfo().getCharWidth(); + const unsigned charSize = target.getCharWidth(); uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false); // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed - const unsigned sizeTypeSize = - astContext.getTypeSize(astContext.getSignedSizeType()); - SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity(); + const unsigned sizeTypeSize = target.getTypeWidth(target.getSizeType()); + SizeSizeInBytes = sizeTypeSize / charSize; // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union uIntPtrTy = cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false); @@ -137,6 +136,10 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage)); theModule->setAttr(cir::CIRDialect::getTripleAttrName(), builder.getStringAttr(getTriple().str())); + theModule->setAttr(cir::CIRDialect::getSizeTypeWidthAttrName(), + builder.getI32IntegerAttr(sizeTypeSize)); + theModule->setAttr(cir::CIRDialect::getIntTypeWidthAttrName(), + builder.getI32IntegerAttr(target.getIntWidth())); if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0) theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(), diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 1117a8da0c4c1..91e42f0b1622d 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -4618,6 +4618,54 @@ LogicalResult cir::LifetimeEndOp::verify() { return verifyProducedBy<cir::AllocaOp>(*this, getPtr(), "ptr"); } +//===----------------------------------------------------------------------===// +// MemChrOp +//===----------------------------------------------------------------------===// + +/// Reads a fundamental integer width from a signless i32 attribute. +static std::optional<unsigned> getRecordedIntegerWidth(mlir::Attribute attr) { + auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(attr); + if (!intAttr || !intAttr.getType().isSignlessInteger(32)) + return std::nullopt; + int64_t width = intAttr.getInt(); + if (width < 0 || + !cir::isValidFundamentalIntWidth(static_cast<unsigned>(width))) + return std::nullopt; + return static_cast<unsigned>(width); +} + +LogicalResult cir::MemChrOp::verify() { + auto moduleOp = (*this)->getParentOfType<mlir::ModuleOp>(); + if (!moduleOp) + return emitOpError("expects an enclosing module"); + + // libc memchr uses pointers in the target's default address space. + if (mlir::cast<cir::PointerType>(getSrc().getType()).getAddrSpace()) + return emitOpError("src must be in the default address space"); + + auto checkWidth = [&](cir::IntType type, llvm::StringRef operandName, + llvm::StringRef attrName) -> LogicalResult { + mlir::Attribute attr = moduleOp->getAttr(attrName); + if (!attr) + return emitOpError("expects the module to record ") << attrName; + std::optional<unsigned> width = getRecordedIntegerWidth(attr); + if (!width) + return emitOpError("requires ") + << attrName + << " to be a signless i32 holding a fundamental integer width"; + if (type.getWidth() != *width) + return emitOpError() << operandName << " must have the width recorded in " + << attrName; + return success(); + }; + + if (failed(checkWidth(getPattern().getType(), "pattern", + cir::CIRDialect::getIntTypeWidthAttrName()))) + return failure(); + return checkWidth(getLen().getType(), "len", + cir::CIRDialect::getSizeTypeWidthAttrName()); +} + //===----------------------------------------------------------------------===// // ConstructCatchParamOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 227f7023909a9..c70a3b431dcc6 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -5639,9 +5639,41 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( return mlir::success(); } +/// Returns whether this target and width combination is handled by the +/// current memchr ABI lowering. +static bool isSupportedMemChrLowering(const llvm::Triple &triple, + unsigned intTypeWidth, + unsigned sizeTypeWidth) { + if (intTypeWidth != 32) + return false; + if (triple.isX86_64()) + return sizeTypeWidth == (triple.isX32() ? 32u : 64u); + return triple.isAArch64(64) && sizeTypeWidth == 64; +} + mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite( cir::MemChrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { + auto moduleOp = op->getParentOfType<mlir::ModuleOp>(); + auto tripleAttr = moduleOp->getAttrOfType<mlir::StringAttr>( + cir::CIRDialect::getTripleAttrName()); + if (!tripleAttr) + return op.emitOpError("expects the module to record ") + << cir::CIRDialect::getTripleAttrName(); + + // The emitted call carries only the default C convention and noundef + // arguments. The triple does not record -mregparm, so 32-bit x86 stays + // unsupported. + // TODO(cir): replace this allowlist with target-aware call classification. + unsigned intTypeWidth = op.getPattern().getType().getWidth(); + unsigned sizeTypeWidth = op.getLen().getType().getWidth(); + if (!isSupportedMemChrLowering(llvm::Triple(tripleAttr.getValue()), + intTypeWidth, sizeTypeWidth)) + return op.emitOpError() + << "lowering is not supported for target '" << tripleAttr.getValue() + << "' with int width " << intTypeWidth << " and size_t width " + << sizeTypeWidth; + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType()); mlir::Type patternTy = diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c b/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c index 5380dbc371de1..e5462a709cd9d 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c +++ b/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c @@ -4,12 +4,45 @@ // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fclangir -emit-cir %s -o %t.i686.cir +// RUN: FileCheck --check-prefix=ILP32 --input-file=%t.i686.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 -fclangir -emit-llvm %s -o %t.x32.ll +// RUN: FileCheck --check-prefix=LLVM32 --input-file=%t.x32.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 -emit-llvm %s -o %t.x32-classic.ll +// RUN: FileCheck --check-prefix=LLVM32 --input-file=%t.x32-classic.ll %s +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.a64.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64.ll %s +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm %s -o %t.a64-classic.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64-classic.ll %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fclangir -emit-llvm %s -o %t.x64mac.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.x64mac.ll %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o %t.x64mac-classic.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.x64mac-classic.ll %s +// RUN: %clang_cc1 -triple aarch64-apple-darwin -fclangir -emit-llvm %s -o %t.a64mac.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64mac.ll %s +// RUN: %clang_cc1 -triple aarch64-apple-darwin -emit-llvm %s -o %t.a64mac-classic.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64mac-classic.ll %s +// RUN: %clang_cc1 -triple msp430-unknown-unknown -fclangir -emit-cir %s -o %t.msp430.cir +// RUN: FileCheck --check-prefix=I16 --input-file=%t.msp430.cir %s void *test_char_memchr(const char arg[32]) { return __builtin_char_memchr(arg, 123, 32); } +// CIR: module{{.*}}cir.int_type_width = 32 : i32{{.*}}cir.size_type_width = 64 : i32 // CIR-LABEL: @test_char_memchr +// ILP32: module{{.*}}cir.int_type_width = 32 : i32{{.*}}cir.size_type_width = 32 : i32 +// ILP32-LABEL: @test_char_memchr +// ILP32: %[[PATTERN32:.*]] = cir.const #cir.int<123> : !s32i +// ILP32: %[[LEN32:.*]] = cir.const #cir.int<32> : !u32i +// ILP32: cir.libc.memchr({{.*}}, %[[PATTERN32]], %[[LEN32]]) : !s32i, !u32i +// I16: module{{.*}}cir.int_type_width = 16 : i32{{.*}}cir.size_type_width = 16 : i32 +// I16-LABEL: @test_char_memchr +// I16: %[[PATTERN16:.*]] = cir.const #cir.int<123> : !s16i +// I16: %[[LEN16:.*]] = cir.const #cir.int<32> : !u16i +// I16: cir.libc.memchr({{.*}}, %[[PATTERN16]], %[[LEN16]]) : !s16i, !u16i +// LLVM32-DAG: declare ptr @memchr(ptr noundef, i32 noundef, i32 noundef) +// LLVM32-DAG: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef 123, i32 noundef 32) // CIR: %[[PATTERN:.*]] = cir.const #cir.int<123> : !s32i // CIR: %[[LEN:.*]] = cir.const #cir.int<32> : !u64i // CIR: {{%.*}} = cir.libc.memchr({{%.*}}, %[[PATTERN]], %[[LEN]]) @@ -19,7 +52,7 @@ void *test_char_memchr(const char arg[32]) { // LLVM: ret ptr -void *test_memchr(const void *ptr, int val, unsigned long size) { +void *test_memchr(const void *ptr, int val, __SIZE_TYPE__ size) { return __builtin_memchr(ptr, val, size); } @@ -29,4 +62,9 @@ void *test_memchr(const void *ptr, int val, unsigned long size) { // LLVM-LABEL: @test_memchr // LLVM: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef %{{.*}}, i64 noundef %{{.*}}) // LLVM: ret ptr +// ILP32-LABEL: @test_memchr +// ILP32: cir.libc.memchr({{.*}}) : !s32i, !u32i +// I16-LABEL: @test_memchr +// I16: cir.libc.memchr({{.*}}) : !s16i, !u16i +// LLVM32-DAG: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) diff --git a/clang/test/CIR/IR/invalid-memchr.cir b/clang/test/CIR/IR/invalid-memchr.cir new file mode 100644 index 0000000000000..5a2999d01db16 --- /dev/null +++ b/clang/test/CIR/IR/invalid-memchr.cir @@ -0,0 +1,119 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s16i = !cir.int<s, 16> +!s32i = !cir.int<s, 32> +!s64i = !cir.int<s, 64> +!u32i = !cir.int<u, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +!asptr = !cir.ptr<!cir.void, target_address_space(1)> +module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { + cir.func @signed_len(%s: !voidptr, %p: !s32i, %n: !s64i) { + // expected-error@+1 {{'cir.libc.memchr' op operand #2 must be fundamental unsigned integer type}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !s64i + cir.return + } + cir.func @unsigned_pattern(%s: !voidptr, %p: !u32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op operand #1 must be fundamental signed integer type}} + %r = cir.libc.memchr(%s, %p, %n) : !u32i, !u64i + cir.return + } + cir.func @wrong_pattern_width(%s: !voidptr, %p: !s16i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op pattern must have the width recorded in cir.int_type_width}} + %r = cir.libc.memchr(%s, %p, %n) : !s16i, !u64i + cir.return + } + cir.func @wrong_len_width(%s: !voidptr, %p: !s32i, %n: !u32i) { + // expected-error@+1 {{'cir.libc.memchr' op len must have the width recorded in cir.size_type_width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i + cir.return + } + cir.func @non_default_addrspace(%s: !asptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op src must be in the default address space}} + %r = "cir.libc.memchr"(%s, %p, %n) : (!asptr, !s32i, !u64i) -> !asptr + cir.return + } + cir.func @result_disagrees_with_src(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op failed to verify that all of {src, result} have same type}} + %r = "cir.libc.memchr"(%s, %p, %n) : (!voidptr, !s32i, !u64i) -> !asptr + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.size_type_width = 64 : i32} { + cir.func @missing_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op expects the module to record cir.int_type_width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.int_type_width = -1 : i32, cir.size_type_width = 64 : i32} { + cir.func @negative_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.int_type_width = 32 : si32, cir.size_type_width = 64 : i32} { + cir.func @signed_metadata(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i64} { + cir.func @malformed_size_width(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op requires cir.size_type_width to be a signless i32 holding a fundamental integer width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.int_type_width = 32 : i32} { + cir.func @missing_size_width(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op expects the module to record cir.size_type_width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> +module attributes {cir.int_type_width = 7 : i32, cir.size_type_width = 64 : i32} { + cir.func @non_fundamental_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { + // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return + } +} diff --git a/clang/test/CIR/IR/libc-memchr.cir b/clang/test/CIR/IR/libc-memchr.cir index bbddb15b187a5..68a5514b59931 100644 --- a/clang/test/CIR/IR/libc-memchr.cir +++ b/clang/test/CIR/IR/libc-memchr.cir @@ -3,10 +3,11 @@ !voidptr = !cir.ptr<!cir.void> !s32i = !cir.int<s, 32> !u64i = !cir.int<u, 64> -module { +module attributes {cir.int_type_width = 32 : i32, + cir.size_type_width = 64 : i32} { cir.func @f(%src : !voidptr, %pattern : !s32i, %len : !u64i) -> !voidptr { - // CHECK: cir.libc.memchr - %ptr = cir.libc.memchr(%src, %pattern, %len) + // CHECK: cir.libc.memchr({{.*}}, {{.*}}, {{.*}}) : !s32i, !u64i + %ptr = cir.libc.memchr(%src, %pattern, %len) : !s32i, !u64i cir.return %ptr : !voidptr } } diff --git a/clang/test/CIR/Lowering/memchr-unsupported-target.cir b/clang/test/CIR/Lowering/memchr-unsupported-target.cir new file mode 100644 index 0000000000000..818fde91966bf --- /dev/null +++ b/clang/test/CIR/Lowering/memchr-unsupported-target.cir @@ -0,0 +1,127 @@ +// RUN: cir-opt --cir-to-llvm %s -verify-diagnostics -split-input-file + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "riscv64-unknown-linux-gnu", + cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { + cir.func @rejects_riscv64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'riscv64-unknown-linux-gnu' with int width 32 and size_t width 64}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "i686-unknown-linux-gnu", + cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { + cir.func @rejects_i686(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'i686-unknown-linux-gnu' with int width 32 and size_t width 32}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> + +// expected-error@+1 {{Module has no target triple}} +module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { + cir.func @rejects_missing_triple(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op expects the module to record cir.triple}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "x86_64-unknown-linux-gnu", + cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { + cir.func @rejects_x86_64_with_size_t32(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnu' with int width 32 and size_t width 32}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "arm64_32-apple-watchos", + cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { + cir.func @rejects_arm64_32_with_size_t64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'arm64_32-apple-watchos' with int width 32 and size_t width 64}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "x86_64-unknown-linux-gnux32", + cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { + cir.func @rejects_x32_with_size_t64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnux32' with int width 32 and size_t width 64}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + cir.return %r : !voidptr + } +} + +// ----- + +!s16i = !cir.int<s, 16> +!u64i = !cir.int<u, 64> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "x86_64-unknown-linux-gnu", + cir.int_type_width = 16 : i32, cir.size_type_width = 64 : i32} { + cir.func @rejects_x86_64_with_int16(%s: !voidptr, %p: !s16i, %n: !u64i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnu' with int width 16 and size_t width 64}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s16i, !u64i + cir.return %r : !voidptr + } +} + +// ----- + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> +!voidptr = !cir.ptr<!cir.void> + +module attributes {cir.triple = "aarch64-unknown-linux-gnu", + cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { + cir.func @rejects_aarch64_with_size_t32(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { + // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'aarch64-unknown-linux-gnu' with int width 32 and size_t width 32}} + // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} + %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i + cir.return %r : !voidptr + } +} >From 94bbf5d2e22f2215d0e2f6fee7317108d44cf0c1 Mon Sep 17 00:00:00 2001 From: SharmaRithik <[email protected]> Date: Thu, 20 Aug 2026 17:34:15 +0000 Subject: [PATCH 2/2] [CIR] Remove the memchr lowering target allowlist The lowering now trusts the verifier and builds the call from the operand types, so i686 and MSP430 lower and match classic CodeGen. Argument attributes such as signext are left to the general call ABI work. The printed form also shows the src type and the TypeSizeInfoAttr TODO now sits beside the attributes it describes. The darwin RUN lines exercised no path the linux triples do not cover once the lowering stopped reading the triple and are removed. Assisted-by: Claude Fable 5 --- .../clang/CIR/Dialect/IR/CIRDialect.td | 8 +- clang/include/clang/CIR/Dialect/IR/CIROps.td | 5 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 3 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 32 ----- .../test/CIR/CodeGenBuiltins/builtin-memchr.c | 27 ++-- clang/test/CIR/IR/invalid-memchr.cir | 20 +-- clang/test/CIR/IR/libc-memchr.cir | 4 +- .../Lowering/memchr-unsupported-target.cir | 127 ------------------ 8 files changed, 34 insertions(+), 192 deletions(-) delete mode 100644 clang/test/CIR/Lowering/memchr-unsupported-target.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index cebcbf28c8083..b1a0e9f3263dd 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -36,12 +36,8 @@ def CIR_Dialect : Dialect { let extraClassDeclaration = [{ static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; } static llvm::StringRef getTripleAttrName() { return "cir.triple"; } - static llvm::StringRef getSizeTypeWidthAttrName() { - return "cir.size_type_width"; - } - static llvm::StringRef getIntTypeWidthAttrName() { - return "cir.int_type_width"; - } + static llvm::StringRef getSizeTypeWidthAttrName() { return "cir.size_type_width"; } + static llvm::StringRef getIntTypeWidthAttrName() { return "cir.int_type_width"; } static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; } static llvm::StringRef getCalleeAttrName() { return "callee"; } static llvm::StringRef getNoThrowAttrName() { return "nothrow"; } diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a2204358af525..1c1d24ebd8cf5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -9192,7 +9192,7 @@ def CIR_MemChrOp : CIR_Op<"libc.memchr", Examples: ``` - %p = cir.libc.memchr(%src, %pattern, %len) : !s32i, !u64i + %p = cir.libc.memchr(%src, %pattern, %len) : !cir.ptr<!void>, !s32i, !u64i ``` }]; @@ -9206,7 +9206,8 @@ def CIR_MemChrOp : CIR_Op<"libc.memchr", let assemblyFormat = [{ `(` $src `,` $pattern `,` $len `)` attr-dict - `:` qualified(type($pattern)) `,` qualified(type($len)) + `:` qualified(type($src)) `,` qualified(type($pattern)) `,` + qualified(type($len)) }]; let hasVerifier = 1; diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index e14d6e863aeef..524a493f62459 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -120,7 +120,6 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, const unsigned charSize = target.getCharWidth(); uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false); - // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed const unsigned sizeTypeSize = target.getTypeWidth(target.getSizeType()); SizeSizeInBytes = sizeTypeSize / charSize; // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union @@ -136,6 +135,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage)); theModule->setAttr(cir::CIRDialect::getTripleAttrName(), builder.getStringAttr(getTriple().str())); + // TODO(CIR): These attributes should eventually be replaced by + // TypeSizeInfoAttr once it is upstreamed. theModule->setAttr(cir::CIRDialect::getSizeTypeWidthAttrName(), builder.getI32IntegerAttr(sizeTypeSize)); theModule->setAttr(cir::CIRDialect::getIntTypeWidthAttrName(), diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index c70a3b431dcc6..227f7023909a9 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -5639,41 +5639,9 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( return mlir::success(); } -/// Returns whether this target and width combination is handled by the -/// current memchr ABI lowering. -static bool isSupportedMemChrLowering(const llvm::Triple &triple, - unsigned intTypeWidth, - unsigned sizeTypeWidth) { - if (intTypeWidth != 32) - return false; - if (triple.isX86_64()) - return sizeTypeWidth == (triple.isX32() ? 32u : 64u); - return triple.isAArch64(64) && sizeTypeWidth == 64; -} - mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite( cir::MemChrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { - auto moduleOp = op->getParentOfType<mlir::ModuleOp>(); - auto tripleAttr = moduleOp->getAttrOfType<mlir::StringAttr>( - cir::CIRDialect::getTripleAttrName()); - if (!tripleAttr) - return op.emitOpError("expects the module to record ") - << cir::CIRDialect::getTripleAttrName(); - - // The emitted call carries only the default C convention and noundef - // arguments. The triple does not record -mregparm, so 32-bit x86 stays - // unsupported. - // TODO(cir): replace this allowlist with target-aware call classification. - unsigned intTypeWidth = op.getPattern().getType().getWidth(); - unsigned sizeTypeWidth = op.getLen().getType().getWidth(); - if (!isSupportedMemChrLowering(llvm::Triple(tripleAttr.getValue()), - intTypeWidth, sizeTypeWidth)) - return op.emitOpError() - << "lowering is not supported for target '" << tripleAttr.getValue() - << "' with int width " << intTypeWidth << " and size_t width " - << sizeTypeWidth; - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType()); mlir::Type patternTy = diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c b/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c index e5462a709cd9d..4b4b1ea05d905 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c +++ b/clang/test/CIR/CodeGenBuiltins/builtin-memchr.c @@ -6,6 +6,10 @@ // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fclangir -emit-cir %s -o %t.i686.cir // RUN: FileCheck --check-prefix=ILP32 --input-file=%t.i686.cir %s +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.i686.ll +// RUN: FileCheck --check-prefix=LLVM32 --input-file=%t.i686.ll %s +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -emit-llvm %s -o %t.i686-classic.ll +// RUN: FileCheck --check-prefix=LLVM32 --input-file=%t.i686-classic.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 -fclangir -emit-llvm %s -o %t.x32.ll // RUN: FileCheck --check-prefix=LLVM32 --input-file=%t.x32.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 -emit-llvm %s -o %t.x32-classic.ll @@ -14,16 +18,12 @@ // RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64.ll %s // RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm %s -o %t.a64-classic.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64-classic.ll %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fclangir -emit-llvm %s -o %t.x64mac.ll -// RUN: FileCheck --check-prefix=LLVM --input-file=%t.x64mac.ll %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o %t.x64mac-classic.ll -// RUN: FileCheck --check-prefix=LLVM --input-file=%t.x64mac-classic.ll %s -// RUN: %clang_cc1 -triple aarch64-apple-darwin -fclangir -emit-llvm %s -o %t.a64mac.ll -// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64mac.ll %s -// RUN: %clang_cc1 -triple aarch64-apple-darwin -emit-llvm %s -o %t.a64mac-classic.ll -// RUN: FileCheck --check-prefix=LLVM --input-file=%t.a64mac-classic.ll %s // RUN: %clang_cc1 -triple msp430-unknown-unknown -fclangir -emit-cir %s -o %t.msp430.cir // RUN: FileCheck --check-prefix=I16 --input-file=%t.msp430.cir %s +// RUN: %clang_cc1 -triple msp430-unknown-unknown -fclangir -emit-llvm %s -o %t.msp430.ll +// RUN: FileCheck --check-prefix=LLVM16 --input-file=%t.msp430.ll %s +// RUN: %clang_cc1 -triple msp430-unknown-unknown -emit-llvm %s -o %t.msp430-classic.ll +// RUN: FileCheck --check-prefix=LLVM16 --input-file=%t.msp430-classic.ll %s void *test_char_memchr(const char arg[32]) { return __builtin_char_memchr(arg, 123, 32); @@ -35,14 +35,16 @@ void *test_char_memchr(const char arg[32]) { // ILP32-LABEL: @test_char_memchr // ILP32: %[[PATTERN32:.*]] = cir.const #cir.int<123> : !s32i // ILP32: %[[LEN32:.*]] = cir.const #cir.int<32> : !u32i -// ILP32: cir.libc.memchr({{.*}}, %[[PATTERN32]], %[[LEN32]]) : !s32i, !u32i +// ILP32: cir.libc.memchr({{.*}}, %[[PATTERN32]], %[[LEN32]]) : !cir.ptr<!void>, !s32i, !u32i // I16: module{{.*}}cir.int_type_width = 16 : i32{{.*}}cir.size_type_width = 16 : i32 // I16-LABEL: @test_char_memchr // I16: %[[PATTERN16:.*]] = cir.const #cir.int<123> : !s16i // I16: %[[LEN16:.*]] = cir.const #cir.int<32> : !u16i -// I16: cir.libc.memchr({{.*}}, %[[PATTERN16]], %[[LEN16]]) : !s16i, !u16i +// I16: cir.libc.memchr({{.*}}, %[[PATTERN16]], %[[LEN16]]) : !cir.ptr<!void>, !s16i, !u16i // LLVM32-DAG: declare ptr @memchr(ptr noundef, i32 noundef, i32 noundef) // LLVM32-DAG: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef 123, i32 noundef 32) +// LLVM16-DAG: declare ptr @memchr(ptr noundef, i16 noundef, i16 noundef) +// LLVM16-DAG: call ptr @memchr(ptr noundef %{{.*}}, i16 noundef 123, i16 noundef 32) // CIR: %[[PATTERN:.*]] = cir.const #cir.int<123> : !s32i // CIR: %[[LEN:.*]] = cir.const #cir.int<32> : !u64i // CIR: {{%.*}} = cir.libc.memchr({{%.*}}, %[[PATTERN]], %[[LEN]]) @@ -63,8 +65,9 @@ void *test_memchr(const void *ptr, int val, __SIZE_TYPE__ size) { // LLVM: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef %{{.*}}, i64 noundef %{{.*}}) // LLVM: ret ptr // ILP32-LABEL: @test_memchr -// ILP32: cir.libc.memchr({{.*}}) : !s32i, !u32i +// ILP32: cir.libc.memchr({{.*}}) : !cir.ptr<!void>, !s32i, !u32i // I16-LABEL: @test_memchr -// I16: cir.libc.memchr({{.*}}) : !s16i, !u16i +// I16: cir.libc.memchr({{.*}}) : !cir.ptr<!void>, !s16i, !u16i // LLVM32-DAG: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) +// LLVM16-DAG: call ptr @memchr(ptr noundef %{{.*}}, i16 noundef %{{.*}}, i16 noundef %{{.*}}) diff --git a/clang/test/CIR/IR/invalid-memchr.cir b/clang/test/CIR/IR/invalid-memchr.cir index 5a2999d01db16..b970d62570aff 100644 --- a/clang/test/CIR/IR/invalid-memchr.cir +++ b/clang/test/CIR/IR/invalid-memchr.cir @@ -10,22 +10,22 @@ module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { cir.func @signed_len(%s: !voidptr, %p: !s32i, %n: !s64i) { // expected-error@+1 {{'cir.libc.memchr' op operand #2 must be fundamental unsigned integer type}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !s64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !s64i cir.return } cir.func @unsigned_pattern(%s: !voidptr, %p: !u32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op operand #1 must be fundamental signed integer type}} - %r = cir.libc.memchr(%s, %p, %n) : !u32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !u32i, !u64i cir.return } cir.func @wrong_pattern_width(%s: !voidptr, %p: !s16i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op pattern must have the width recorded in cir.int_type_width}} - %r = cir.libc.memchr(%s, %p, %n) : !s16i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s16i, !u64i cir.return } cir.func @wrong_len_width(%s: !voidptr, %p: !s32i, %n: !u32i) { // expected-error@+1 {{'cir.libc.memchr' op len must have the width recorded in cir.size_type_width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u32i cir.return } cir.func @non_default_addrspace(%s: !asptr, %p: !s32i, %n: !u64i) { @@ -48,7 +48,7 @@ module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32 module attributes {cir.size_type_width = 64 : i32} { cir.func @missing_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op expects the module to record cir.int_type_width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } @@ -61,7 +61,7 @@ module attributes {cir.size_type_width = 64 : i32} { module attributes {cir.int_type_width = -1 : i32, cir.size_type_width = 64 : i32} { cir.func @negative_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } @@ -74,7 +74,7 @@ module attributes {cir.int_type_width = -1 : i32, cir.size_type_width = 64 : i32 module attributes {cir.int_type_width = 32 : si32, cir.size_type_width = 64 : i32} { cir.func @signed_metadata(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } @@ -87,7 +87,7 @@ module attributes {cir.int_type_width = 32 : si32, cir.size_type_width = 64 : i3 module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i64} { cir.func @malformed_size_width(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op requires cir.size_type_width to be a signless i32 holding a fundamental integer width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } @@ -100,7 +100,7 @@ module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i64 module attributes {cir.int_type_width = 32 : i32} { cir.func @missing_size_width(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op expects the module to record cir.size_type_width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } @@ -113,7 +113,7 @@ module attributes {cir.int_type_width = 32 : i32} { module attributes {cir.int_type_width = 7 : i32, cir.size_type_width = 64 : i32} { cir.func @non_fundamental_int_width(%s: !voidptr, %p: !s32i, %n: !u64i) { // expected-error@+1 {{'cir.libc.memchr' op requires cir.int_type_width to be a signless i32 holding a fundamental integer width}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i + %r = cir.libc.memchr(%s, %p, %n) : !voidptr, !s32i, !u64i cir.return } } diff --git a/clang/test/CIR/IR/libc-memchr.cir b/clang/test/CIR/IR/libc-memchr.cir index 68a5514b59931..28e02330c364c 100644 --- a/clang/test/CIR/IR/libc-memchr.cir +++ b/clang/test/CIR/IR/libc-memchr.cir @@ -6,8 +6,8 @@ module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { cir.func @f(%src : !voidptr, %pattern : !s32i, %len : !u64i) -> !voidptr { - // CHECK: cir.libc.memchr({{.*}}, {{.*}}, {{.*}}) : !s32i, !u64i - %ptr = cir.libc.memchr(%src, %pattern, %len) : !s32i, !u64i + // CHECK: cir.libc.memchr({{.*}}, {{.*}}, {{.*}}) : !cir.ptr<!void>, !s32i, !u64i + %ptr = cir.libc.memchr(%src, %pattern, %len) : !voidptr, !s32i, !u64i cir.return %ptr : !voidptr } } diff --git a/clang/test/CIR/Lowering/memchr-unsupported-target.cir b/clang/test/CIR/Lowering/memchr-unsupported-target.cir deleted file mode 100644 index 818fde91966bf..0000000000000 --- a/clang/test/CIR/Lowering/memchr-unsupported-target.cir +++ /dev/null @@ -1,127 +0,0 @@ -// RUN: cir-opt --cir-to-llvm %s -verify-diagnostics -split-input-file - -!s32i = !cir.int<s, 32> -!u64i = !cir.int<u, 64> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "riscv64-unknown-linux-gnu", - cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { - cir.func @rejects_riscv64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'riscv64-unknown-linux-gnu' with int width 32 and size_t width 64}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "i686-unknown-linux-gnu", - cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { - cir.func @rejects_i686(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'i686-unknown-linux-gnu' with int width 32 and size_t width 32}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u64i = !cir.int<u, 64> -!voidptr = !cir.ptr<!cir.void> - -// expected-error@+1 {{Module has no target triple}} -module attributes {cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { - cir.func @rejects_missing_triple(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op expects the module to record cir.triple}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "x86_64-unknown-linux-gnu", - cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { - cir.func @rejects_x86_64_with_size_t32(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnu' with int width 32 and size_t width 32}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u64i = !cir.int<u, 64> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "arm64_32-apple-watchos", - cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { - cir.func @rejects_arm64_32_with_size_t64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'arm64_32-apple-watchos' with int width 32 and size_t width 64}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u64i = !cir.int<u, 64> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "x86_64-unknown-linux-gnux32", - cir.int_type_width = 32 : i32, cir.size_type_width = 64 : i32} { - cir.func @rejects_x32_with_size_t64(%s: !voidptr, %p: !s32i, %n: !u64i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnux32' with int width 32 and size_t width 64}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u64i - cir.return %r : !voidptr - } -} - -// ----- - -!s16i = !cir.int<s, 16> -!u64i = !cir.int<u, 64> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "x86_64-unknown-linux-gnu", - cir.int_type_width = 16 : i32, cir.size_type_width = 64 : i32} { - cir.func @rejects_x86_64_with_int16(%s: !voidptr, %p: !s16i, %n: !u64i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'x86_64-unknown-linux-gnu' with int width 16 and size_t width 64}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s16i, !u64i - cir.return %r : !voidptr - } -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!voidptr = !cir.ptr<!cir.void> - -module attributes {cir.triple = "aarch64-unknown-linux-gnu", - cir.int_type_width = 32 : i32, cir.size_type_width = 32 : i32} { - cir.func @rejects_aarch64_with_size_t32(%s: !voidptr, %p: !s32i, %n: !u32i) -> !voidptr { - // expected-error@+2 {{'cir.libc.memchr' op lowering is not supported for target 'aarch64-unknown-linux-gnu' with int width 32 and size_t width 32}} - // expected-error@+1 {{failed to legalize operation 'cir.libc.memchr'}} - %r = cir.libc.memchr(%s, %p, %n) : !s32i, !u32i - cir.return %r : !voidptr - } -} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
