Skip to content

Commit 689c552

Browse files
authored
Merge pull request #8169 from tautschnig/bugfixes/float-extensions
C/C++ front-end: accept all floating-point extensions that GCC and Clang support
2 parents dbffea6 + bf1159f commit 689c552

21 files changed

+165
-70
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ src/ansi-c/compiler_headers/gcc_builtin_headers_omp.inc
5252
src/ansi-c/compiler_headers/gcc_builtin_headers_power.inc
5353
src/ansi-c/compiler_headers/gcc_builtin_headers_tm.inc
5454
src/ansi-c/compiler_headers/gcc_builtin_headers_types.inc
55-
src/ansi-c/compiler_headers/gcc_builtin_headers_types_gcc7plus.inc
5655
src/ansi-c/compiler_headers/gcc_builtin_headers_ubsan.inc
5756
src/ansi-c/compiler_headers/windows_builtin_headers.inc
5857
src/cpp/cprover_library.inc

regression/ansi-c/float_constant1/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,21 @@ STATIC_ASSERT(__builtin_types_compatible_p(_Float64, __typeof(1.0f64)));
2121
STATIC_ASSERT(__builtin_types_compatible_p(_Float128, __typeof(1.0f128)));
2222
STATIC_ASSERT(__builtin_types_compatible_p(_Float32x, __typeof(1.0f32x)));
2323
STATIC_ASSERT(__builtin_types_compatible_p(_Float64x, __typeof(1.0f64x)));
24+
// f128x should be supported by GCC >= 7 (and for C++ in GCC >=13), but there
25+
// are no current GCC target architectures that actually support such types
2426
STATIC_ASSERT(__builtin_types_compatible_p(_Float128x, __typeof(1.0f128x)));
2527
#endif
2628

29+
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 13
30+
STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16)));
31+
STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.0bf16)));
32+
STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.BF16)));
33+
#endif
34+
35+
#if defined(__clang__) && __clang_major__ >= 15
36+
STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16)));
37+
#endif
38+
2739
#ifdef __GNUC__
2840
_Complex c;
2941
#endif

src/ansi-c/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ make_inc(compiler_headers/gcc_builtin_headers_omp)
7979
make_inc(compiler_headers/gcc_builtin_headers_power)
8080
make_inc(compiler_headers/gcc_builtin_headers_tm)
8181
make_inc(compiler_headers/gcc_builtin_headers_types)
82-
make_inc(compiler_headers/gcc_builtin_headers_types_gcc7plus)
8382
make_inc(compiler_headers/gcc_builtin_headers_ubsan)
8483
make_inc(compiler_headers/windows_builtin_headers)
8584
make_inc(cprover_builtin_headers)
@@ -104,7 +103,6 @@ set(extra_dependencies
104103
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_power.inc
105104
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_tm.inc
106105
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_types.inc
107-
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_types_gcc7plus.inc
108106
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_ubsan.inc
109107
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/windows_builtin_headers.inc
110108
${CMAKE_CURRENT_BINARY_DIR}/cprover_library.inc

src/ansi-c/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ BUILTIN_FILES = \
7070
compiler_headers/gcc_builtin_headers_power.inc \
7171
compiler_headers/gcc_builtin_headers_tm.inc \
7272
compiler_headers/gcc_builtin_headers_types.inc \
73-
compiler_headers/gcc_builtin_headers_types_gcc7plus.inc \
7473
compiler_headers/gcc_builtin_headers_ubsan.inc \
7574
compiler_headers/windows_builtin_headers.inc
7675

src/ansi-c/ansi_c_internal_additions.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ const char gcc_builtin_headers_types[] =
2222
#include "compiler_headers/gcc_builtin_headers_types.inc" // IWYU pragma: keep
2323
; // NOLINT(whitespace/semicolon)
2424

25-
const char gcc_builtin_headers_types_gcc7plus[] =
26-
"#line 1 \"gcc_builtin_headers_types_gcc7plus.h\"\n"
27-
// NOLINTNEXTLINE(whitespace/line_length)
28-
#include "compiler_headers/gcc_builtin_headers_types_gcc7plus.inc" // IWYU pragma: keep
29-
; // NOLINT(whitespace/semicolon)
30-
3125
const char gcc_builtin_headers_generic[] =
3226
"#line 1 \"gcc_builtin_headers_generic.h\"\n"
3327
#include "compiler_headers/gcc_builtin_headers_generic.inc" // IWYU pragma: keep
@@ -158,9 +152,7 @@ max_malloc_size(std::size_t pointer_width, std::size_t object_bits)
158152
return ((mp_integer)1) << (mp_integer)bits_for_positive_offset;
159153
}
160154

