Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1797,6 +1797,10 @@ case BuiltinType::UShortAccum: case BuiltinType::ShortFract: case BuiltinType::UShortFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatUShortFract: Width = Target->getShortWidth(); Align = Target->getShortAlign(); break; @@ -1806,6 +1810,10 @@ case BuiltinType::UAccum: case BuiltinType::Fract: case BuiltinType::UFract: + case BuiltinType::SatAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatFract: + case BuiltinType::SatUFract: Width = Target->getIntWidth(); Align = Target->getIntAlign(); break; @@ -1815,6 +1823,10 @@ case BuiltinType::ULongAccum: case BuiltinType::LongFract: case BuiltinType::ULongFract: + case BuiltinType::SatLongAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatLongFract: + case BuiltinType::SatULongFract: Width = Target->getLongWidth(); Align = Target->getLongAlign(); break; Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -2204,17 +2204,29 @@ const auto *BT = type->getAs(); switch (BT->getKind()) { default: llvm_unreachable("Not a fixed point type!"); + case BuiltinType::SatShortAccum: case BuiltinType::ShortAccum: fbits = BUILTIN_SACCUM_FBIT; break; + case BuiltinType::SatAccum: case BuiltinType::Accum: fbits = BUILTIN_ACCUM_FBIT; break; + case BuiltinType::SatLongAccum: case BuiltinType::LongAccum: fbits = BUILTIN_LACCUM_FBIT; break; + case BuiltinType::SatUShortAccum: case BuiltinType::UShortAccum: fbits = BUILTIN_USACCUM_FBIT; break; + case BuiltinType::SatUAccum: case BuiltinType::UAccum: fbits = BUILTIN_UACCUM_FBIT; break; + case BuiltinType::SatULongAccum: case BuiltinType::ULongAccum: fbits = BUILTIN_ULACCUM_FBIT; break; + case BuiltinType::SatShortFract: case BuiltinType::ShortFract: fbits = BUILTIN_SFRACT_FBIT; break; + case BuiltinType::SatFract: case BuiltinType::Fract: fbits = BUILTIN_FRACT_FBIT; break; + case BuiltinType::SatLongFract: case BuiltinType::LongFract: fbits = BUILTIN_LFRACT_FBIT; break; + case BuiltinType::SatUShortFract: case BuiltinType::UShortFract: fbits = BUILTIN_USFRACT_FBIT; break; + case BuiltinType::SatUFract: case BuiltinType::UFract: fbits = BUILTIN_UFRACT_FBIT; break; + case BuiltinType::SatULongFract: case BuiltinType::ULongFract: fbits = BUILTIN_ULFRACT_FBIT; break; } llvm::Value *amt = llvm::ConstantInt::get(value->getType(), 1ULL << fbits, Index: test/Frontend/fixed_point_all_builtin_operations.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point_all_builtin_operations.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -Werror %s + +// Check that we can use all supported binary and unary operations according to +// clause 4.1.6 in N1169. + +#define ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \ + TYPE unary_add ## ID (TYPE a) { return +a; } \ + TYPE unary_sub ## ID (TYPE a) { return -a; } \ + int logical_not ## ID (TYPE a) { return !a; } \ + TYPE add ## ID (TYPE a, TYPE b) { return a + b; } \ + TYPE sub ## ID (TYPE a, TYPE b) { return a - b; } \ + TYPE mul ## ID (TYPE a, TYPE b) { return a * b; } \ + TYPE div ## ID (TYPE a, TYPE b) { return a / b; } \ + TYPE shl ## ID (TYPE a, int b) { return a << b; } \ + TYPE shr ## ID (TYPE a, int b) { return a >> b; } \ + TYPE augmented_add ## ID (TYPE a, TYPE b) { a += b; return a; } \ + TYPE augmented_sub ## ID (TYPE a, TYPE b) { a -= b; return a; } \ + TYPE augmented_mul ## ID (TYPE a, TYPE b) { a *= b; return a; } \ + TYPE augmented_div ## ID (TYPE a, TYPE b) { a /= b; return a; } \ + TYPE augmented_shl ## ID (TYPE a, int b) { a <<= b; return a; } \ + TYPE augmented_shr ## ID (TYPE a, int b) { a >>= b; return a; } \ + int eq ## ID (TYPE a, TYPE b) { return a == b; } \ + int ne ## ID (TYPE a, TYPE b) { return a != b; } \ + int lt ## ID (TYPE a, TYPE b) { return a < b; } \ + int le ## ID (TYPE a, TYPE b) { return a <= b; } \ + int ge ## ID (TYPE a, TYPE b) { return a >= b; } \ + int gt ## ID (TYPE a, TYPE b) { return a > b; } \ + TYPE pre_inc ## ID (TYPE a) { return ++a; } \ + TYPE pre_dec ## ID (TYPE a) { return --a; } \ + TYPE post_inc ## ID (TYPE a) { return a++; } \ + TYPE post_dec ## ID (TYPE a) { return a--; } \ + TYPE deref_pre_inc ## ID (TYPE *a) { return ++(*a); } \ + TYPE deref_pre_dec ## ID (TYPE *a) { return --(*a); } \ + TYPE deref_post_inc ## ID (TYPE *a) { return (*a)++; } \ + TYPE deref_post_dec ## ID (TYPE *a) { return (*a)--; } + +#define ALL_OPERATIONS(TYPE, ID) \ + ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \ + ALL_OPERATIONS_FOR_TYPE(signed TYPE, Signed ## ID) \ + ALL_OPERATIONS_FOR_TYPE(unsigned TYPE, Unsigned ## ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat TYPE, Sat ## ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat signed TYPE, SatSigned ## ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned ## ID) + +ALL_OPERATIONS(short _Fract, ShortFract); +ALL_OPERATIONS(_Fract, Fract); +ALL_OPERATIONS(long _Fract, LongFract); +ALL_OPERATIONS(short _Accum, ShortAccum); +ALL_OPERATIONS(_Accum, Accum); +ALL_OPERATIONS(long _Accum, LongAccum);