]> granicus.if.org Git - clang/commitdiff
This diff includes changes for supporting the following types.
authorLeonard Chan <leonardchan@google.com>
Mon, 4 Jun 2018 16:07:52 +0000 (16:07 +0000)
committerLeonard Chan <leonardchan@google.com>
Mon, 4 Jun 2018 16:07:52 +0000 (16:07 +0000)
// Primary fixed point types
signed short _Accum s_short_accum;
signed _Accum s_accum;
signed long _Accum s_long_accum;
unsigned short _Accum u_short_accum;
unsigned _Accum u_accum;
unsigned long _Accum u_long_accum;

// Aliased fixed point types
short _Accum short_accum;
_Accum accum;
long _Accum long_accum;
This diff only allows for declaration of the fixed point types. Assignment and other operations done on fixed point types according to http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf will be added in future patches. The saturated versions of these types and the equivalent _Fract types will also be added in future patches.

The tests included are for asserting that we can declare these types.

Fixed the test that was failing by not checking for dso_local on some
targets.

Differential Revision: https://reviews.llvm.org/D46084

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333923 91177308-0d34-0410-b5e6-96231b3b80d8

38 files changed:
include/clang-c/Index.h
include/clang/AST/ASTContext.h
include/clang/AST/BuiltinTypes.def
include/clang/Basic/DiagnosticCommonKinds.td
include/clang/Basic/LangOptions.def
include/clang/Basic/Specifiers.h
include/clang/Basic/TargetInfo.h
include/clang/Basic/TokenKinds.def
include/clang/Driver/Options.td
include/clang/Sema/DeclSpec.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MicrosoftMangle.cpp
lib/AST/NSAPI.cpp
lib/AST/Type.cpp
lib/AST/TypeLoc.cpp
lib/Analysis/PrintfFormatString.cpp
lib/Basic/TargetInfo.cpp
lib/CodeGen/CGDebugInfo.cpp
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/ItaniumCXXABI.cpp
lib/Driver/ToolChains/Clang.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Index/USRGeneration.cpp
lib/Parse/ParseDecl.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaTemplateVariadic.cpp
lib/Sema/SemaType.cpp
lib/Serialization/ASTCommon.cpp
lib/Serialization/ASTReader.cpp
test/Frontend/fixed_point.c [new file with mode: 0644]
test/Frontend/fixed_point_bit_widths.c [new file with mode: 0644]
test/Frontend/fixed_point_errors.c [new file with mode: 0644]
test/Frontend/fixed_point_errors.cpp [new file with mode: 0644]
test/Frontend/fixed_point_not_enabled.c [new file with mode: 0644]
tools/libclang/CXType.cpp

index ff14d6e729a5209d672164f69fd1a95a46a4b5cd..0973783a452d8bdc34168f57803c07f48f8f4732 100644 (file)
@@ -3182,8 +3182,14 @@ enum CXTypeKind {
   CXType_Float128 = 30,
   CXType_Half = 31,
   CXType_Float16 = 32,
+  CXType_ShortAccum = 33,
+  CXType_Accum = 34,
+  CXType_LongAccum = 35,
+  CXType_UShortAccum = 36,
+  CXType_UAccum = 37,
+  CXType_ULongAccum = 38,
   CXType_FirstBuiltin = CXType_Void,
-  CXType_LastBuiltin  = CXType_Float16,
+  CXType_LastBuiltin = CXType_ULongAccum,
 
   CXType_Complex = 100,
   CXType_Pointer = 101,
index d70e455a5a8e801e78c69740fbf544819bf869a0..64160ebbace730f59affc5effe77e328a43514bc 100644 (file)
@@ -1007,6 +1007,9 @@ public:
   CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
   CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
   CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
+  CanQualType ShortAccumTy, AccumTy,
+      LongAccumTy;  // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+  CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy;
   CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
   CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
index 4d4ed79220846500c09230c0a1dacf81cef0b653..b2fa49828ab2ded82b691c58c2f75ef224564acf 100644 (file)
@@ -122,6 +122,26 @@ SIGNED_TYPE(LongLong, LongLongTy)
 // '__int128_t'
 SIGNED_TYPE(Int128, Int128Ty)
 
+//===- Fixed point types --------------------------------------------------===//
+
+// 'short _Accum'
+SIGNED_TYPE(ShortAccum, ShortAccumTy)
+
+// '_Accum'
+SIGNED_TYPE(Accum, AccumTy)
+
+// 'long _Accum'
+SIGNED_TYPE(LongAccum, LongAccumTy)
+
+// 'unsigned short _Accum'
+UNSIGNED_TYPE(UShortAccum, UnsignedShortAccumTy)
+
+// 'unsigned _Accum'
+UNSIGNED_TYPE(UAccum, UnsignedAccumTy)
+
+// 'unsigned long _Accum'
+UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy)
+
 //===- Floating point types -----------------------------------------------===//
 
 // 'half' in OpenCL, '__fp16' in ARM NEON.
