// L -> long (e.g. Li for 'long int', Ld for 'long double')
// LL -> long long (e.g. LLi for 'long long int', LLd for __float128)
// LLL -> __int128_t (e.g. LLLi)
-// W -> int64_t
+// Z -> int32_t (require a native 32-bit integer type on the target)
+// W -> int64_t (require a native 64-bit integer type on the target)
// N -> 'int' size if target is LP64, 'L' otherwise.
// S -> signed
// U -> unsigned
BUILTIN(__builtin_clrsbl , "iLi" , "nc")
BUILTIN(__builtin_clrsbll, "iLLi", "nc")
-// FIXME: These type signatures are not correct for targets with int != 32-bits
-// or with ULL != 64-bits.
+// The following builtins rely on that char == 8 bits, short == 16 bits and that
+// there exists native types on the target that are 32- and 64-bits wide, unless
+// these conditions are fulfilled these builtins will operate on a not intended
+// bitwidth.
BUILTIN(__builtin_bswap16, "UsUs", "nc")
-BUILTIN(__builtin_bswap32, "UiUi", "nc")
-BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
+BUILTIN(__builtin_bswap32, "UZiUZi", "nc")
+BUILTIN(__builtin_bswap64, "UWiUWi", "nc")
BUILTIN(__builtin_bitreverse8, "UcUc", "nc")
BUILTIN(__builtin_bitreverse16, "UsUs", "nc")
-BUILTIN(__builtin_bitreverse32, "UiUi", "nc")
-BUILTIN(__builtin_bitreverse64, "ULLiULLi", "nc")
+BUILTIN(__builtin_bitreverse32, "UZiUZi", "nc")
+BUILTIN(__builtin_bitreverse64, "UWiUWi", "nc")
BUILTIN(__builtin_rotateleft8, "UcUcUc", "nc")
BUILTIN(__builtin_rotateleft16, "UsUsUs", "nc")
-BUILTIN(__builtin_rotateleft32, "UiUiUi", "nc")
-BUILTIN(__builtin_rotateleft64, "ULLiULLiULLi", "nc")
+BUILTIN(__builtin_rotateleft32, "UZiUZiUZi", "nc")
+BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "nc")
BUILTIN(__builtin_rotateright8, "UcUcUc", "nc")
BUILTIN(__builtin_rotateright16, "UsUsUs", "nc")
-BUILTIN(__builtin_rotateright32, "UiUiUi", "nc")
-BUILTIN(__builtin_rotateright64, "ULLiULLiULLi", "nc")
+BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "nc")
+BUILTIN(__builtin_rotateright64, "UWiUWiWi", "nc")
// Random GCC builtins
BUILTIN(__builtin_constant_p, "i.", "nctu")
// Read the prefixed modifiers first.
bool Done = false;
#ifndef NDEBUG
- bool IsSpecialLong = false;
+ bool IsSpecial = false;
#endif
while (!Done) {
switch (*Str++) {
Unsigned = true;
break;
case 'L':
- assert(!IsSpecialLong && "Can't use 'L' with 'W' or 'N' modifiers");
+ assert(!IsSpecial && "Can't use 'L' with 'W', 'N' or 'Z' modifiers");
assert(HowLong <= 2 && "Can't have LLLL modifier");
++HowLong;
break;
case 'N':
// 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise.
- assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
+ assert(!IsSpecial && "Can't use two 'N', 'W' or 'Z' modifiers!");
assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!");
#ifndef NDEBUG
- IsSpecialLong = true;
+ IsSpecial = true;
#endif
if (Context.getTargetInfo().getLongWidth() == 32)
++HowLong;
break;
case 'W':
// This modifier represents int64 type.
- assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
+ assert(!IsSpecial && "Can't use two 'N', 'W' or 'Z' modifiers!");
assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!");
#ifndef NDEBUG
- IsSpecialLong = true;
+ IsSpecial = true;
#endif
switch (Context.getTargetInfo().getInt64Type()) {
default:
break;
}
break;
+ case 'Z':
+ // This modifier represents int32 type.
+ assert(!IsSpecial && "Can't use two 'N', 'W' or 'Z' modifiers!");
+ assert(HowLong == 0 && "Can't use both 'L' and 'Z' modifiers!");
+ #ifndef NDEBUG
+ IsSpecial = true;
+ #endif
+ switch (Context.getTargetInfo().getIntTypeByWidth(32, true)) {
+ default:
+ llvm_unreachable("Unexpected integer type");
+ case TargetInfo::SignedInt:
+ HowLong = 0;
+ break;
+ case TargetInfo::SignedLong:
+ HowLong = 1;
+ break;
+ case TargetInfo::SignedLongLong:
+ HowLong = 2;
+ break;
+ }
+ break;
}
}
--- /dev/null
+// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+unsigned char bitrev8(unsigned char data) {
+ return __builtin_bitreverse8(data);
+}
+
+// CHECK: define zeroext i8 @bitrev8
+// CHECK: i8 @llvm.bitreverse.i8(i8
+
+unsigned int bitrev16(unsigned int data) {
+ return __builtin_bitreverse16(data);
+}
+
+// CHECK: define i16 @bitrev16
+// CHECK: i16 @llvm.bitreverse.i16(i16
+
+unsigned long bitrev32(unsigned long data) {
+ return __builtin_bitreverse32(data);
+}
+// CHECK: define i32 @bitrev32
+// CHECK: i32 @llvm.bitreverse.i32(i32
+
+unsigned long long bitrev64(unsigned long long data) {
+ return __builtin_bitreverse64(data);
+}
+
+// CHECK: define i64 @bitrev64
+// CHECK: i64 @llvm.bitreverse.i64(i64
+
+unsigned char rotleft8(unsigned char x, unsigned char y) {
+ return __builtin_rotateleft8(x, y);
+}
+
+// CHECK: define zeroext i8 @rotleft8
+// CHECK: i8 @llvm.fshl.i8(i8
+
+unsigned int rotleft16(unsigned int x, unsigned int y) {
+ return __builtin_rotateleft16(x, y);
+}
+
+// CHECK: define i16 @rotleft16
+// CHECK: i16 @llvm.fshl.i16(i16
+
+unsigned long rotleft32(unsigned long x, unsigned long y) {
+ return __builtin_rotateleft32(x, y);
+}
+// CHECK: define i32 @rotleft32
+// CHECK: i32 @llvm.fshl.i32(i32
+
+unsigned long long rotleft64(unsigned long long x, unsigned long long y) {
+ return __builtin_rotateleft64(x, y);
+}
+
+// CHECK: define i64 @rotleft64
+// CHECK: i64 @llvm.fshl.i64(i64
+
+unsigned char rotright8(unsigned char x, unsigned char y) {
+ return __builtin_rotateright8(x, y);
+}
+
+// CHECK: define zeroext i8 @rotright8
+// CHECK: i8 @llvm.fshr.i8(i8
+
+unsigned int rotright16(unsigned int x, unsigned int y) {
+ return __builtin_rotateright16(x, y);
+}
+
+// CHECK: define i16 @rotright16
+// CHECK: i16 @llvm.fshr.i16(i16
+
+unsigned long rotright32(unsigned long x, unsigned long y) {
+ return __builtin_rotateright32(x, y);
+}
+// CHECK: define i32 @rotright32
+// CHECK: i32 @llvm.fshr.i32(i32
+
+unsigned long long rotright64(unsigned long long x, unsigned long long y) {
+ return __builtin_rotateright64(x, y);
+}
+
+// CHECK: define i64 @rotright64
+// CHECK: i64 @llvm.fshr.i64(i64
+
+unsigned int byteswap16(unsigned int x) {
+ return __builtin_bswap16(x);
+}
+
+// CHECK: define i16 @byteswap16
+// CHECK: i16 @llvm.bswap.i16(i16
+
+unsigned long byteswap32(unsigned long x) {
+ return __builtin_bswap32(x);
+}
+// CHECK: define i32 @byteswap32
+// CHECK: i32 @llvm.bswap.i32(i32
+
+unsigned long long byteswap64(unsigned long long x) {
+ return __builtin_bswap64(x);
+}
+
+// CHECK: define i64 @byteswap64
+// CHECK: i64 @llvm.bswap.i64(i64
--- /dev/null
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -ffreestanding -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple i686-pc-linux-gnu -ffreestanding -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple avr-unknown-unknown -ffreestanding -verify %s
+
+// expected-no-diagnostics
+
+// Test that checks that the builtins return the same type as the stdint.h type
+// withe the same witdh. This is done by first declaring a variable of a stdint
+// type of the correct width and the redeclaring the variable with the type that
+// the builting return. If the types are different you should the an error from
+// clang of the form:
+// "redefinition of '<varname>' with a different type: '<type1>' vs '<type2>'
+// (with gcc you get an error message
+// "conflicting declaration '<type> <varname>'").
+
+#include <stdint.h>
+
+extern uint16_t bswap16;
+decltype(__builtin_bswap16(0)) bswap16 = 42;
+extern uint32_t bswap32;
+decltype(__builtin_bswap32(0)) bswap32 = 42;
+extern uint64_t bswap64;
+decltype(__builtin_bswap64(0)) bswap64 = 42;
+
+#ifdef __clang__
+extern uint8_t bitrev8;
+decltype(__builtin_bitreverse8(0)) bitrev8 = 42;
+extern uint16_t bitrev16;
+decltype(__builtin_bitreverse16(0)) bitrev16 = 42;
+extern uint32_t bitrev32;
+decltype(__builtin_bitreverse32(0)) bitrev32 = 42;
+extern uint64_t bitrev64;
+decltype(__builtin_bitreverse64(0)) bitrev64 = 42;
+
+extern uint8_t rotl8;
+decltype(__builtin_rotateleft8(0,0)) rotl8 = 42;
+extern uint16_t rotl16;
+decltype(__builtin_rotateleft16(0,0)) rotl16 = 42;
+extern uint32_t rotl32;
+decltype(__builtin_rotateleft32(0,0)) rotl32 = 42;
+extern uint64_t rotl64;
+decltype(__builtin_rotateleft64(0,0)) rotl64 = 42;
+
+extern uint8_t rotr8;
+decltype(__builtin_rotateright8(0,0)) rotr8 = 42;
+extern uint16_t rotr16;
+decltype(__builtin_rotateright16(0,0)) rotr16 = 42;
+extern uint32_t rotr32;
+decltype(__builtin_rotateright32(0,0)) rotr32 = 42;
+extern uint64_t rotr64;
+decltype(__builtin_rotateright64(0,0)) rotr64 = 42;
+#endif