Skip to content

Commit c0d0f3c

Browse files
committed
fix bswapg codegen and add c++ tests
1 parent fa016a1 commit c0d0f3c

File tree

5 files changed

+136
-4
lines changed

5 files changed

+136
-4
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13988,7 +13988,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1398813988
return false;
1398913989
if (Val.getBitWidth() == 8)
1399013990
return Success(Val, E);
13991-
13991+
1399213992
return Success(Val.byteSwap(), E);
1399313993
}
1399413994

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3622,7 +3622,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
36223622
Builder.CreateArithmeticFence(ArgValue, ConvertType(ArgType)));
36233623
return RValue::get(ArgValue);
36243624
}
3625-
case Builtin::BI__builtin_bswapg:
3625+
case Builtin::BI__builtin_bswapg: {
3626+
Value *ArgValue = EmitScalarExpr(E->getArg(0));
3627+
llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
3628+
assert(IntTy && "LLVM's __builtin_bswapg only supports integer variants");
3629+
if (IntTy->getBitWidth() == 8)
3630+
return RValue::get(ArgValue);
3631+
return RValue::get(
3632+
emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bswap));
3633+
}
36263634
case Builtin::BI__builtin_bswap16:
36273635
case Builtin::BI__builtin_bswap32:
36283636
case Builtin::BI__builtin_bswap64:

clang/lib/Sema/SemaChecking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3476,7 +3476,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
34763476
}
34773477
case Builtin::BI__builtin_bswapg:
34783478
if (BuiltinBswapg(*this, TheCall))
3479-
return ExprError();
3479+
return ExprError();
34803480
break;
34813481
case Builtin::BI__builtin_popcountg:
34823482
if (BuiltinPopcountg(*this, TheCall))

clang/test/CodeGen/builtins.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ int main(void) {
130130
P(object_size, (s0, 3));
131131

132132
// Whatever
133-
P(bswapg, (N));
133+
P(bswapg, ((char)N));
134+
P(bswapg, ((short)N));
135+
P(bswapg, ((int)N));
136+
P(bswapg, ((unsigned long)N));
134137
P(bswap16, (N));
135138
P(bswap32, (N));
136139
P(bswap64, (N));

clang/test/Sema/builtin-bswapg.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
3+
// expected-no-diagnostics
4+
template <class A, class B>
5+
static constexpr bool is_same_type = false;
6+
7+
template <class A>
8+
static constexpr bool is_same_type<A, A> = true;
9+
10+
void test_basic_type_checks() {
11+
static_assert(is_same_type<char, decltype(__builtin_bswapg((char)0))>, "");
12+
static_assert(is_same_type<unsigned char, decltype(__builtin_bswapg((unsigned char)0))>, "");
13+
static_assert(is_same_type<short, decltype(__builtin_bswapg((short)0))>, "");
14+
static_assert(is_same_type<unsigned short, decltype(__builtin_bswapg((unsigned short)0))>, "");
15+
static_assert(is_same_type<int, decltype(__builtin_bswapg((int)0))>, "");
16+
static_assert(is_same_type<unsigned int, decltype(__builtin_bswapg((unsigned int)0))>, "");
17+
static_assert(is_same_type<long, decltype(__builtin_bswapg((long)0))>, "");
18+
static_assert(is_same_type<unsigned long, decltype(__builtin_bswapg((unsigned long)0))>, "");
19+
}
20+
21+
template<typename T>
22+
void test_template_type_check() {
23+
static_assert(is_same_type<T, decltype(__builtin_bswapg(T{}))>,
24+
"bswapg should return the same type as its argument");
25+
constexpr T zero{};
26+
constexpr T max = ~T{};
27+
constexpr T one = T{1};
28+
29+
static_assert(is_same_type<T, decltype(__builtin_bswapg(zero))>, "");
30+
static_assert(is_same_type<T, decltype(__builtin_bswapg(max))>, "");
31+
static_assert(is_same_type<T, decltype(__builtin_bswapg(one))>, "");
32+
}
33+
template void test_template_type_check<char>();
34+
template void test_template_type_check<unsigned char>();
35+
template void test_template_type_check<short>();
36+
template void test_template_type_check<unsigned short>();
37+
template void test_template_type_check<int>();
38+
template void test_template_type_check<unsigned int>();
39+
template void test_template_type_check<long>();
40+
template void test_template_type_check<unsigned long>();
41+
42+
void test_lambda_type_checks() {
43+
auto lambda = [](auto x) {
44+
static_assert(is_same_type<decltype(x), decltype(__builtin_bswapg(x))>,
45+
"bswapg in lambda should preserve type");
46+
return __builtin_bswapg(x);
47+
};
48+
auto result_long = lambda(42UL);
49+
static_assert(is_same_type<unsigned long, decltype(result_long)>, "");
50+
51+
auto result_int = lambda(42);
52+
static_assert(is_same_type<int, decltype(result_int)>, "");
53+
54+
auto result_short = lambda(static_cast<short>(42));
55+
static_assert(is_same_type<short, decltype(result_short)>, "");
56+
57+
auto result_char = lambda(static_cast<char>(42));
58+
static_assert(is_same_type<char, decltype(result_char)>, "");
59+
}
60+
61+
auto test_auto_return_type_long(long x) {
62+
auto result = __builtin_bswapg(x);
63+
static_assert(is_same_type<long, decltype(result)>, "");
64+
return result;
65+
}
66+
67+
auto test_auto_return_type_int(int x) {
68+
auto result = __builtin_bswapg(x);
69+
static_assert(is_same_type<int, decltype(result)>, "");
70+
return result;
71+
}
72+
73+
auto test_auto_return_type_short(short x) {
74+
auto result = __builtin_bswapg(x);
75+
static_assert(is_same_type<short, decltype(result)>, "");
76+
return result;
77+
}
78+
79+
auto test_auto_return_type_char(char x) {
80+
auto result = __builtin_bswapg(x);
81+
static_assert(is_same_type<char, decltype(result)>, "");
82+
return result;
83+
}
84+
85+
void test_auto_return_type() {
86+
test_auto_return_type_long(42);
87+
test_auto_return_type_int(42);
88+
test_auto_return_type_short(42);
89+
test_auto_return_type_char(42);
90+
}
91+
92+
decltype(auto) test_decltype_auto(int x) {
93+
return __builtin_bswapg(x);
94+
}
95+
96+
void test_decltype_auto_check() {
97+
int x = 42;
98+
auto result = test_decltype_auto(x);
99+
static_assert(is_same_type<int, decltype(result)>, "");
100+
}
101+
102+
template<auto Value>
103+
struct ValueTemplateTypeTest {
104+
using value_type = decltype(Value);
105+
using result_type = decltype(__builtin_bswapg(Value));
106+
107+
static constexpr bool type_matches = is_same_type<value_type, result_type>;
108+
static_assert(type_matches, "Value template bswapg should preserve type");
109+
110+
static constexpr auto swapped_value = __builtin_bswapg(Value);
111+
};
112+
113+
template<auto... Values>
114+
void test_template_pack_types() {
115+
static_assert((is_same_type<decltype(Values), decltype(__builtin_bswapg(Values))> && ...), "All pack elements should preserve type");
116+
}
117+
118+
template struct ValueTemplateTypeTest<0x1234>;
119+
template struct ValueTemplateTypeTest<0x12345678UL>;
120+
template struct ValueTemplateTypeTest<(short)0x1234>;
121+
template struct ValueTemplateTypeTest<(char)0x12>;

0 commit comments

Comments
 (0)