index 56c735a4b64763c521cd4986250b277032219f92..93f262361c81ca4f73bb0549ce38edce1fa28c2c 100644 (file)
@@ -168,6 +168,8 @@ def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">,
                           InGroup<GccCompat>;
 def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">,
                             InGroup<GccCompat>;
+def err_fixed_point_not_enabled : Error<"compile with "
+  "'-ffixed-point' to enable fixed point types">;
 
 // SEH
 def err_seh_expected_handler : Error<
index 8605286f28c8bf2caff3ee48eb890972120b7366..6bd8958e36db41bf4b5c5359cce814f884cb047c 100644 (file)
@@ -302,6 +302,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest,
 
 COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions")
 
+LANGOPT(FixedPoint, 1, 0, "fixed point types")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT
index ee57fc47fdc516ecfd2d20ee07e967e1c56ead10..231b92ab79bb72b494c2ec6adf32e102cdd04bbf 100644 (file)
@@ -54,6 +54,7 @@ namespace clang {
     TST_int128,
     TST_half,         // OpenCL half, ARM NEON __fp16
     TST_Float16,      // C11 extension ISO/IEC TS 18661-3
+    TST_Accum,        // ISO/IEC JTC1 SC22 WG14 N1169 Extension
     TST_float,
     TST_double,
     TST_float128,
index b8e45e64d5156cdf8157fb148875cdd6c99c4a35..08e33f58f55999874404ce5d9cc2222dadddea48 100644 (file)
@@ -74,6 +74,9 @@ protected:
   unsigned char LargeArrayMinWidth, LargeArrayAlign;
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
+  unsigned char ShortAccumWidth, ShortAccumAlign;
+  unsigned char AccumWidth, AccumAlign;
+  unsigned char LongAccumWidth, LongAccumAlign;
   unsigned char SuitableAlign;
   unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
@@ -358,6 +361,21 @@ public:
   unsigned getLongLongWidth() const { return LongLongWidth; }
   unsigned getLongLongAlign() const { return LongLongAlign; }
 
+  /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
+  /// 'unsigned short _Accum' for this target, in bits.
+  unsigned getShortAccumWidth() const { return ShortAccumWidth; }
+  unsigned getShortAccumAlign() const { return ShortAccumAlign; }
+
+  /// getAccumWidth/Align - Return the size of 'signed _Accum' and
+  /// 'unsigned _Accum' for this target, in bits.
+  unsigned getAccumWidth() const { return AccumWidth; }
+  unsigned getAccumAlign() const { return AccumAlign; }
+
+  /// getLongAccumWidth/Align - Return the size of 'signed long _Accum' and
+  /// 'unsigned long _Accum' for this target, in bits.
+  unsigned getLongAccumWidth() const { return LongAccumWidth; }
+  unsigned getLongAccumAlign() const { return LongAccumAlign; }
+
   /// Determine whether the __int128 type is supported on this target.
   virtual bool hasInt128Type() const {
     return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
index cc717f61280d199307bcd95e21443fda8f7fb7f1..867b8abfeaa378d1be677f5c7121a7505b2ef100 100644 (file)
@@ -389,6 +389,9 @@ KEYWORD(char8_t                     , CHAR8SUPPORT)
 // C11 Extension
 KEYWORD(_Float16                    , KEYALL)
 
+// ISO/IEC JTC1 SC22 WG14 N1169 Extension
+KEYWORD(_Accum                      , KEYNOCXX)
+
 // GNU Extensions (in impl-reserved namespace)
 KEYWORD(_Decimal32                  , KEYALL)
 KEYWORD(_Decimal64                  , KEYALL)
index 94a5310fba9762fa1bd71de457e9b55482fc01aa..093706f2790bad7ae8e2ecbd2dc2365eb41de3b7 100644 (file)
@@ -887,6 +887,11 @@ def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">,
   Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Disable support for int128_t type">;
 
+def ffixed_point : Flag<["-"], "ffixed-point">, Group<f_Group>,
+                   Flags<[CC1Option]>, HelpText<"Enable fixed point types">;
+def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>,
+                      HelpText<"Disable fixed point types">;
+
 // Begin sanitizer flags. These should all be core options exposed in all driver
 // modes.
 let Flags = [CC1Option, CoreOption] in {
index 4ae317bafd762f189813d1b803bb26722f0e2915..50881426fd7ac9fa769e7a3b235f9a96be963e62 100644 (file)
@@ -282,6 +282,7 @@ public:
   static const TST TST_float = clang::TST_float;
   static const TST TST_double = clang::TST_double;
   static const TST TST_float16 = clang::TST_Float16;
+  static const TST TST_accum = clang::TST_Accum;
   static const TST TST_float128 = clang::TST_float128;
   static const TST TST_bool = clang::TST_bool;
   static const TST TST_decimal32 = clang::TST_decimal32;
index 4ddffe1192d0971cc300d353ba205dad3dc3d75c..24bdb644decca313dc24aca4329b3e6f45f29d5c 100644 (file)
@@ -939,6 +939,24 @@ namespace serialization {
       /// The C++ 'char8_t' type.
       PREDEF_TYPE_CHAR8_ID = 45,
 
+      /// \brief The 'short _Accum' type
+      PREDEF_TYPE_SHORT_ACCUM_ID    = 46,
+
+      /// \brief The '_Accum' type
+      PREDEF_TYPE_ACCUM_ID      = 47,
+
+      /// \brief The 'long _Accum' type
+      PREDEF_TYPE_LONG_ACCUM_ID = 48,
+
+      /// \brief The 'unsigned short _Accum' type
+      PREDEF_TYPE_USHORT_ACCUM_ID   = 49,
+
+      /// \brief The 'unsigned _Accum' type
+      PREDEF_TYPE_UACCUM_ID     = 50,
+
+      /// \brief The 'unsigned long _Accum' type
+      PREDEF_TYPE_ULONG_ACCUM_ID    = 51,
+
       /// OpenCL image types with auto numeration
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
       PREDEF_TYPE_##Id##_ID,
index 2eec05c439615035f08da61274fa9d1aa2535f9b..4956710b4f50b17c270c91940734687632b0ba44 100644 (file)
@@ -1134,6 +1134,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
   // C11 extension ISO/IEC TS 18661-3
   InitBuiltinType(Float16Ty,           BuiltinType::Float16);
 
+  // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+  InitBuiltinType(ShortAccumTy,         BuiltinType::ShortAccum);
+  InitBuiltinType(AccumTy,              BuiltinType::Accum);
+  InitBuiltinType(LongAccumTy,          BuiltinType::LongAccum);
+  InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum);
+  InitBuiltinType(UnsignedAccumTy,      BuiltinType::UAccum);
+  InitBuiltinType(UnsignedLongAccumTy,  BuiltinType::ULongAccum);
+
   // GNU extension, 128-bit integers.
   InitBuiltinType(Int128Ty,            BuiltinType::Int128);
   InitBuiltinType(UnsignedInt128Ty,    BuiltinType::UInt128);
@@ -1785,6 +1793,21 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
       Width = 128;
       Align = 128; // int128_t is 128-bit aligned on all targets.
       break;
+    case BuiltinType::ShortAccum:
+    case BuiltinType::UShortAccum:
+      Width = Target->getShortAccumWidth();
+      Align = Target->getShortAccumAlign();
+      break;
+    case BuiltinType::Accum:
+    case BuiltinType::UAccum:
+      Width = Target->getAccumWidth();
+      Align = Target->getAccumAlign();
+      break;
+    case BuiltinType::LongAccum:
+    case BuiltinType::ULongAccum:
+      Width = Target->getLongAccumWidth();
+      Align = Target->getLongAccumAlign();
+      break;
     case BuiltinType::Float16:
     case BuiltinType::Half:
       Width = Target->getHalfWidth();
@@ -6222,6 +6245,12 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
     case BuiltinType::Float16:
     case BuiltinType::Float128:
     case BuiltinType::Half:
+    case BuiltinType::ShortAccum:
+    case BuiltinType::Accum:
+    case BuiltinType::LongAccum:
+    case BuiltinType::UShortAccum:
+    case BuiltinType::UAccum:
+    case BuiltinType::ULongAccum:
       // FIXME: potentially need @encodes for these!
       return ' ';
 
index 714053791537e9479aae54230eec950aa82f3168..590ebba997fad49aaf1fd0c517aa792e3d51e933 100644 (file)
@@ -7355,6 +7355,11 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
     case BuiltinType::UInt128:
       return GCCTypeClass::Integer;
 
+    case BuiltinType::UShortAccum:
+    case BuiltinType::UAccum:
+    case BuiltinType::ULongAccum:
+      return GCCTypeClass::None;
+
     case BuiltinType::NullPtr:
 
     case BuiltinType::ObjCId:
index 1a656b5719c6a730b959d9f07b73af00cde0a32f..80b91dca7f8f536fa83088922a38f9ea52c085d7 100644 (file)
@@ -2552,6 +2552,13 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   case BuiltinType::Float16:
     Out << "DF16_";
     break;
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
+    llvm_unreachable("Fixed point types are disabled for c++");
   case BuiltinType::Half:
     Out << "Dh";
     break;
index f7b80d5b277d7d0c3b3d7a5e912866e8ed8de5ef..e9474791961de8262e73149c968ffde7f6560de3 100644 (file)
@@ -1926,6 +1926,12 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
     mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"});
     break;
 
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
   case BuiltinType::Char8:
   case BuiltinType::Float128: {
     DiagnosticsEngine &Diags = Context.getDiags();
index 030f2a0c9c7264f1fc4ea029e38969f1667fbd1f..d61638e54a1f33676b713866a46630ec57199fb4 100644 (file)
@@ -441,6 +441,12 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
   case BuiltinType::Char32:
   case BuiltinType::Int128:
   case BuiltinType::LongDouble:
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
   case BuiltinType::UInt128:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
index 065a77aa507d67c5d32343c934d157e54751f7cc..6615ea88b66d2b0f97c0c5157a87caffbdb35e98 100644 (file)
@@ -2656,6 +2656,18 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
     return "double";
   case LongDouble:
     return "long double";
+  case ShortAccum:
+    return "short _Accum";
+  case Accum:
+    return "_Accum";
+  case LongAccum:
+    return "long _Accum";
+  case UShortAccum:
+    return "unsigned short _Accum";
+  case UAccum:
+    return "unsigned _Accum";
+  case ULongAccum:
+    return "unsigned long _Accum";
   case Float16:
     return "_Float16";
   case Float128:
index dc325427b94458c6e5fe6c944c5a46b08e7dfd2d..1aa7b5a3cdcf0656309707135a7b07f13f2c8ebb 100644 (file)
@@ -344,6 +344,12 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
   case BuiltinType::LongDouble:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
     llvm_unreachable("Builtin type needs extra local data!");
     // Fall through, if the impossible happens.
       
index 2043970ccd484253f80eefc91c003652f3bb91d2..5884d33136f0453b506def426255b569286fa46d 100644 (file)
@@ -655,6 +655,12 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
   case BuiltinType::Half:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
     // Various types which are non-trivial to correct.
     return false;
 
index bacd85bc55e6b8a6bfdd8af803db86430374912c..bf36effbe3b5ae086b8ce046e6a1f6c198f00a0e 100644 (file)
@@ -40,6 +40,9 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   IntWidth = IntAlign = 32;
   LongWidth = LongAlign = 32;
   LongLongWidth = LongLongAlign = 64;
+  ShortAccumWidth = ShortAccumAlign = 16;
+  AccumWidth = AccumAlign = 32;
+  LongAccumWidth = LongAccumAlign = 64;
   SuitableAlign = 64;
   DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
index 9e99a646b0bff2ca89580f77b923e8dcef20c23b..db6a82b415dcdd2a8fc69a711e4ca6f4885fe50e 100644 (file)
@@ -702,6 +702,16 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
     // floating point types of the same size.
     Encoding = llvm::dwarf::DW_ATE_float;
     break;
+  case BuiltinType::ShortAccum:
+  case BuiltinType::Accum:
+  case BuiltinType::LongAccum:
+    Encoding = llvm::dwarf::DW_ATE_signed_fixed;
+    break;
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
+    Encoding = llvm::dwarf::DW_ATE_unsigned_fixed;
+    break;
   }
 
   switch (BT->getKind()) {
index ce1fdf9b125080a591773392a78117253f0efa4b..c1ff9d28463266b086ecf5716c51b2a68683faf0 100644 (file)
@@ -440,6 +440,12 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
     case BuiltinType::Char8:
     case BuiltinType::Char16:
     case BuiltinType::Char32:
+    case BuiltinType::ShortAccum:
+    case BuiltinType::Accum:
+    case BuiltinType::LongAccum:
+    case BuiltinType::UShortAccum:
+    case BuiltinType::UAccum:
+    case BuiltinType::ULongAccum:
       ResultType = llvm::IntegerType::get(getLLVMContext(),
                                  static_cast<unsigned>(Context.getTypeSize(T)));
       break;
index 3e2c461d6a7946eff3f1be10bca16740abb3814c..d84a10c6ba23c96af6f4e39ba45432a3acd21ea0 100644 (file)
@@ -2724,6 +2724,12 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
     case BuiltinType::OCLClkEvent:
     case BuiltinType::OCLQueue:
     case BuiltinType::OCLReserveID:
+    case BuiltinType::ShortAccum:
+    case BuiltinType::Accum:
+    case BuiltinType::LongAccum:
+    case BuiltinType::UShortAccum:
+    case BuiltinType::UAccum:
+    case BuiltinType::ULongAccum:
       return false;
 
     case BuiltinType::Dependent:
index 2347cfebf0b768edc5b96f65c9ff7c200986a9c8..afcf45d9f8a2352abab039ec586670fec492a03f 100644 (file)
@@ -3756,6 +3756,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
   Args.AddLastArg(CmdArgs, options::OPT_w);
 
+  // Fixed point flags
+  if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point,
+                   /*Default=*/false))
+    Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
+
   // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
   // (-ansi is equivalent to -std=c89 or -std=c++98).
   //
index b5396dd758f2716f634633ffb912861b26750a7a..46f8c9f235fcdfecac51ecccc39d9a119301ee38 100644 (file)
@@ -2333,6 +2333,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
   Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
 
+  // -ffixed-point
+  Opts.FixedPoint =
+      Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) &&
+      !Opts.CPlusPlus;
+
   // Handle exception personalities
   Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
                            options::OPT_fseh_exceptions,
index ba536c748c3871dc2bd28dc3962f423297e90a0e..9c9600188f74dd130ec2fc2b4aa8408a0951e711 100644 (file)
@@ -709,6 +709,12 @@ void USRGenerator::VisitType(QualType T) {
         case BuiltinType::OCLQueue:
         case BuiltinType::OCLReserveID:
         case BuiltinType::OCLSampler:
+        case BuiltinType::ShortAccum:
+        case BuiltinType::Accum:
+        case BuiltinType::LongAccum:
+        case BuiltinType::UShortAccum:
+        case BuiltinType::UAccum:
+        case BuiltinType::ULongAccum:
           IgnoreResults = true;
           return;
         case BuiltinType::ObjCId:
index 456214f0668fdd79f1f310f4179017d8f062fb2a..2b9c4afaaf10a75bb772eb76c8c9aba5e479e6d6 100644 (file)
@@ -3580,6 +3580,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
                                      DiagID, Policy);
       break;
+    case tok::kw__Accum:
+      if (!getLangOpts().FixedPoint) {
+        DiagID = diag::err_fixed_point_not_enabled;
+        PrevSpec = "";  // Not used by diagnostic
+        isInvalid = true;
+      } else {
+        isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec,
+                                       DiagID, Policy);
+      }
+      break;
     case tok::kw___float128:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
                                      DiagID, Policy);
