llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: None (adams381) <details> <summary>Changes</summary> Add an optional `bitint` parameter to `cir::IntType` so CIR can distinguish `_BitInt(N)` from builtin integer types like `__int128`. Both lower to the same LLVM integer type, but they have different ABI rules (alignment, passing convention) on x86_64. The flag is set during CIRGen for `Type::BitInt`, printed/parsed as `!cir.int<s, 128, bitint>`, and excluded from `isFundamental()`. Existing 2-arg `IntType::get()` calls continue to work via a default parameter. --- Full diff: https://github.com/llvm/llvm-project/pull/188113.diff 7 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+16-3) - (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+2-1) - (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+16-3) - (added) clang/test/CIR/CodeGen/bitint.c (+32) - (modified) clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp (+15-15) - (added) clang/test/CIR/IR/bitint.cir (+20) - (modified) clang/test/CIR/global-var-simple.cpp (+2-2) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 450c02135e033..f14d6099304ce 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -50,21 +50,34 @@ def CIR_IntType : CIR_Type<"Int", "int", [ fundamental integer types. Said types are: `signed char`, `short`, `int`, `long`, `long long`, and their unsigned variations. }]; - let parameters = (ins "unsigned":$width, "bool":$isSigned); + let parameters = (ins "unsigned":$width, "bool":$isSigned, + DefaultValuedParameter<"bool", "false">:$bitInt); + let builders = [ + TypeBuilder<(ins "unsigned":$width, "bool":$isSigned), [{ + return $_get($_ctxt, width, isSigned, /*bitInt=*/false); + }]>, + ]; let hasCustomAssemblyFormat = 1; let extraClassDeclaration = [{ /// Return true if this is a signed integer type. bool isSigned() const { return getIsSigned(); } /// Return true if this is an unsigned integer type. bool isUnsigned() const { return !getIsSigned(); } + /// Return true if this is a _BitInt type. + bool isBitInt() const { return getBitInt(); } /// Return type alias. std::string getAlias() const { - return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i'; + std::string alias = + (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i'; + if (isBitInt()) + alias += "_bitint"; + return alias; } /// Return true if this is a fundamental integer type (i.e. signed or /// unsigned integer types whose bit width is 8, 16, 32, or 64). + /// _BitInt types are never fundamental even if their width matches. bool isFundamental() const { - return isFundamentalIntType(*this); + return !isBitInt() && isFundamentalIntType(*this); } bool isSignedFundamental() const { return isFundamentalSIntType(*this); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 2092964bac065..c86ddbb44a501 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -564,7 +564,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) { resultType = cgm.sInt32Ty; } else { resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(), - bitIntTy->isSigned()); + bitIntTy->isSigned(), + /*bitInt=*/true); } break; } diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index d96975b3e6aa7..1da59b7815ab5 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -499,15 +499,28 @@ Type IntType::parse(mlir::AsmParser &parser) { return {}; } + bool bitInt = false; + if (succeeded(parser.parseOptionalComma())) { + llvm::StringRef kw; + if (parser.parseKeyword(&kw) || kw != "bitint") { + parser.emitError(loc, "expected 'bitint'"); + return {}; + } + bitInt = true; + } + if (parser.parseGreater()) return {}; - return IntType::get(context, width, isSigned); + return IntType::get(context, width, isSigned, bitInt); } void IntType::print(mlir::AsmPrinter &printer) const { char sign = isSigned() ? 's' : 'u'; - printer << '<' << sign << ", " << getWidth() << '>'; + printer << '<' << sign << ", " << getWidth(); + if (isBitInt()) + printer << ", bitint"; + printer << '>'; } llvm::TypeSize @@ -523,7 +536,7 @@ uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout, mlir::LogicalResult IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, - unsigned width, bool isSigned) { + unsigned width, bool isSigned, bool bitInt) { if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) return emitError() << "IntType only supports widths from " << IntType::minBitwidth() << " up to " diff --git a/clang/test/CIR/CodeGen/bitint.c b/clang/test/CIR/CodeGen/bitint.c new file mode 100644 index 0000000000000..1f02c6f3eaaba --- /dev/null +++ b/clang/test/CIR/CodeGen/bitint.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// 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=OGCG --input-file=%t.ll %s + +// _BitInt types are distinguished from regular integer types via the +// "bitint" keyword in CIR. Verify that the type alias includes "_bitint" +// and that regular __int128 does not. + +// CIR-DAG: !s32i_bitint = !cir.int<s, 32, bitint> +// CIR-DAG: !s128i_bitint = !cir.int<s, 128, bitint> +// CIR-DAG: !u64i_bitint = !cir.int<u, 64, bitint> +// CIR-DAG: !s128i = !cir.int<s, 128> + +void take_bitint_32(_BitInt(32) x) {} +// LLVM: define {{.*}} void @take_bitint_32(i32 {{.*}}) +// OGCG: define {{.*}} void @take_bitint_32(i32 {{.*}}) + +void take_bitint_128(signed _BitInt(128) x) {} +// LLVM: define {{.*}} void @take_bitint_128(i128 {{.*}}) +// OGCG: define {{.*}} void @take_bitint_128(i128 {{.*}}) + +void take_unsigned_bitint(unsigned _BitInt(64) x) {} +// LLVM: define {{.*}} void @take_unsigned_bitint(i64 {{.*}}) +// OGCG: define {{.*}} void @take_unsigned_bitint(i64 {{.*}}) + +// Regular __int128 should NOT have the bitint flag. +void take_int128(__int128 x) {} +// LLVM: define {{.*}} void @take_int128(i128 {{.*}}) +// OGCG: define {{.*}} void @take_int128(i128 {{.*}}) diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp b/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp index 1c674ff5a297a..8089a538d733b 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp +++ b/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp @@ -40,11 +40,11 @@ bool test_add_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y, _BitIn } // CIR: cir.func {{.*}} @_Z38test_add_overflow_xint31_xint31_xint31DB31_S_PS_ -// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>> -// CIR-NEXT: %[[RES:.+]], %{{.+}} = cir.add.overflow %[[#LHS]], %[[#RHS]] : !cir.int<s, 31> -> !cir.int<s, 31> -// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, !cir.ptr<!cir.int<s, 31>> +// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>> +// CIR: %[[RES:.+]], %{{.+}} = cir.add.overflow %{{.+}}, %{{.+}} : !cir.int<s, 31> -> !cir.int<s, 31, bitint> +// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, bitint>, !cir.ptr<!cir.int<s, 31, bitint>> // CIR: } bool test_sub_overflow_uint_uint_uint(unsigned x, unsigned y, unsigned *res) { @@ -76,11 +76,11 @@ bool test_sub_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y, _BitIn } // CIR: cir.func {{.*}} @_Z38test_sub_overflow_xint31_xint31_xint31DB31_S_PS_ -// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>> -// CIR-NEXT: %[[RES:.+]], %{{.+}} = cir.sub.overflow %[[#LHS]], %[[#RHS]] : !cir.int<s, 31> -> !cir.int<s, 31> -// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, !cir.ptr<!cir.int<s, 31>> +// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>> +// CIR: %[[RES:.+]], %{{.+}} = cir.sub.overflow %{{.+}}, %{{.+}} : !cir.int<s, 31> -> !cir.int<s, 31, bitint> +// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, bitint>, !cir.ptr<!cir.int<s, 31, bitint>> // CIR: } bool test_mul_overflow_uint_uint_uint(unsigned x, unsigned y, unsigned *res) { @@ -112,11 +112,11 @@ bool test_mul_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y, _BitIn } // CIR: cir.func {{.*}} @_Z38test_mul_overflow_xint31_xint31_xint31DB31_S_PS_ -// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31>>, !cir.int<s, 31> -// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>> -// CIR-NEXT: %[[RES:.+]], %{{.+}} = cir.mul.overflow %[[#LHS]], %[[#RHS]] : !cir.int<s, 31> -> !cir.int<s, 31> -// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, !cir.ptr<!cir.int<s, 31>> +// CIR: %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint> +// CIR-NEXT: %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>> +// CIR: %[[RES:.+]], %{{.+}} = cir.mul.overflow %{{.+}}, %{{.+}} : !cir.int<s, 31> -> !cir.int<s, 31, bitint> +// CIR-NEXT: cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, bitint>, !cir.ptr<!cir.int<s, 31, bitint>> // CIR: } bool test_mul_overflow_ulong_ulong_long(unsigned long x, unsigned long y, unsigned long *res) { diff --git a/clang/test/CIR/IR/bitint.cir b/clang/test/CIR/IR/bitint.cir new file mode 100644 index 0000000000000..5dddddc833777 --- /dev/null +++ b/clang/test/CIR/IR/bitint.cir @@ -0,0 +1,20 @@ +// RUN: cir-opt %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +!s32i = !cir.int<s, 32> +!s32i_bitint = !cir.int<s, 32, bitint> +!u64i_bitint = !cir.int<u, 64, bitint> +!s128i_bitint = !cir.int<s, 128, bitint> + +module { + // CHECK: cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint) + cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint) { + cir.return + } + + // Regular int should NOT print bitint. + // CHECK: cir.func @round_trip_regular(%arg0: !s32i) + cir.func @round_trip_regular(%arg0: !s32i) { + cir.return + } +} diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp index 4608089058fb4..68e44c926110c 100644 --- a/clang/test/CIR/global-var-simple.cpp +++ b/clang/test/CIR/global-var-simple.cpp @@ -53,10 +53,10 @@ char32_t c32; // CHECK: cir.global external @c32 = #cir.int<0> : !u32i _BitInt(20) sb20; -// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20> +// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20, bitint> unsigned _BitInt(48) ub48; -// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48> +// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48, bitint> bool boolfalse = false; // CHECK: cir.global external @boolfalse = #false `````````` </details> https://github.com/llvm/llvm-project/pull/188113 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
