[clang] [llvm] [Clang][ABI][X86] Don't extend _BitInt returns to 64-bits (PR #234872)
Nikita Popov via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 23 01:14:20 PDT 2026
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/234872
For X86, _BitInt(N) with N <= 32 is passed iN, while for 32 < N <= 64 it's passed as i64. I don't think there is any good reason for this difference in behavior, and we should always use iN.
Nominally, this does not change the ABI. The previous Direct pass as i64 implied that the high bits are unspecified. In practice, the callee zero-extended the value (independent of _BitInt signedness), but the caller did not rely on that zero-extension. With CIR it was zero or sign extended, depending on signedness. Both are ultimately correct (because the high bits are unspecified).
This still leaves behind a peculiarity for 64 < N < 128, which gets returned as `{ i64, i64 }`, until we reach N=128, when it switches to `i128`. I believe all of those should also use iN, but I'll leave that for a separate change. I'm also not changing argument passing here.
Followup to https://github.com/llvm/llvm-project/pull/232729.
>From e99c4594db5d24754c56cc0cbcf14db75271a9d6 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 23 Oct 2026 10:00:35 +0200
Subject: [PATCH] [Clang][ABI][X86] Don't extend _BitInt returns to 64-bits
For X86, _BitInt(N) with N <= 32 is passed iN, while for 32 < N <= 64
it's passed as i64. I don't think there is any good reason for this
difference in behavior, and we should always use iN.
Nominally, this does not change the ABI. The previous Direct pass
as i64 implied that the high bits are unspecified. In practice,
the callee zero-extended the value (independent of _BitInt
signedness), but the caller did not rely on that zero-extension.
With CIR it was zero or sign extended, depending on signedness.
Both are ultimately correct (because the high bits are unspecified).
This still leaves behind a peculiarity for 64 < N < 128, which gets
returned as `{ i64, i64 }`, until we reach N=128, when it switches
to `i128`. I believe all of those should also use iN, but I'll
leave that for a separate change.
---
clang/lib/CodeGen/Targets/X86.cpp | 3 +-
.../Transforms/abi-lowering/x86_64-bitint.cir | 84 ++++---------------
clang/test/CodeGen/X86/x86_64-abi-size.c | 2 +-
clang/test/CodeGen/ext-int-cc.c | 2 +-
clang/test/CodeGenCXX/ext-int.cpp | 4 +-
llvm/lib/ABI/Targets/X86.cpp | 5 +-
llvm/unittests/ABI/X86TargetInfoTest.cpp | 5 +-
7 files changed, 26 insertions(+), 79 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 4dd9eef4840210..a6789e924dc6f5 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2848,8 +2848,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy) const {
if (const auto *ED = RetTy->getAsEnumDecl())
RetTy = ED->getIntegerType();
- if (RetTy->isIntegralOrEnumerationType() &&
- isPromotableIntegerTypeForABI(RetTy))
+ if (RetTy->isIntegralOrEnumerationType())
return shouldExtendReturnType(*this, RetTy)
? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect();
diff --git a/clang/test/CIR/Transforms/abi-lowering/x86_64-bitint.cir b/clang/test/CIR/Transforms/abi-lowering/x86_64-bitint.cir
index a37021076d63e0..e858299f3f362e 100644
--- a/clang/test/CIR/Transforms/abi-lowering/x86_64-bitint.cir
+++ b/clang/test/CIR/Transforms/abi-lowering/x86_64-bitint.cir
@@ -84,64 +84,44 @@ module attributes {
cir.return %arg0 : !b33i
}
- // CHECK-LABEL: cir.func{{.*}} @ret_b33(%arg0: !u64i) -> !u64i
- // CHECK-NEXT: %[[RETSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
+ // CHECK-LABEL: cir.func{{.*}} @ret_b33(%arg0: !u64i) -> !cir.int<s, 33, bitint>
// CHECK-NEXT: %[[ARGSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: cir.store %arg0, %[[ARGSLOT]] : !u64i, !cir.ptr<!u64i>
// CHECK-NEXT: %[[ARGVIEW:[0-9]+]] = cir.cast bitcast %[[ARGSLOT]]
// CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
// CHECK-NEXT: %[[VAL:[0-9]+]] = cir.load %[[ARGVIEW]]
// CHECK-SAME: : !cir.ptr<!cir.int<s, 33, bitint>>, !cir.int<s, 33, bitint>
- // CHECK-NEXT: %[[RETVIEW:[0-9]+]] = cir.cast bitcast %[[RETSLOT]]
- // CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
- // CHECK-NEXT: cir.store %[[VAL]], %[[RETVIEW]]
- // CHECK-SAME: : !cir.int<s, 33, bitint>, !cir.ptr<!cir.int<s, 33, bitint>>
- // CHECK-NEXT: %[[WIDE:[0-9]+]] = cir.load %[[RETSLOT]] : !cir.ptr<!u64i>, !u64i
- // CHECK-NEXT: cir.return %[[WIDE]] : !u64i
+ // CHECK-NEXT: cir.return %[[VAL]] : !cir.int<s, 33, bitint>
- // LLVM-LABEL: define i64 @ret_b33(
+ // LLVM-LABEL: define i33 @ret_b33(
// LLVM-SAME: i64 %[[ARG:[0-9]+]])
- // LLVM-NEXT: %[[RETSLOT:[0-9]+]] = alloca i64
// LLVM-NEXT: %[[ARGSLOT:[0-9]+]] = alloca i64
// LLVM-NEXT: store i64 %[[ARG]], ptr %[[ARGSLOT]]
// LLVM-NEXT: %[[WIDE:[0-9]+]] = load i64, ptr %[[ARGSLOT]]
// LLVM-NEXT: %[[NARROW:[0-9]+]] = trunc i64 %[[WIDE]] to i33
- // LLVM-NEXT: %[[EXT:[0-9]+]] = sext i33 %[[NARROW]] to i64
- // LLVM-NEXT: store i64 %[[EXT]], ptr %[[RETSLOT]]
- // LLVM-NEXT: %[[RES:[0-9]+]] = load i64, ptr %[[RETSLOT]]
- // LLVM-NEXT: ret i64 %[[RES]]
+ // LLVM-NEXT: ret i33 %[[NARROW]]
// Signedness changes only the extension back into the eightbyte.
cir.func @ret_ub33(%arg0: !ub33i) -> !ub33i {
cir.return %arg0 : !ub33i
}
- // CHECK-LABEL: cir.func{{.*}} @ret_ub33(%arg0: !u64i) -> !u64i
- // CHECK-NEXT: %[[RETSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
+ // CHECK-LABEL: cir.func{{.*}} @ret_ub33(%arg0: !u64i) -> !cir.int<u, 33, bitint>
// CHECK-NEXT: %[[ARGSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: cir.store %arg0, %[[ARGSLOT]] : !u64i, !cir.ptr<!u64i>
// CHECK-NEXT: %[[ARGVIEW:[0-9]+]] = cir.cast bitcast %[[ARGSLOT]]
// CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<u, 33, bitint>>
// CHECK-NEXT: %[[VAL:[0-9]+]] = cir.load %[[ARGVIEW]]
// CHECK-SAME: : !cir.ptr<!cir.int<u, 33, bitint>>, !cir.int<u, 33, bitint>
- // CHECK-NEXT: %[[RETVIEW:[0-9]+]] = cir.cast bitcast %[[RETSLOT]]
- // CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<u, 33, bitint>>
- // CHECK-NEXT: cir.store %[[VAL]], %[[RETVIEW]]
- // CHECK-SAME: : !cir.int<u, 33, bitint>, !cir.ptr<!cir.int<u, 33, bitint>>
- // CHECK-NEXT: %[[WIDE:[0-9]+]] = cir.load %[[RETSLOT]] : !cir.ptr<!u64i>, !u64i
- // CHECK-NEXT: cir.return %[[WIDE]] : !u64i
+ // CHECK-NEXT: cir.return %[[VAL]] : !cir.int<u, 33, bitint>
- // LLVM-LABEL: define i64 @ret_ub33(
+ // LLVM-LABEL: define i33 @ret_ub33(
// LLVM-SAME: i64 %[[ARG:[0-9]+]])
- // LLVM-NEXT: %[[RETSLOT:[0-9]+]] = alloca i64
// LLVM-NEXT: %[[ARGSLOT:[0-9]+]] = alloca i64
// LLVM-NEXT: store i64 %[[ARG]], ptr %[[ARGSLOT]]
// LLVM-NEXT: %[[WIDE:[0-9]+]] = load i64, ptr %[[ARGSLOT]]
// LLVM-NEXT: %[[NARROW:[0-9]+]] = trunc i64 %[[WIDE]] to i33
- // LLVM-NEXT: %[[EXT:[0-9]+]] = zext i33 %[[NARROW]] to i64
- // LLVM-NEXT: store i64 %[[EXT]], ptr %[[RETSLOT]]
- // LLVM-NEXT: %[[RES:[0-9]+]] = load i64, ptr %[[RETSLOT]]
- // LLVM-NEXT: ret i64 %[[RES]]
+ // LLVM-NEXT: ret i33 %[[NARROW]]
// 63 bits fills the eightbyte, and the slot takes whichever type is larger,
// so here it is the bit-precise one and the i64 view moves to the load.
@@ -149,31 +129,21 @@ module attributes {
cir.return %arg0 : !b63i
}
- // CHECK-LABEL: cir.func{{.*}} @ret_b63(%arg0: !u64i) -> !u64i
- // CHECK-NEXT: %[[RETSLOT:[0-9]+]] = cir.alloca "coerce" align(8)
- // CHECK-SAME: : !cir.ptr<!cir.int<s, 63, bitint>>
+ // CHECK-LABEL: cir.func{{.*}} @ret_b63(%arg0: !u64i) -> !cir.int<s, 63, bitint>
// CHECK-NEXT: %[[ARGSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: cir.store %arg0, %[[ARGSLOT]] : !u64i, !cir.ptr<!u64i>
// CHECK-NEXT: %[[ARGVIEW:[0-9]+]] = cir.cast bitcast %[[ARGSLOT]]
// CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 63, bitint>>
// CHECK-NEXT: %[[VAL:[0-9]+]] = cir.load %[[ARGVIEW]]
// CHECK-SAME: : !cir.ptr<!cir.int<s, 63, bitint>>, !cir.int<s, 63, bitint>
- // CHECK-NEXT: cir.store %[[VAL]], %[[RETSLOT]]
- // CHECK-SAME: : !cir.int<s, 63, bitint>, !cir.ptr<!cir.int<s, 63, bitint>>
- // CHECK-NEXT: %[[RETVIEW:[0-9]+]] = cir.cast bitcast %[[RETSLOT]]
- // CHECK-SAME: : !cir.ptr<!cir.int<s, 63, bitint>> -> !cir.ptr<!u64i>
- // CHECK-NEXT: %[[WIDE:[0-9]+]] = cir.load %[[RETVIEW]] : !cir.ptr<!u64i>, !u64i
- // CHECK-NEXT: cir.return %[[WIDE]] : !u64i
+ // CHECK-NEXT: cir.return %[[VAL]] : !cir.int<s, 63, bitint>
- // LLVM-LABEL: define i64 @ret_b63(
+ // LLVM-LABEL: define i63 @ret_b63(
// LLVM-SAME: i64 %[[ARG:[0-9]+]])
// LLVM: store i64 %[[ARG]], ptr %[[ARGSLOT:[0-9]+]], align 8
// LLVM-NEXT: %[[WIDE:[0-9]+]] = load i64, ptr %[[ARGSLOT]], align 8
// LLVM-NEXT: %[[NARROW:[0-9]+]] = trunc i64 %[[WIDE]] to i63
- // LLVM-NEXT: %[[EXT:[0-9]+]] = sext i63 %[[NARROW]] to i64
- // LLVM-NEXT: store i64 %[[EXT]], ptr %[[RETSLOT:[0-9]+]], align 8
- // LLVM-NEXT: %[[RES:[0-9]+]] = load i64, ptr %[[RETSLOT]], align 8
- // LLVM-NEXT: ret i64 %[[RES]]
+ // LLVM-NEXT: ret i63 %[[NARROW]]
// A _BitInt exactly filling one register is Direct, signature unchanged.
cir.func @ret_b64(%arg0: !b64i) -> !b64i {
@@ -345,35 +315,23 @@ module attributes {
cir.return %0 : !b33i
}
- // CHECK-LABEL: cir.func{{.*}} @call_b33(%arg0: !u64i) -> !u64i
- // CHECK-NEXT: %[[RETSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
+ // CHECK-LABEL: cir.func{{.*}} @call_b33(%arg0: !u64i) -> !cir.int<s, 33, bitint>
// CHECK-NEXT: %[[INSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: cir.store %arg0, %[[INSLOT]] : !u64i, !cir.ptr<!u64i>
// CHECK-NEXT: %[[INVIEW:[0-9]+]] = cir.cast bitcast %[[INSLOT]]
// CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
// CHECK-NEXT: %[[VAL:[0-9]+]] = cir.load %[[INVIEW]]
// CHECK-SAME: : !cir.ptr<!cir.int<s, 33, bitint>>, !cir.int<s, 33, bitint>
- // CHECK-NEXT: %[[RESSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: %[[ARGSLOT:[0-9]+]] = cir.alloca "coerce" align(8) : !cir.ptr<!u64i>
// CHECK-NEXT: %[[ARGVIEW:[0-9]+]] = cir.cast bitcast %[[ARGSLOT]]
// CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
// CHECK-NEXT: cir.store %[[VAL]], %[[ARGVIEW]]
// CHECK-SAME: : !cir.int<s, 33, bitint>, !cir.ptr<!cir.int<s, 33, bitint>>
// CHECK-NEXT: %[[WIDE:[0-9]+]] = cir.load %[[ARGSLOT]] : !cir.ptr<!u64i>, !u64i
- // CHECK-NEXT: %[[RES:[0-9]+]] = cir.call @ret_b33(%[[WIDE]]) : (!u64i) -> !u64i
- // CHECK-NEXT: cir.store %[[RES]], %[[RESSLOT]] : !u64i, !cir.ptr<!u64i>
- // CHECK-NEXT: %[[RESVIEW:[0-9]+]] = cir.cast bitcast %[[RESSLOT]]
- // CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
- // CHECK-NEXT: %[[NARROW:[0-9]+]] = cir.load %[[RESVIEW]]
- // CHECK-SAME: : !cir.ptr<!cir.int<s, 33, bitint>>, !cir.int<s, 33, bitint>
- // CHECK-NEXT: %[[RETVIEW:[0-9]+]] = cir.cast bitcast %[[RETSLOT]]
- // CHECK-SAME: : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
- // CHECK-NEXT: cir.store %[[NARROW]], %[[RETVIEW]]
- // CHECK-SAME: : !cir.int<s, 33, bitint>, !cir.ptr<!cir.int<s, 33, bitint>>
- // CHECK-NEXT: %[[OUT:[0-9]+]] = cir.load %[[RETSLOT]] : !cir.ptr<!u64i>, !u64i
- // CHECK-NEXT: cir.return %[[OUT]] : !u64i
+ // CHECK-NEXT: %[[RES:[0-9]+]] = cir.call @ret_b33(%[[WIDE]]) : (!u64i) -> !cir.int<s, 33, bitint>
+ // CHECK-NEXT: cir.return %[[RES]] : !cir.int<s, 33, bitint>
- // LLVM-LABEL: define i64 @call_b33(
+ // LLVM-LABEL: define i33 @call_b33(
// LLVM-SAME: i64 %[[ARG:[0-9]+]])
// LLVM: store i64 %[[ARG]], ptr %[[INSLOT:[0-9]+]], align 8
// LLVM-NEXT: %[[INWIDE:[0-9]+]] = load i64, ptr %[[INSLOT]], align 8
@@ -381,14 +339,8 @@ module attributes {
// LLVM: %[[ARGEXT:[0-9]+]] = sext i33 %[[VAL]] to i64
// LLVM-NEXT: store i64 %[[ARGEXT]], ptr %[[ARGSLOT:[0-9]+]], align 8
// LLVM-NEXT: %[[WIDE:[0-9]+]] = load i64, ptr %[[ARGSLOT]], align 8
- // LLVM-NEXT: %[[RES:[0-9]+]] = call i64 @ret_b33(i64 %[[WIDE]])
- // LLVM-NEXT: store i64 %[[RES]], ptr %[[RESSLOT:[0-9]+]], align 8
- // LLVM-NEXT: %[[RESWIDE:[0-9]+]] = load i64, ptr %[[RESSLOT]], align 8
- // LLVM-NEXT: %[[RESNARROW:[0-9]+]] = trunc i64 %[[RESWIDE]] to i33
- // LLVM-NEXT: %[[RETEXT:[0-9]+]] = sext i33 %[[RESNARROW]] to i64
- // LLVM-NEXT: store i64 %[[RETEXT]], ptr %[[RETSLOT:[0-9]+]], align 8
- // LLVM-NEXT: %[[OUT:[0-9]+]] = load i64, ptr %[[RETSLOT]], align 8
- // LLVM-NEXT: ret i64 %[[OUT]]
+ // LLVM-NEXT: %[[RES:[0-9]+]] = call i33 @ret_b33(i64 %[[WIDE]])
+ // LLVM-NEXT: ret i33 %[[RES]]
// A call site decomposes the argument into the two registers the callee
// expects and reassembles the returned pair.
diff --git a/clang/test/CodeGen/X86/x86_64-abi-size.c b/clang/test/CodeGen/X86/x86_64-abi-size.c
index 6a2760a120a942..721140a3aff1d0 100644
--- a/clang/test/CodeGen/X86/x86_64-abi-size.c
+++ b/clang/test/CodeGen/X86/x86_64-abi-size.c
@@ -104,7 +104,7 @@ union LSFirst lsfirst(union LSFirst u) { return u; }
// In registers a _BitInt is coerced to the eightbytes covering its storage.
_BitInt(40) bi40(_BitInt(40) x) { return x; }
-// CHECK: define dso_local i64 @bi40(i64 noundef %{{.*}})
+// CHECK: define dso_local i40 @bi40(i64 noundef %{{.*}})
_BitInt(100) bi100(_BitInt(100) x) { return x; }
// CHECK: define dso_local { i64, i64 } @bi100(i64 noundef %{{.*}}, i64 noundef %{{.*}})
diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c
index 0872991252eb5b..3fdbe5240e3928 100644
--- a/clang/test/CodeGen/ext-int-cc.c
+++ b/clang/test/CodeGen/ext-int-cc.c
@@ -159,7 +159,7 @@ void ParamPassing4(_BitInt(129) a) {}
#endif
_BitInt(63) ReturnPassing(void) { return 0; }
-// LIN64: define{{.*}} i64 @ReturnPassing(
+// LIN64: define{{.*}} i63 @ReturnPassing(
// WIN64: define dso_local i63 @ReturnPassing(
// LIN32: define{{.*}} i63 @ReturnPassing(
// WIN32: define dso_local i63 @ReturnPassing(
diff --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp
index 6ea5d2e7dcd8eb..95e81dd47d33fe 100644
--- a/clang/test/CodeGenCXX/ext-int.cpp
+++ b/clang/test/CodeGenCXX/ext-int.cpp
@@ -111,14 +111,14 @@ void BitfieldAssignment() {
}
unsigned _BitInt(33) ManglingTestRetParam(unsigned _BitInt(33) Param) {
-// LIN64: define{{.*}} i64 @_Z20ManglingTestRetParamDU33_(i64 %
+// LIN64: define{{.*}} i33 @_Z20ManglingTestRetParamDU33_(i64 %
// LIN32: define{{.*}} i33 @_Z20ManglingTestRetParamDU33_(i33 %
// WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_UBitInt@$0CB@@__clang@@U12@@Z"(i33
return 0;
}
_BitInt(33) ManglingTestRetParam(_BitInt(33) Param) {
-// LIN64: define{{.*}} i64 @_Z20ManglingTestRetParamDB33_(i64 %
+// LIN64: define{{.*}} i33 @_Z20ManglingTestRetParamDB33_(i64 %
// LIN32: define{{.*}} i33 @_Z20ManglingTestRetParamDB33_(i33 %
// WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_BitInt@$0CB@@__clang@@U12@@Z"(i33
return 0;
diff --git a/llvm/lib/ABI/Targets/X86.cpp b/llvm/lib/ABI/Targets/X86.cpp
index 26f2d682ad5d31..d04d624e1b9dd5 100644
--- a/llvm/lib/ABI/Targets/X86.cpp
+++ b/llvm/lib/ABI/Targets/X86.cpp
@@ -759,9 +759,8 @@ ArgInfo X86_64TargetInfo::classifyReturnType(const Type *RetTy) const {
// so that the parameter gets the right LLVM IR attributes.
if (Hi == NoClass && ResType->isInteger()) {
if (const IntegerType *IntTy = dyn_cast<IntegerType>(RetTy))
- if (isPromotableInteger(IntTy))
- return shouldExtendReturnType(IntTy) ? ArgInfo::getExtend(RetTy)
- : ArgInfo::getDirect(RetTy);
+ return shouldExtendReturnType(IntTy) ? ArgInfo::getExtend(RetTy)
+ : ArgInfo::getDirect(RetTy);
}
if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
assert(Hi == Integer);
diff --git a/llvm/unittests/ABI/X86TargetInfoTest.cpp b/llvm/unittests/ABI/X86TargetInfoTest.cpp
index 29dfb4ce1de362..4511c703f12f5d 100644
--- a/llvm/unittests/ABI/X86TargetInfoTest.cpp
+++ b/llvm/unittests/ABI/X86TargetInfoTest.cpp
@@ -942,13 +942,10 @@ TEST_F(X86TargetInfoTest, IntReturnExtension) {
TB.getIntegerType(13, llvm::Align(2), /*IsSigned=*/true,
/*IsBitInt=*/true);
expectDirectInteger(classifyRet(BitInt13, FI, TI), 13);
-
- // _BitInt > 32-bit gets passed as 64-bit, to match Clang ABI behavior.
- // Returning this as i40 would be equivalent.
const ABIType *BitInt40 =
TB.getIntegerType(40, llvm::Align(8), /*IsSigned=*/false,
/*IsBitInt=*/true);
- expectDirectInteger(classifyRet(BitInt40, FI, TI), 64);
+ expectDirectInteger(classifyRet(BitInt40, FI, TI), 40);
// char, short and int must not be extended.
expectDirectInteger(classifyRet(I8, FI, TI), 8);
More information about the cfe-commits
mailing list