@@ -4606,6 +4616,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
+  case tok::kw__Accum:
   case tok::kw__Float16:
   case tok::kw___float128:
   case tok::kw_bool:
@@ -4683,6 +4694,7 @@ bool Parser::isTypeSpecifierQualifier() {
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
+  case tok::kw__Accum:
   case tok::kw__Float16:
   case tok::kw___float128:
   case tok::kw_bool:
@@ -4841,6 +4853,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
+  case tok::kw__Accum:
   case tok::kw__Float16:
   case tok::kw___float128:
   case tok::kw_bool:
index dd2476ec371f61609fd1bd2642ce8a28f3c60733..aa5f197b54104041e78e402b0c0c1a1ef190294f 100644 (file)
@@ -339,6 +339,7 @@ bool Declarator::isDeclarationOfFunction() const {
     case TST_decimal32:
     case TST_decimal64:
     case TST_double:
+    case TST_Accum:
     case TST_Float16:
     case TST_float128:
     case TST_enum:
@@ -510,6 +511,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
   case DeclSpec::TST_half:        return "half";
   case DeclSpec::TST_float:       return "float";
   case DeclSpec::TST_double:      return "double";
+  case DeclSpec::TST_accum:       return "_Accum";
   case DeclSpec::TST_float16:     return "_Float16";
   case DeclSpec::TST_float128:    return "__float128";
   case DeclSpec::TST_bool:        return Policy.Bool ? "bool" : "_Bool";
@@ -1100,12 +1102,13 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
     }
   }
 