161-
void ansi_c_internal_additions(
162-
std::string &code,
163-
bool support_ts_18661_3_Floatn_types)
155+
void ansi_c_internal_additions(std::string &code, bool support_float16_type)
164156
{
165157
// clang-format off
166158
// do the built-in types and variables
@@ -249,8 +241,15 @@ void ansi_c_internal_additions(
249241
config.ansi_c.mode == configt::ansi_ct::flavourt::ARM)
250242
{
251243
code+=gcc_builtin_headers_types;
252-
if(support_ts_18661_3_Floatn_types)
253-
code += gcc_builtin_headers_types_gcc7plus;
244+
if(support_float16_type)
245+
{
246+
code +=
247+
"typedef _Float16 __gcc_v8hf __attribute__((__vector_size__(16)));\n";
248+
code +=
249+
"typedef _Float16 __gcc_v16hf __attribute__((__vector_size__(32)));\n";
250+
code +=
251+
"typedef _Float16 __gcc_v32hf __attribute__((__vector_size__(64)));\n";
252+
}
254253

255254
// there are many more, e.g., look at
256255
// https://developer.apple.com/library/mac/#documentation/developertools/gcc-4.0.1/gcc/Target-Builtins.html

src/ansi-c/ansi_c_internal_additions.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <string>
1414

15-
void ansi_c_internal_additions(
16-
std::string &code,
17-
bool support_ts_18661_3_Floatn_types);
15+
void ansi_c_internal_additions(std::string &code, bool support_float16_type);
1816
void ansi_c_architecture_strings(std::string &code);
1917

2018
extern const char clang_builtin_headers[];
2119
extern const char cprover_builtin_headers[];
2220
extern const char gcc_builtin_headers_types[];
23-
extern const char gcc_builtin_headers_types_gcc7plus[];
2421
extern const char gcc_builtin_headers_generic[];
2522
extern const char gcc_builtin_headers_math[];
2623
extern const char gcc_builtin_headers_mem_string[];

src/ansi-c/ansi_c_language.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ bool ansi_c_languaget::parse(
6868
// parsing
6969

7070
std::string code;
71-
ansi_c_internal_additions(code, config.ansi_c.ts_18661_3_Floatn_types);
71+
ansi_c_internal_additions(code, config.ansi_c.float16_type);
7272
std::istringstream codestr(code);
7373

7474
ansi_c_parser.clear();
@@ -77,6 +77,8 @@ bool ansi_c_languaget::parse(
7777
ansi_c_parser.log.set_message_handler(message_handler);
7878
ansi_c_parser.for_has_scope=config.ansi_c.for_has_scope;
7979
ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
80+
ansi_c_parser.float16_type = config.ansi_c.float16_type;
81+
ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
8082
ansi_c_parser.cpp98=false; // it's not C++
8183
ansi_c_parser.cpp11=false; // it's not C++
8284
ansi_c_parser.mode=config.ansi_c.mode;
@@ -203,6 +205,8 @@ bool ansi_c_languaget::to_expr(
203205
ansi_c_parser.log.set_message_handler(message_handler);
204206
ansi_c_parser.mode=config.ansi_c.mode;
205207
ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
208+
ansi_c_parser.float16_type = config.ansi_c.float16_type;
209+
ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
206210
ansi_c_scanner_init();
207211

208212
bool result=ansi_c_parser.parse();

src/ansi-c/ansi_c_parser.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class ansi_c_parsert:public parsert
3333
cpp98(false),
3434
cpp11(false),
3535
for_has_scope(false),
36-
ts_18661_3_Floatn_types(false)
36+
ts_18661_3_Floatn_types(false),
37+
float16_type(false),
38+
bf16_type(false)
3739
{
3840
}
3941

@@ -78,6 +80,8 @@ class ansi_c_parsert:public parsert
7880

7981
// ISO/IEC TS 18661-3:2015
8082
bool ts_18661_3_Floatn_types;
83+
bool float16_type;
84+
bool bf16_type;
8185

8286
typedef ansi_c_identifiert identifiert;
8387
typedef ansi_c_scopet scopet;

src/ansi-c/builtin_factory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static bool convert(
9797
//! \return 'true' on error
9898
bool builtin_factory(
9999
const irep_idt &identifier,
100-
bool support_ts_18661_3_Floatn_types,
100+
bool support_float16_type,
101101
symbol_table_baset &symbol_table,
102102
message_handlert &mh)
103103
{
@@ -107,7 +107,7 @@ bool builtin_factory(
107107
std::ostringstream s;
108108

109109
std::string code;
110-
ansi_c_internal_additions(code, support_ts_18661_3_Floatn_types);
110+
ansi_c_internal_additions(code, support_float16_type);
111111
s << code;
112112

113113
// our own extensions

src/ansi-c/builtin_factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class symbol_table_baset;
1717
//! \return 'true' in case of error
1818
bool builtin_factory(
1919
const irep_idt &identifier,
20-
bool support_ts_18661_3_Floatn_types,
20+
bool support_float16_type,
2121
symbol_table_baset &,
2222
message_handlert &);
2323

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2077,7 +2077,7 @@ bool c_typecheck_baset::builtin_factory(const irep_idt &identifier)
20772077
{
20782078
return ::builtin_factory(
20792079
identifier,
2080-
config.ansi_c.ts_18661_3_Floatn_types,
2080+
config.ansi_c.float16_type,
20812081
symbol_table,
20822082
get_message_handler());
20832083
}

src/ansi-c/compiler_headers/gcc_builtin_headers_types_gcc7plus.h

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/ansi-c/gcc_version.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,16 @@ void configure_gcc(const gcc_versiont &gcc_version)
162162
config.ansi_c.gcc__float128_type =
163163
gcc_version.flavor == gcc_versiont::flavort::GCC &&
164164
gcc_version.is_at_least(4u, gcc_float128_minor_version);
165+
166+
config.ansi_c.float16_type =
167+
(gcc_version.flavor == gcc_versiont::flavort::GCC &&
168+
gcc_version.is_at_least(12u)) ||
169+
(gcc_version.flavor == gcc_versiont::flavort::CLANG &&
170+
gcc_version.is_at_least(15u));
171+
172+
config.ansi_c.bf16_type =
173+
(gcc_version.flavor == gcc_versiont::flavort::GCC &&
174+
gcc_version.is_at_least(13u)) ||
175+
(gcc_version.flavor == gcc_versiont::flavort::CLANG &&
176+
gcc_version.is_at_least(15u));
165177
}

src/ansi-c/literals/parse_float.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ parse_floatt::parse_floatt(const std::string &src)
7777
p++;
7878

7979
// get exponent
80-
while(*p!=0 && *p!='f' && *p!='l' &&
81-
*p!='w' && *p!='q' && *p!='d')
80+
while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' &&
81+
*p != 'd' && *p != 'b')
8282
{
8383
str_exponent+=*p;
8484
p++;
@@ -121,10 +121,8 @@ parse_floatt::parse_floatt(const std::string &src)
121121
p++;
122122

123123
// get fraction part
124-
while(*p!=0 && *p!='e' &&
125-
*p!='f' && *p!='l' &&
126-
*p!='w' && *p!='q' && *p!='d' &&
127-
*p!='i' && *p!='j')
124+
while(*p != 0 && *p != 'e' && *p != 'f' && *p != 'l' && *p != 'w' &&
125+
*p != 'q' && *p != 'd' && *p != 'i' && *p != 'j' && *p != 'b')
128126
{
129127
str_fraction_part+=*p;
130128
p++;
@@ -139,9 +137,8 @@ parse_floatt::parse_floatt(const std::string &src)
139137
p++;
140138

141139
// get exponent
142-
while(*p!=0 && *p!='f' && *p!='l' &&
143-
*p!='w' && *p!='q' && *p!='d' &&
144-
*p!='i' && *p!='j')
140+
while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' &&
141+
*p != 'd' && *p != 'i' && *p != 'j' && *p != 'b')
145142
{
146143
str_exponent+=*p;
147144
p++;
@@ -173,7 +170,7 @@ parse_floatt::parse_floatt(const std::string &src)
173170
is_float80=false;
174171
is_float128=is_float128x=false;
175172

176-
if(strcmp(p, "f16")==0)
173+
if(strcmp(p, "f16") == 0 || strcmp(p, "bf16") == 0)
177174
is_float16=true;
178175
else if(strcmp(p, "f32")==0)
179176
is_float32=true;

src/ansi-c/scanner.l

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,13 @@ hexfloat1 "0"[xX]{hexdigit}*"."{hexdigit}+[pP][+-]?{integer}
217217
hexfloat2 "0"[xX]{hexdigit}*"."[pP][+-]?{integer}
218218
hexfloat3 "0"[xX]{hexdigit}*[pP][+-]?{integer}
219219
float_suffix [fFlLiIjJ]*
220-
gcc_ext_float_suffix [wWqQ]|[dD][fFdDlL]?|"f16"|"f32"|"f64"|"f128"|"f32x"|"f64x"|"f128x"
220+
clang_ext_float_suffix [qQ]|"f16"|"F16"
221+
gcc_ext_float_width (("bf"|"BF")"16")|([fF]("32"|"64"|"128"|"32x"|"64x"|"128x"))
222+
gcc_ext_float_suffix {clang_ext_float_suffix}|[wW]|[dD][fFdDlL]?|{gcc_ext_float_width}
221223
float {float1}|{float2}|{float3}|{hexfloat1}|{hexfloat2}|{hexfloat3}
222224
float_s {float}{float_suffix}|{integer}[fF]
223225
gcc_ext_float_s {float}{gcc_ext_float_suffix}
226+
clang_ext_float_s {float}{clang_ext_float_suffix}
224227
cppstart {ws}"#"{ws}
225228
cpplineno {cppstart}"line"*{ws}{integer}{ws}.*{newline}
226229
cppdirective {cppstart}({newline}|[^p].*|"p"[^r].*|"pr"[^a].*|"pra"[^g].*|"prag"[^m].*|"pragm"[^a].*)
@@ -524,13 +527,13 @@ void ansi_c_scanner_init()
524527
return make_identifier();
525528
}
526529

527-
"_Float16" { if(PARSER.ts_18661_3_Floatn_types)
530+
"_Float16" { if(PARSER.float16_type)
528531
{ loc(); return TOK_GCC_FLOAT16; }
529532
else
530533
return make_identifier();
531534
}
532535

533-
"__bf16" { if(PARSER.ts_18661_3_Floatn_types)
536+
"__bf16" { if(PARSER.bf16_type)
534537
{ loc(); return TOK_GCC_FLOAT16; }
535538
else
536539
return make_identifier();
@@ -1561,9 +1564,21 @@ __decltype { if(PARSER.cpp98 &&
15611564
return TOK_INTEGER;
15621565
}
15631566

1567+
{clang_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC &&
1568+
PARSER.mode != configt::ansi_ct::flavourt::CLANG)
1569+
{
1570+
yyansi_cerror("Floating-point constant with unsupported extension");
1571+
return TOK_SCANNER_ERROR;
1572+
}
1573+
newstack(yyansi_clval);
1574+
parser_stack(yyansi_clval)=convert_float_literal(yytext);
1575+
PARSER.set_source_location(parser_stack(yyansi_clval));
1576+
return TOK_FLOATING;
1577+
}
1578+
15641579
{gcc_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC)
15651580
{
1566-
yyansi_cerror("Preprocessor directive found");
1581+
yyansi_cerror("Floating-point constant with unsupported extension");
15671582
return TOK_SCANNER_ERROR;
15681583
}
15691584
newstack(yyansi_clval);

src/cpp/cpp_parser.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,36 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <util/config.h>
1515

16+
#include <ansi-c/gcc_version.h>
17+
1618
cpp_parsert cpp_parser;
1719

1820
bool cpp_parse();
1921

2022
bool cpp_parsert::parse()
2123
{
24+
if(!support_float16.has_value())
25+
{
26+
if(config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::GCC)
27+
{
28+
gcc_versiont gcc_version;
29+
gcc_version.get("gcc");
30+
support_float16 = gcc_version.flavor == gcc_versiont::flavort::GCC &&
31+
gcc_version.is_at_least(13u);
32+
}
33+
else
34+
support_float16 = false;
35+
}
36+
2237
// We use the ANSI-C scanner
2338
ansi_c_parser.cpp98=true;
2439
ansi_c_parser.cpp11 =
2540
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP11 ||
2641
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP14 ||
2742
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP17;
28-
ansi_c_parser.ts_18661_3_Floatn_types=false;
43+
ansi_c_parser.ts_18661_3_Floatn_types = false; // these are still typedefs
44+
ansi_c_parser.float16_type = *support_float16;
45+
ansi_c_parser.bf16_type = *support_float16;
2946
ansi_c_parser.in=in;
3047
ansi_c_parser.mode=mode;
3148
ansi_c_parser.set_file(get_file());

src/cpp/cpp_parser.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Author: Daniel Kroening, [email protected]
1919
#include "cpp_parse_tree.h"
2020
#include "cpp_token_buffer.h"
2121

22+
#include <optional>
23+
2224
class cpp_parsert:public parsert
2325
{
2426
public:
@@ -34,10 +36,11 @@ class cpp_parsert:public parsert
3436
asm_block_following=false;
3537
}
3638

37-
cpp_parsert():
38-
mode(configt::ansi_ct::flavourt::ANSI),
39-
recognize_wchar_t(true),
40-
asm_block_following(false)
39+
cpp_parsert()
40+
: mode(configt::ansi_ct::flavourt::ANSI),
41+
recognize_wchar_t(true),
42+
asm_block_following(false),
43+
support_float16(std::nullopt)
4144
{
4245
}
4346

@@ -65,6 +68,9 @@ class cpp_parsert:public parsert
6568
// scanner
6669
unsigned parenthesis_counter;
6770
bool asm_block_following;
71+
72+
protected:
73+
std::optional<bool> support_float16;
6874
};
6975

7076
extern cpp_parsert cpp_parser;

0 commit comments

Comments
 (0)