diff --git a/ChangeLog.md b/ChangeLog.md index 1b0f2a91..40a4fad4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,10 @@ # Changelog +## 0.10.0 + +- Support for half-precision floating point `__fp16`, `_Float16`, and `_Float16x`. +- Support for bfloat16 `__bf16`. + ## 0.9.4 - Support `happy-2.1`. diff --git a/language-c.cabal b/language-c.cabal index 8c92621e..ee0b9e6f 100644 --- a/language-c.cabal +++ b/language-c.cabal @@ -1,6 +1,6 @@ cabal-version: 2.2 name: language-c -version: 0.9.4 +version: 0.10.0 license: BSD-3-Clause license-file: LICENSE copyright: LICENSE diff --git a/scripts/tokenlist.txt b/scripts/tokenlist.txt index a56e7a09..38e292e7 100644 --- a/scripts/tokenlist.txt +++ b/scripts/tokenlist.txt @@ -29,6 +29,10 @@ void, volatile @__, while, label __label__ +BFloat16 __bf16 +(CTokFloatN 16 False) __fp16 +(CTokFloatN 16 False) _Float16 +(CTokFloatN 16 True) _Float16x (CTokFloatN 32 False) _Float32 (CTokFloatN 32 True) _Float32x (CTokFloatN 64 False) _Float64 diff --git a/src/Language/C/Analysis/DeclAnalysis.hs b/src/Language/C/Analysis/DeclAnalysis.hs index 6e586cbb..3f82fd82 100644 --- a/src/Language/C/Analysis/DeclAnalysis.hs +++ b/src/Language/C/Analysis/DeclAnalysis.hs @@ -395,6 +395,7 @@ tNumType (NumTypeSpec basetype sgn sz iscomplex) = (BaseFloat, NoSignSpec, NoSizeMod) -> floatType TyFloat (BaseDouble, NoSignSpec, NoSizeMod) -> floatType TyDouble (BaseDouble, NoSignSpec, LongMod) -> floatType TyLDouble + (BaseBFloat16, NoSignSpec, NoSizeMod) -> floatType TyBFloat16 (BaseFloatN n x, NoSignSpec, NoSizeMod) -> floatType (TyFloatN n x) -- TODO: error analysis (_,_,_) -> error "Bad AST analysis" @@ -431,7 +432,7 @@ tTypeQuals = foldrM go (noTypeQuals,[]) where To canoicalize type specifiers, we define a canonical form: void | bool | (char|int|int128|float|double|floatNx)? (signed|unsigned)? (long long?)? complex? | othertype -} -data NumBaseType = NoBaseType | BaseChar | BaseInt | BaseInt128 | BaseFloat | +data NumBaseType = NoBaseType | BaseChar | BaseInt | BaseInt128 | BaseFloat | BaseBFloat16 | BaseFloatN Int Bool | BaseDouble deriving (Eq,Ord) data SignSpec = NoSignSpec | Signed | Unsigned deriving (Eq,Ord) data SizeMod = NoSizeMod | ShortMod | LongMod | LongLongMod deriving (Eq,Ord) @@ -461,6 +462,8 @@ canonicalTypeSpec = foldrM go TSNone where = return$ TSNum$ nts { base = BaseInt128 } go (CFloatType _) tsa | (Just nts@(NumTypeSpec { base = NoBaseType })) <- getNTS tsa = return$ TSNum$ nts { base = BaseFloat } + go (CBFloat16Type _) tsa | (Just nts@(NumTypeSpec { base = NoBaseType })) <- getNTS tsa + = return$ TSNum$ nts { base = BaseBFloat16 } go (CFloatNType n x _) tsa | (Just nts@(NumTypeSpec { base = NoBaseType })) <- getNTS tsa = return$ TSNum$ nts { base = BaseFloatN n x } go (CDoubleType _) tsa | (Just nts@(NumTypeSpec { base = NoBaseType })) <- getNTS tsa diff --git a/src/Language/C/Analysis/Export.hs b/src/Language/C/Analysis/Export.hs index 3ecb8d63..acae43d7 100644 --- a/src/Language/C/Analysis/Export.hs +++ b/src/Language/C/Analysis/Export.hs @@ -177,6 +177,7 @@ exportFloatType ty = TyFloat -> [CFloatType ni] TyDouble -> [CDoubleType ni] TyLDouble -> [CLongType ni, CDoubleType ni] + TyBFloat16 -> [CBFloat16Type ni] TyFloatN n x -> [CFloatNType n x ni] exportComplexType :: FloatType -> [CTypeSpec] diff --git a/src/Language/C/Analysis/MachineDescs.hs b/src/Language/C/Analysis/MachineDescs.hs index 85b83873..80927479 100644 --- a/src/Language/C/Analysis/MachineDescs.hs +++ b/src/Language/C/Analysis/MachineDescs.hs @@ -27,6 +27,7 @@ x86_64 = TyFloat -> 4 TyDouble -> 8 TyLDouble -> 16 + TyBFloat16 -> error "TyBFloat16" TyFloatN{} -> error "TyFloatN" builtinSize = \case TyVaList -> 24 @@ -52,6 +53,7 @@ x86_64 = TyFloat -> 4 TyDouble -> 8 TyLDouble -> 16 + TyBFloat16{} -> error "TyBFloat16" TyFloatN{} -> error "TyFloatN" builtinAlign = \case TyVaList -> 8 @@ -81,6 +83,7 @@ armv7l = TyFloat -> 4 TyDouble -> 8 TyLDouble -> 8 + TyBFloat16 -> 2 TyFloatN{} -> error "TyFloatN" builtinSize = \case TyVaList -> 4 @@ -106,6 +109,7 @@ armv7l = TyFloat -> 4 TyDouble -> 8 TyLDouble -> 8 + TyBFloat16 -> 2 TyFloatN{} -> error "TyFloatN" builtinAlign = \case TyVaList -> 4 diff --git a/src/Language/C/Analysis/SemRep.hs b/src/Language/C/Analysis/SemRep.hs index 71d19739..efd5f428 100644 --- a/src/Language/C/Analysis/SemRep.hs +++ b/src/Language/C/Analysis/SemRep.hs @@ -431,6 +431,7 @@ data FloatType = TyFloat | TyDouble | TyLDouble + | TyBFloat16 | TyFloatN Int Bool deriving (Typeable, Data, Eq, Ord) @@ -438,6 +439,7 @@ instance Show FloatType where show TyFloat = "float" show TyDouble = "double" show TyLDouble = "long double" + show TyBFloat16 = "__bf16" show (TyFloatN n x) = "_Float" ++ (show n) ++ (if x then "x" else "") -- | composite type declarations diff --git a/src/Language/C/Parser/Lexer.x b/src/Language/C/Parser/Lexer.x index 4ff6cb4d..396d29ec 100644 --- a/src/Language/C/Parser/Lexer.x +++ b/src/Language/C/Parser/Lexer.x @@ -311,6 +311,10 @@ void, volatile @__, while, label __label__ +BFloat16 __bf16 +(CTokFloatN 16 False) __fp16 +(CTokFloatN 16 False) _Float16 +(CTokFloatN 16 True) _Float16x (CTokFloatN 32 False) _Float32 (CTokFloatN 32 True) _Float32x (CTokFloatN 64 False) _Float64 @@ -328,13 +332,17 @@ label __label__ (flip CTokClangC ClangBuiltinConvertVector) __builtin_convertvector -} --- Tokens: _Alignas _Alignof __alignof alignof __alignof__ __asm asm __asm__ _Atomic auto break _Bool case char __const const __const__ continue _Complex __complex__ default do double else enum extern float for _Generic goto if __inline inline __inline__ int __int128_t long _Noreturn _Nullable __nullable _Nonnull __nonnull register __restrict restrict __restrict__ return short __signed signed __signed__ sizeof static _Static_assert struct switch typedef __typeof typeof __typeof__ __thread _Thread_local __uint128 __uint128_t union unsigned void __volatile volatile __volatile__ while __label__ _Float32 _Float32x _Float64 _Float64x _Float128 __float128 _Float128x __attribute __attribute__ __extension__ __real __real__ __imag __imag__ __builtin_va_arg __builtin_offsetof __builtin_types_compatible_p __builtin_bit_cast __builtin_convertvector +-- Tokens: _Alignas _Alignof __alignof alignof __alignof__ __asm asm __asm__ _Atomic auto break _Bool case char __const const __const__ continue _Complex __complex__ default do double else enum extern float for _Generic goto if __inline inline __inline__ int __int128_t long _Noreturn _Nullable __nullable _Nonnull __nonnull register __restrict restrict __restrict__ return short __signed signed __signed__ sizeof static _Static_assert struct switch typedef __typeof typeof __typeof__ __thread _Thread_local __uint128 __uint128_t union unsigned void __volatile volatile __volatile__ while __label__ __bf16 __fp16 _Float16 _Float16x _Float32 _Float32x _Float64 _Float64x _Float128 __float128 _Float128x __attribute __attribute__ __extension__ __real __real__ __imag __imag__ __builtin_va_arg __builtin_offsetof __builtin_types_compatible_p __builtin_bit_cast __builtin_convertvector idkwtok ('_' : 'A' : 'l' : 'i' : 'g' : 'n' : 'a' : 's' : []) = tok 8 CTokAlignas idkwtok ('_' : 'A' : 'l' : 'i' : 'g' : 'n' : 'o' : 'f' : []) = tok 8 CTokAlignof idkwtok ('_' : 'A' : 't' : 'o' : 'm' : 'i' : 'c' : []) = tok 7 CTokAtomic idkwtok ('_' : 'B' : 'o' : 'o' : 'l' : []) = tok 5 CTokBool idkwtok ('_' : 'C' : 'o' : 'm' : 'p' : 'l' : 'e' : 'x' : []) = tok 8 CTokComplex +idkwtok ('_' : '_' : 'b' : 'f' : '1' : '6' : []) = tok 6 CTokBFloat16 +idkwtok ('_' : '_' : 'f' : 'p' : '1' : '6' : []) = tok 6 (CTokFloatN 16 False) #ifdef IEC_60559_TYPES_EXT +idkwtok ('_' : 'F' : 'l' : 'o' : 'a' : 't' : '1' : '6' : []) = tok 8 (CTokFloatN 16 False) +idkwtok ('_' : 'F' : 'l' : 'o' : 'a' : 't' : '1' : '6' : 'x' : []) = tok 9 (CTokFloatN 16 True) idkwtok ('_' : 'F' : 'l' : 'o' : 'a' : 't' : '1' : '2' : '8' : []) = tok 9 (CTokFloatN 128 False) idkwtok ('_' : 'F' : 'l' : 'o' : 'a' : 't' : '1' : '2' : '8' : 'x' : []) = tok 10 (CTokFloatN 128 True) idkwtok ('_' : 'F' : 'l' : 'o' : 'a' : 't' : '3' : '2' : []) = tok 8 (CTokFloatN 32 False) diff --git a/src/Language/C/Parser/Parser.y b/src/Language/C/Parser/Parser.y index 9323db82..9e3c52e2 100644 --- a/src/Language/C/Parser/Parser.y +++ b/src/Language/C/Parser/Parser.y @@ -202,6 +202,10 @@ else { CTokElse _ } enum { CTokEnum _ } extern { CTokExtern _ } float { CTokFloat _ } +"__bf16" { CTokBFloat16 _ } +"__fp16" { CTokFloatN 16 False _ } +"_Float16" { CTokFloatN 16 False _ } +"_Float16x" { CTokFloatN 16 True _ } "_Float32" { CTokFloatN 32 False _ } "_Float32x" { CTokFloatN 32 True _ } "_Float64" { CTokFloatN 64 False _ } @@ -898,6 +902,10 @@ basic_type_name | "_Complex" {% withNodeInfo $1 $ CComplexType } | "__int128" {% withNodeInfo $1 $ CInt128Type } | "__uint128" {% withNodeInfo $1 $ CUInt128Type } + | "__bf16" {% withNodeInfo $1 $ CBFloat16Type } + | "__fp16" {% withNodeInfo $1 $ (CFloatNType 16 False) } + | "_Float16" {% withNodeInfo $1 $ (CFloatNType 16 False) } + | "_Float16x" {% withNodeInfo $1 $ (CFloatNType 16 True) } | "_Float32" {% withNodeInfo $1 $ (CFloatNType 32 False) } | "_Float32x" {% withNodeInfo $1 $ (CFloatNType 32 True) } | "_Float64" {% withNodeInfo $1 $ (CFloatNType 64 False) } diff --git a/src/Language/C/Parser/Tokens.hs b/src/Language/C/Parser/Tokens.hs index 78e18f12..54c39cd6 100644 --- a/src/Language/C/Parser/Tokens.hs +++ b/src/Language/C/Parser/Tokens.hs @@ -92,7 +92,10 @@ data CToken = CTokLParen !PosLength -- `(' | CTokEnum !PosLength -- `enum' | CTokExtern !PosLength -- `extern' | CTokFloat !PosLength -- `float' - | CTokFloatN !Int !Bool !PosLength -- `__float128' or `_Float{32,64,128}{,x}` + | CTokBFloat16 !PosLength -- `__bf16' + | CTokFloatN !Int !Bool !PosLength -- (or `__float128', + -- `__fp16', + -- `_Float{16,32,64,128}{,x}`) | CTokFor !PosLength -- `for' | CTokGeneric !PosLength -- `_Generic' | CTokGoto !PosLength -- `goto' @@ -235,6 +238,7 @@ posLenOfTok (CTokElse pos ) = pos posLenOfTok (CTokEnum pos ) = pos posLenOfTok (CTokExtern pos ) = pos posLenOfTok (CTokFloat pos ) = pos +posLenOfTok (CTokBFloat16 pos ) = pos posLenOfTok (CTokFloatN _ _ pos) = pos posLenOfTok (CTokFor pos ) = pos posLenOfTok (CTokGeneric pos ) = pos @@ -348,6 +352,7 @@ instance Show CToken where showsPrec _ (CTokEnum _ ) = showString "enum" showsPrec _ (CTokExtern _ ) = showString "extern" showsPrec _ (CTokFloat _ ) = showString "float" + showsPrec _ (CTokBFloat16 _ ) = showString "__bf16" showsPrec _ (CTokFloatN n x _) = showString "_Float" . shows n . showString (if x then "x" else "") showsPrec _ (CTokFor _ ) = showString "for" diff --git a/src/Language/C/Pretty.hs b/src/Language/C/Pretty.hs index 993d389f..5ad0f1e8 100644 --- a/src/Language/C/Pretty.hs +++ b/src/Language/C/Pretty.hs @@ -248,6 +248,7 @@ instance Pretty CTypeSpec where pretty (CIntType _) = text "int" pretty (CLongType _) = text "long" pretty (CFloatType _) = text "float" + pretty (CBFloat16Type _) = text "__bf16" pretty (CFloatNType n x _) = text "_Float" <> text (show n) <> (if x then text "x" else empty) pretty (CDoubleType _) = text "double" diff --git a/src/Language/C/Syntax/AST.hs b/src/Language/C/Syntax/AST.hs index b9d9fa38..d1d31f2c 100644 --- a/src/Language/C/Syntax/AST.hs +++ b/src/Language/C/Syntax/AST.hs @@ -469,6 +469,7 @@ data CTypeSpecifier a | CComplexType a | CInt128Type a | CUInt128Type a + | CBFloat16Type a | CFloatNType Int Bool a -- ^ IEC 60227: width (32,64,128), extended flag | CSUType (CStructureUnion a) a -- ^ Struct or Union specifier | CEnumType (CEnumeration a) a -- ^ Enumeration specifier @@ -1090,6 +1091,7 @@ instance CNode t1 => CNode (CTypeSpecifier t1) where nodeInfo (CShortType d) = nodeInfo d nodeInfo (CIntType d) = nodeInfo d nodeInfo (CLongType d) = nodeInfo d + nodeInfo (CBFloat16Type d) = nodeInfo d nodeInfo (CFloatType d) = nodeInfo d nodeInfo (CFloatNType _ _ d) = nodeInfo d nodeInfo (CDoubleType d) = nodeInfo d @@ -1115,6 +1117,7 @@ instance Functor CTypeSpecifier where fmap _f (CIntType a1) = CIntType (_f a1) fmap _f (CLongType a1) = CLongType (_f a1) fmap _f (CFloatType a1) = CFloatType (_f a1) + fmap _f (CBFloat16Type a1) = CBFloat16Type (_f a1) fmap _f (CFloatNType n x a1) = CFloatNType n x (_f a1) fmap _f (CDoubleType a1) = CDoubleType (_f a1) fmap _f (CSignedType a1) = CSignedType (_f a1) @@ -1137,6 +1140,7 @@ instance Annotated CTypeSpecifier where annotation (CIntType n) = n annotation (CLongType n) = n annotation (CFloatType n) = n + annotation (CBFloat16Type n) = n annotation (CFloatNType _ _ n) = n annotation (CDoubleType n) = n annotation (CSignedType n) = n @@ -1157,6 +1161,7 @@ instance Annotated CTypeSpecifier where amap f (CIntType a_1) = CIntType (f a_1) amap f (CLongType a_1) = CLongType (f a_1) amap f (CFloatType a_1) = CFloatType (f a_1) + amap f (CBFloat16Type a_1) = CBFloat16Type (f a_1) amap f (CFloatNType n x a_1) = CFloatNType n x (f a_1) amap f (CDoubleType a_1) = CDoubleType (f a_1) amap f (CSignedType a_1) = CSignedType (f a_1) diff --git a/test/harness/arm_float16/Makefile b/test/harness/arm_float16/Makefile new file mode 100644 index 00000000..b07175b8 --- /dev/null +++ b/test/harness/arm_float16/Makefile @@ -0,0 +1,12 @@ +PP=../../../examples/ParseAndPrint +TY=../../../examples/TypeCheck +all: parse +parse: +# gcc -c -Wall test.c + $(PP) test.c > test.out + diff -u test.expect test.out + $(TY) test.c +clean: + rm -f *.out +gcc_check: + gcc -fsyntax-only -c test.c diff --git a/test/harness/arm_float16/test.c b/test/harness/arm_float16/test.c new file mode 100644 index 00000000..86819b31 --- /dev/null +++ b/test/harness/arm_float16/test.c @@ -0,0 +1,6 @@ +/* extended floating point types */ +static void f(void) +{ + __fp16 a1 = 2.0; + __bf16 b1 = 2.0; +} diff --git a/test/harness/arm_float16/test.expect b/test/harness/arm_float16/test.expect new file mode 100644 index 00000000..048a1ba9 --- /dev/null +++ b/test/harness/arm_float16/test.expect @@ -0,0 +1,5 @@ +static void f(void) +{ + _Float16 a1 = 2.0; + __bf16 b1 = 2.0; +} diff --git a/test/harness/iec_60559/test.c b/test/harness/iec_60559/test.c index 2796d6b4..316b0802 100644 --- a/test/harness/iec_60559/test.c +++ b/test/harness/iec_60559/test.c @@ -7,6 +7,8 @@ static void f(void) _Float64x d1 = 2.0; _Float128 e1 = 2.0; __float128 g1 = 2.0 + e1; + _Float16 h1 = 2.0; + _Float16x i1 = 2.0; _Float32 a = 2.0f32; _Float32x b = 2.0if32x; @@ -18,4 +20,5 @@ static void f(void) _Float128x f = 2.0f128x; _Float128x f1 = 2.0 + d1 + e1; #endif + } diff --git a/test/harness/iec_60559/test.expect b/test/harness/iec_60559/test.expect index a386f804..116b54b0 100644 --- a/test/harness/iec_60559/test.expect +++ b/test/harness/iec_60559/test.expect @@ -6,6 +6,8 @@ static void f(void) _Float64x d1 = 2.0; _Float128 e1 = 2.0; _Float128 g1 = 2.0 + e1; + _Float16 h1 = 2.0; + _Float16x i1 = 2.0; _Float32 a = 2.0f32; _Float32x b = 2.0if32x; _Float64 c = 2.0f64;