-  // signed/unsigned are only valid with int/char/wchar_t.
+  // signed/unsigned are only valid with int/char/wchar_t/_Accum.
   if (TypeSpecSign != TSS_unspecified) {
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
-    else if (TypeSpecType != TST_int  && TypeSpecType != TST_int128 &&
-             TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+    else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
+             TypeSpecType != TST_char && TypeSpecType != TST_wchar &&
+             TypeSpecType != TST_accum) {
       S.Diag(TSSLoc, diag::err_invalid_sign_spec)
         << getSpecifierName((TST)TypeSpecType, Policy);
       // signed double -> double.
@@ -1120,7 +1123,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
   case TSW_longlong: // long long int
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int; // short -> short int, long long -> long long int.
-    else if (TypeSpecType != TST_int) {
+    else if (!(TypeSpecType == TST_int ||
+               (TypeSpecType == TST_accum && TypeSpecWidth != TSW_longlong))) {
       S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
           << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
       TypeSpecType = TST_int;
@@ -1130,7 +1134,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
   case TSW_long:  // long double, long int
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int;  // long -> long int.
-    else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+    else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
+             TypeSpecType != TST_accum) {
       S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
           << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
       TypeSpecType = TST_int;
index c58e648bb3bdefa0c4df500fbe17ec5376438c2f..dc67c8ef19aaa2009dab4f1203d5103d9a17dfcb 100644 (file)
@@ -830,6 +830,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
   case TST_half:
   case TST_float:
   case TST_double:
+  case TST_Accum:
   case TST_Float16:
   case TST_float128:
   case TST_bool:
index 6839dd7de21d5aefc817a675bea1bf3974fe0d70..ac85e016ba0ebc03e148ccccf337dca7beaed453 100644 (file)
@@ -1391,6 +1391,39 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
     }
     break;
   }
+  case DeclSpec::TST_accum: {
+    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+      switch (DS.getTypeSpecWidth()) {
+        case DeclSpec::TSW_short:
+          Result = Context.ShortAccumTy;
+          break;
+        case DeclSpec::TSW_unspecified:
+          Result = Context.AccumTy;
+          break;
+        case DeclSpec::TSW_long:
+          Result = Context.LongAccumTy;
+          break;
+        case DeclSpec::TSW_longlong:
+          // Unreachable b/c this is caught in final analysis of the DeclSpec.
+          llvm_unreachable("Unable to specify long long as _Accum width");
+      }
+    } else {
+      switch (DS.getTypeSpecWidth()) {
+        case DeclSpec::TSW_short:
+          Result = Context.UnsignedShortAccumTy;
+          break;
+        case DeclSpec::TSW_unspecified:
+          Result = Context.UnsignedAccumTy;
+          break;
+        case DeclSpec::TSW_long:
+          Result = Context.UnsignedLongAccumTy;
+          break;
+        case DeclSpec::TSW_longlong:
+          llvm_unreachable("Unable to specify long long as _Accum width");
+      }
+    }
+    break;
+  }
   case DeclSpec::TST_int128:
     if (!S.Context.getTargetInfo().hasInt128Type())
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
index 54cea92042ae048a9fb2b59ac8ec69ad8c40be93..f5584cc04d16ded86698d7b503496d78505253b3 100644 (file)
@@ -91,6 +91,24 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
   case BuiltinType::LongDouble:
     ID = PREDEF_TYPE_LONGDOUBLE_ID;
     break;
+  case BuiltinType::ShortAccum:
+    ID = PREDEF_TYPE_SHORT_ACCUM_ID;
+    break;
+  case BuiltinType::Accum:
+    ID = PREDEF_TYPE_ACCUM_ID;
+    break;
+  case BuiltinType::LongAccum:
+    ID = PREDEF_TYPE_LONG_ACCUM_ID;
+    break;
+  case BuiltinType::UShortAccum:
+    ID = PREDEF_TYPE_USHORT_ACCUM_ID;
+    break;
+  case BuiltinType::UAccum:
+    ID = PREDEF_TYPE_UACCUM_ID;
+    break;
+  case BuiltinType::ULongAccum:
+    ID = PREDEF_TYPE_ULONG_ACCUM_ID;
+    break;
   case BuiltinType::Float16:
     ID = PREDEF_TYPE_FLOAT16_ID;
     break;
index 391e350445933c8d422630e9c509f1a88ccc2ae0..4dd79720270219cc58245973a794919a3977ea95 100644 (file)
@@ -6819,6 +6819,24 @@ QualType ASTReader::GetType(TypeID ID) {
     case PREDEF_TYPE_LONGDOUBLE_ID:
       T = Context.LongDoubleTy;
       break;
+    case PREDEF_TYPE_SHORT_ACCUM_ID:
+      T = Context.ShortAccumTy;
+      break;
+    case PREDEF_TYPE_ACCUM_ID:
+      T = Context.AccumTy;
+      break;
+    case PREDEF_TYPE_LONG_ACCUM_ID:
+      T = Context.LongAccumTy;
+      break;
+    case PREDEF_TYPE_USHORT_ACCUM_ID:
+      T = Context.UnsignedShortAccumTy;
+      break;
+    case PREDEF_TYPE_UACCUM_ID:
+      T = Context.UnsignedAccumTy;
+      break;
+    case PREDEF_TYPE_ULONG_ACCUM_ID:
+      T = Context.UnsignedLongAccumTy;
+      break;
     case PREDEF_TYPE_FLOAT16_ID:
       T = Context.Float16Ty;
       break;
diff --git a/test/Frontend/fixed_point.c b/test/Frontend/fixed_point.c
new file mode 100644 (file)
index 0000000..d64bd55
--- /dev/null
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -x c -ffixed-point -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:      |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} long_accum 'long _Accum'
+
+#define MIX_TYPE_SPEC(SPEC, SIGN, SIZE, ID) \
+  SPEC SIGN SIZE _Accum ID; \
+  SIGN SPEC SIZE _Accum ID ## 2; \
+  SIGN SIZE SPEC _Accum ID ## 3; \
+  SIGN SIZE _Accum SPEC ID ## 4;
+
+/* Mixing fixed point types with other type specifiers */
+
+#define MIX_VOLATILE(SIGN, SIZE, ID) MIX_TYPE_SPEC(volatile, SIGN, SIZE, ID)
+#define MIX_ATOMIC(SIGN, SIZE, ID) MIX_TYPE_SPEC(_Atomic, SIGN, SIZE, ID)
+#define MIX_CONST(SIGN, SIZE, ID) MIX_TYPE_SPEC(const, SIGN, SIZE, ID)
+
+MIX_VOLATILE(signed, short, vol_s_short_accum)
+MIX_ATOMIC(signed, short, atm_s_short_accum)
+MIX_CONST(signed, short, const_s_short_accum)
+
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum2 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum3 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum4 'volatile short _Accum'
+
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum2 '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum3 '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum4 '_Atomic(short _Accum)'
+
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum 'const short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum2 'const short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum3 'const short _Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} const_s_short_accum4 'const short _Accum'
diff --git a/test/Frontend/fixed_point_bit_widths.c b/test/Frontend/fixed_point_bit_widths.c
new file mode 100644 (file)
index 0000000..6b4eea9
--- /dev/null
@@ -0,0 +1,46 @@
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-ubuntu-fast %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=ppc64 %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-windows10pro-fast %s | FileCheck %s
+
+int size_SsA = sizeof(signed short _Accum);
+int size_SA  = sizeof(signed _Accum);
+int size_SlA = sizeof(signed long _Accum);
+int align_SsA = __alignof(signed short _Accum);
+int align_SA  = __alignof(signed _Accum);
+int align_SlA = __alignof(signed long _Accum);
+
+int size_UsA = sizeof(unsigned short _Accum);
+int size_UA  = sizeof(unsigned _Accum);
+int size_UlA = sizeof(unsigned long _Accum);
+int align_UsA = __alignof(unsigned short _Accum);
+int align_UA  = __alignof(unsigned _Accum);
+int align_UlA = __alignof(unsigned long _Accum);
+
+int size_sA = sizeof(short _Accum);
+int size_A  = sizeof(_Accum);
+int size_lA = sizeof(long _Accum);
+int align_sA = __alignof(short _Accum);
+int align_A  = __alignof(_Accum);
+int align_lA = __alignof(long _Accum);
+
+// CHECK:      @size_SsA  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SA   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SlA  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SA  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SlA = {{.*}}global i{{[0-9]+}} 8
+
+// CHECK-NEXT: @size_UsA  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_UA   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_UlA  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_UsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_UA  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_UlA = {{.*}}global i{{[0-9]+}} 8
+
+// CHECK-NEXT: @size_sA   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_A    = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_lA   = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_sA  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_A   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_lA  = {{.*}}global i{{[0-9]+}} 8
diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c
new file mode 100644 (file)
index 0000000..0158dc6
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+/* We do not yet support long long. No recommended bit widths are given for this
+ * size. */
+
+long long _Accum longlong_accum;              // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;   // expected-error{{'long long _Accum' is invalid}}
+
+/* Although _Complex types work with floating point numbers, the extension
+ * provides no info for complex fixed point types. */
+
+_Complex signed short _Accum cmplx_s_short_accum;   // expected-error{{'_Complex _Accum' is invalid}}
+_Complex signed _Accum cmplx_s_accum;               // expected-error{{'_Complex _Accum' is invalid}}
+_Complex signed long _Accum cmplx_s_long_accum;     // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned short _Accum cmplx_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned _Accum cmplx_u_accum;             // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned long _Accum cmplx_u_long_accum;   // expected-error{{'_Complex _Accum' is invalid}}
+_Complex short _Accum cmplx_s_short_accum;          // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Accum cmplx_s_accum;                      // expected-error{{'_Complex _Accum' is invalid}}
+_Complex long _Accum cmplx_s_long_accum;            // expected-error{{'_Complex _Accum' is invalid}}
+
+/* Bad combinations */
+float _Accum f_accum;     // expected-error{{cannot combine with previous 'float' declaration specifier}}
+double _Accum d_accum;    // expected-error{{cannot combine with previous 'double' declaration specifier}}
+_Bool _Accum b_accum;     // expected-error{{cannot combine with previous '_Bool' declaration specifier}}
+char _Accum c_accum;      // expected-error{{cannot combine with previous 'char' declaration specifier}}
+int _Accum i_accum;       // expected-error{{cannot combine with previous 'int' declaration specifier}}
diff --git a/test/Frontend/fixed_point_errors.cpp b/test/Frontend/fixed_point_errors.cpp
new file mode 100644 (file)
index 0000000..aa95bb1
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -x c++ -ffixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+_Accum accum;                           // expected-error{{unknown type name '_Accum'}}
diff --git a/test/Frontend/fixed_point_not_enabled.c b/test/Frontend/fixed_point_not_enabled.c
new file mode 100644 (file)
index 0000000..e5c82f5
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;    // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed _Accum s_accum;                // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;      // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;              // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;    // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum;             // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+_Accum accum;                         // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+                                      // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;               // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
index 0b678b0a2a996d3593b1b5d9706bec2d21e0e2d1..7c0f307944a14835add4d319dddb26e5d3fe720a 100644 (file)
@@ -53,6 +53,12 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
     BTCASE(Float);
     BTCASE(Double);
     BTCASE(LongDouble);
+    BTCASE(ShortAccum);
+    BTCASE(Accum);
+    BTCASE(LongAccum);
+    BTCASE(UShortAccum);
+    BTCASE(UAccum);
+    BTCASE(ULongAccum);
     BTCASE(Float16);
     BTCASE(Float128);
     BTCASE(NullPtr);
@@ -546,6 +552,12 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
     TKIND(Float);
     TKIND(Double);
     TKIND(LongDouble);
+    TKIND(ShortAccum);
+    TKIND(Accum);
+    TKIND(LongAccum);
+    TKIND(UShortAccum);
+    TKIND(UAccum);
+    TKIND(ULongAccum);
     TKIND(Float16);
     TKIND(Float128);
     TKIND(NullPtr);