@@ -768,6 +768,59 @@ void InitializeOpenCLFeatureTestMacros(const TargetInfo &TI,
768
768
Builder.defineMacro (" __opencl_c_int64" );
769
769
}
770
770
771
+ std::string ConstructFixedPointLiteral (llvm::APFixedPoint Val,
772
+ llvm::StringRef Suffix) {
773
+ if (Val.isSigned () && Val == llvm::APFixedPoint::getMin (Val.getSemantics ())) {
774
+ // When representing the min value of a signed fixed point type in source
775
+ // code, we cannot simply write `-<lowest value>`. For example, the min
776
+ // value of a `short _Fract` cannot be written as `-1.0hr`. This is because
777
+ // the parser will read this (and really any negative numerical literal) as
778
+ // a UnaryOperator that owns a FixedPointLiteral with a positive value
779
+ // rather than just a FixedPointLiteral with a negative value. Compiling
780
+ // `-1.0hr` results in an overflow to the maximal value of that fixed point
781
+ // type. The correct way to represent a signed min value is to instead split
782
+ // it into two halves, like `(-0.5hr-0.5hr)` which is what the standard
783
+ // defines SFRACT_MIN as.
784
+ std::string Literal;
785
+ std::string HalfStr = ConstructFixedPointLiteral (Val.shr (1 ), Suffix);
786
+ Literal.push_back (' (' );
787
+ Literal += HalfStr;
788
+ Literal += HalfStr;
789
+ Literal.push_back (' )' );
790
+ return Literal;
791
+ }
792
+
793
+ std::string Str (Val.toString ());
794
+ Str += Suffix;
795
+ return Str;
796
+ }
797
+
798
+ void DefineFixedPointMacros (const TargetInfo &TI, MacroBuilder &Builder,
799
+ llvm::StringRef TypeName, llvm::StringRef Suffix,
800
+ unsigned Width, unsigned Scale, bool Signed) {
801
+ // Saturation doesn't affect the size or scale of a fixed point type, so we
802
+ // don't need it here.
803
+ llvm::FixedPointSemantics FXSema (
804
+ Width, Scale, Signed, /* IsSaturated=*/ false ,
805
+ !Signed && TI.doUnsignedFixedPointTypesHavePadding ());
806
+ llvm::SmallString<32 > MacroPrefix (" __" );
807
+ MacroPrefix += TypeName;
808
+ Builder.defineMacro (MacroPrefix + " _EPSILON__" ,
809
+ ConstructFixedPointLiteral (
810
+ llvm::APFixedPoint::getEpsilon (FXSema), Suffix));
811
+ Builder.defineMacro (MacroPrefix + " _FBIT__" , Twine (Scale));
812
+ Builder.defineMacro (
813
+ MacroPrefix + " _MAX__" ,
814
+ ConstructFixedPointLiteral (llvm::APFixedPoint::getMax (FXSema), Suffix));
815
+
816
+ // N1169 doesn't specify MIN macros for unsigned types since they're all just
817
+ // zero.
818
+ if (Signed)
819
+ Builder.defineMacro (
820
+ MacroPrefix + " _MIN__" ,
821
+ ConstructFixedPointLiteral (llvm::APFixedPoint::getMin (FXSema), Suffix));
822
+ }
823
+
771
824
static void InitializePredefinedMacros (const TargetInfo &TI,
772
825
const LangOptions &LangOpts,
773
826
const FrontendOptions &FEOpts,
@@ -1097,6 +1150,47 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
1097
1150
TI.getTypeWidth (TI.getIntMaxType ()) &&
1098
1151
" uintmax_t and intmax_t have different widths?" );
1099
1152
1153
+ if (LangOpts.FixedPoint ) {
1154
+ // Each unsigned type has the same width as their signed type.
1155
+ DefineFixedPointMacros (TI, Builder, " SFRACT" , " hr" , TI.getShortFractWidth (),
1156
+ TI.getShortFractScale (), /* Signed=*/ true );
1157
+ DefineFixedPointMacros (TI, Builder, " USFRACT" , " uhr" ,
1158
+ TI.getShortFractWidth (),
1159
+ TI.getUnsignedShortFractScale (), /* Signed=*/ false );
1160
+ DefineFixedPointMacros (TI, Builder, " FRACT" , " r" , TI.getFractWidth (),
1161
+ TI.getFractScale (), /* Signed=*/ true );
1162
+ DefineFixedPointMacros (TI, Builder, " UFRACT" , " ur" , TI.getFractWidth (),
1163
+ TI.getUnsignedFractScale (), /* Signed=*/ false );
1164
+ DefineFixedPointMacros (TI, Builder, " LFRACT" , " lr" , TI.getLongFractWidth (),
1165
+ TI.getLongFractScale (), /* Signed=*/ true );
1166
+ DefineFixedPointMacros (TI, Builder, " ULFRACT" , " ulr" ,
1167
+ TI.getLongFractWidth (),
1168
+ TI.getUnsignedLongFractScale (), /* Signed=*/ false );
1169
+ DefineFixedPointMacros (TI, Builder, " SACCUM" , " hk" , TI.getShortAccumWidth (),
1170
+ TI.getShortAccumScale (), /* Signed=*/ true );
1171
+ DefineFixedPointMacros (TI, Builder, " USACCUM" , " uhk" ,
1172
+ TI.getShortAccumWidth (),
1173
+ TI.getUnsignedShortAccumScale (), /* Signed=*/ false );
1174
+ DefineFixedPointMacros (TI, Builder, " ACCUM" , " k" , TI.getAccumWidth (),
1175
+ TI.getAccumScale (), /* Signed=*/ true );
1176
+ DefineFixedPointMacros (TI, Builder, " UACCUM" , " uk" , TI.getAccumWidth (),
1177
+ TI.getUnsignedAccumScale (), /* Signed=*/ false );
1178
+ DefineFixedPointMacros (TI, Builder, " LACCUM" , " lk" , TI.getLongAccumWidth (),
1179
+ TI.getLongAccumScale (), /* Signed=*/ true );
1180
+ DefineFixedPointMacros (TI, Builder, " ULACCUM" , " ulk" ,
1181
+ TI.getLongAccumWidth (),
1182
+ TI.getUnsignedLongAccumScale (), /* Signed=*/ false );
1183
+
1184
+ Builder.defineMacro (" __SACCUM_IBIT__" , Twine (TI.getShortAccumIBits ()));
1185
+ Builder.defineMacro (" __USACCUM_IBIT__" ,
1186
+ Twine (TI.getUnsignedShortAccumIBits ()));
1187
+ Builder.defineMacro (" __ACCUM_IBIT__" , Twine (TI.getAccumIBits ()));
1188
+ Builder.defineMacro (" __UACCUM_IBIT__" , Twine (TI.getUnsignedAccumIBits ()));
1189
+ Builder.defineMacro (" __LACCUM_IBIT__" , Twine (TI.getLongAccumIBits ()));
1190
+ Builder.defineMacro (" __ULACCUM_IBIT__" ,
1191
+ Twine (TI.getUnsignedLongAccumIBits ()));
1192
+ }
1193
+
1100
1194
if (TI.hasFloat16Type ())
1101
1195
DefineFloatMacros (Builder, " FLT16" , &TI.getHalfFormat (), " F16" );
1102
1196
DefineFloatMacros (Builder, " FLT" , &TI.getFloatFormat (), " F" );
0 commit comments