Index: cfe/trunk/include/clang/Basic/Builtins.def =================================================================== --- cfe/trunk/include/clang/Basic/Builtins.def +++ cfe/trunk/include/clang/Basic/Builtins.def @@ -50,7 +50,8 @@ // 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 @@ -418,25 +419,27 @@ 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") Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -9286,7 +9286,7 @@ // Read the prefixed modifiers first. bool Done = false; #ifndef NDEBUG - bool IsSpecialLong = false; + bool IsSpecial = false; #endif while (!Done) { switch (*Str++) { @@ -9305,26 +9305,26 @@ 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: @@ -9337,6 +9337,27 @@ 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; } } Index: cfe/trunk/test/CodeGen/avr-builtins.c =================================================================== --- cfe/trunk/test/CodeGen/avr-builtins.c +++ cfe/trunk/test/CodeGen/avr-builtins.c @@ -0,0 +1,102 @@ +// 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 Index: cfe/trunk/test/CodeGen/builtins.cpp =================================================================== --- cfe/trunk/test/CodeGen/builtins.cpp +++ cfe/trunk/test/CodeGen/builtins.cpp @@ -0,0 +1,52 @@ +// 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 '' with a different type: '' vs '' +// (with gcc you get an error message +// "conflicting declaration ' '"). + +#include + +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