Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C/C++ front-end: accept all floating-point extensions that GCC and Clang support #8169

Merged
merged 1 commit into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ src/ansi-c/compiler_headers/gcc_builtin_headers_omp.inc
src/ansi-c/compiler_headers/gcc_builtin_headers_power.inc
src/ansi-c/compiler_headers/gcc_builtin_headers_tm.inc
src/ansi-c/compiler_headers/gcc_builtin_headers_types.inc
src/ansi-c/compiler_headers/gcc_builtin_headers_types_gcc7plus.inc
src/ansi-c/compiler_headers/gcc_builtin_headers_ubsan.inc
src/ansi-c/compiler_headers/windows_builtin_headers.inc
src/cpp/cprover_library.inc
Expand Down
12 changes: 12 additions & 0 deletions regression/ansi-c/float_constant1/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,21 @@ STATIC_ASSERT(__builtin_types_compatible_p(_Float64, __typeof(1.0f64)));
STATIC_ASSERT(__builtin_types_compatible_p(_Float128, __typeof(1.0f128)));
STATIC_ASSERT(__builtin_types_compatible_p(_Float32x, __typeof(1.0f32x)));
STATIC_ASSERT(__builtin_types_compatible_p(_Float64x, __typeof(1.0f64x)));
// f128x should be supported by GCC >= 7 (and for C++ in GCC >=13), but there
// are no current GCC target architectures that actually support such types
STATIC_ASSERT(__builtin_types_compatible_p(_Float128x, __typeof(1.0f128x)));
#endif

#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 13
STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16)));
STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.0bf16)));
STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.BF16)));
#endif

#if defined(__clang__) && __clang_major__ >= 15
STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16)));
#endif

#ifdef __GNUC__
_Complex c;
#endif
Expand Down
2 changes: 0 additions & 2 deletions src/ansi-c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ make_inc(compiler_headers/gcc_builtin_headers_omp)
make_inc(compiler_headers/gcc_builtin_headers_power)
make_inc(compiler_headers/gcc_builtin_headers_tm)
make_inc(compiler_headers/gcc_builtin_headers_types)
make_inc(compiler_headers/gcc_builtin_headers_types_gcc7plus)
make_inc(compiler_headers/gcc_builtin_headers_ubsan)
make_inc(compiler_headers/windows_builtin_headers)
make_inc(cprover_builtin_headers)
Expand All @@ -104,7 +103,6 @@ set(extra_dependencies
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_power.inc
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_tm.inc
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_types.inc
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_types_gcc7plus.inc
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/gcc_builtin_headers_ubsan.inc
${CMAKE_CURRENT_BINARY_DIR}/compiler_headers/windows_builtin_headers.inc
${CMAKE_CURRENT_BINARY_DIR}/cprover_library.inc
Expand Down
1 change: 0 additions & 1 deletion src/ansi-c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ BUILTIN_FILES = \
compiler_headers/gcc_builtin_headers_power.inc \
compiler_headers/gcc_builtin_headers_tm.inc \
compiler_headers/gcc_builtin_headers_types.inc \
compiler_headers/gcc_builtin_headers_types_gcc7plus.inc \
compiler_headers/gcc_builtin_headers_ubsan.inc \
compiler_headers/windows_builtin_headers.inc

Expand Down
21 changes: 10 additions & 11 deletions src/ansi-c/ansi_c_internal_additions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ const char gcc_builtin_headers_types[] =
#include "compiler_headers/gcc_builtin_headers_types.inc" // IWYU pragma: keep
; // NOLINT(whitespace/semicolon)

const char gcc_builtin_headers_types_gcc7plus[] =
"#line 1 \"gcc_builtin_headers_types_gcc7plus.h\"\n"
// NOLINTNEXTLINE(whitespace/line_length)
#include "compiler_headers/gcc_builtin_headers_types_gcc7plus.inc" // IWYU pragma: keep
; // NOLINT(whitespace/semicolon)

const char gcc_builtin_headers_generic[] =
"#line 1 \"gcc_builtin_headers_generic.h\"\n"
#include "compiler_headers/gcc_builtin_headers_generic.inc" // IWYU pragma: keep
Expand Down Expand Up @@ -158,9 +152,7 @@ max_malloc_size(std::size_t pointer_width, std::size_t object_bits)
return ((mp_integer)1) << (mp_integer)bits_for_positive_offset;
}

void ansi_c_internal_additions(
std::string &code,
bool support_ts_18661_3_Floatn_types)
void ansi_c_internal_additions(std::string &code, bool support_float16_type)
{
// clang-format off
// do the built-in types and variables
Expand Down Expand Up @@ -249,8 +241,15 @@ void ansi_c_internal_additions(
config.ansi_c.mode == configt::ansi_ct::flavourt::ARM)
{
code+=gcc_builtin_headers_types;
if(support_ts_18661_3_Floatn_types)
code += gcc_builtin_headers_types_gcc7plus;
if(support_float16_type)
{
code +=
"typedef _Float16 __gcc_v8hf __attribute__((__vector_size__(16)));\n";
code +=
"typedef _Float16 __gcc_v16hf __attribute__((__vector_size__(32)));\n";
code +=
"typedef _Float16 __gcc_v32hf __attribute__((__vector_size__(64)));\n";
}

// there are many more, e.g., look at
// https://developer.apple.com/library/mac/#documentation/developertools/gcc-4.0.1/gcc/Target-Builtins.html
Expand Down
5 changes: 1 addition & 4 deletions src/ansi-c/ansi_c_internal_additions.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ Author: Daniel Kroening, [email protected]

#include <string>

void ansi_c_internal_additions(
std::string &code,
bool support_ts_18661_3_Floatn_types);
void ansi_c_internal_additions(std::string &code, bool support_float16_type);
void ansi_c_architecture_strings(std::string &code);

extern const char clang_builtin_headers[];
extern const char cprover_builtin_headers[];
extern const char gcc_builtin_headers_types[];
extern const char gcc_builtin_headers_types_gcc7plus[];
extern const char gcc_builtin_headers_generic[];
extern const char gcc_builtin_headers_math[];
extern const char gcc_builtin_headers_mem_string[];
Expand Down
6 changes: 5 additions & 1 deletion src/ansi-c/ansi_c_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ bool ansi_c_languaget::parse(
// parsing

std::string code;
ansi_c_internal_additions(code, config.ansi_c.ts_18661_3_Floatn_types);
ansi_c_internal_additions(code, config.ansi_c.float16_type);
std::istringstream codestr(code);

ansi_c_parser.clear();
Expand All @@ -77,6 +77,8 @@ bool ansi_c_languaget::parse(
ansi_c_parser.log.set_message_handler(message_handler);
ansi_c_parser.for_has_scope=config.ansi_c.for_has_scope;
ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
ansi_c_parser.float16_type = config.ansi_c.float16_type;
ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
ansi_c_parser.cpp98=false; // it's not C++
ansi_c_parser.cpp11=false; // it's not C++
ansi_c_parser.mode=config.ansi_c.mode;
Expand Down Expand Up @@ -203,6 +205,8 @@ bool ansi_c_languaget::to_expr(
ansi_c_parser.log.set_message_handler(message_handler);
ansi_c_parser.mode=config.ansi_c.mode;
ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
ansi_c_parser.float16_type = config.ansi_c.float16_type;
ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
ansi_c_scanner_init();

bool result=ansi_c_parser.parse();
Expand Down
6 changes: 5 additions & 1 deletion src/ansi-c/ansi_c_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class ansi_c_parsert:public parsert
cpp98(false),
cpp11(false),
for_has_scope(false),
ts_18661_3_Floatn_types(false)
ts_18661_3_Floatn_types(false),
float16_type(false),
bf16_type(false)
{
}

Expand Down Expand Up @@ -78,6 +80,8 @@ class ansi_c_parsert:public parsert

// ISO/IEC TS 18661-3:2015
bool ts_18661_3_Floatn_types;
bool float16_type;
bool bf16_type;

typedef ansi_c_identifiert identifiert;
typedef ansi_c_scopet scopet;
Expand Down
4 changes: 2 additions & 2 deletions src/ansi-c/builtin_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ static bool convert(
//! \return 'true' on error
bool builtin_factory(
const irep_idt &identifier,
bool support_ts_18661_3_Floatn_types,
bool support_float16_type,
symbol_table_baset &symbol_table,
message_handlert &mh)
{
Expand All @@ -107,7 +107,7 @@ bool builtin_factory(
std::ostringstream s;

std::string code;
ansi_c_internal_additions(code, support_ts_18661_3_Floatn_types);
ansi_c_internal_additions(code, support_float16_type);
s << code;

// our own extensions
Expand Down
2 changes: 1 addition & 1 deletion src/ansi-c/builtin_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class symbol_table_baset;
//! \return 'true' in case of error
bool builtin_factory(
const irep_idt &identifier,
bool support_ts_18661_3_Floatn_types,
bool support_float16_type,
symbol_table_baset &,
message_handlert &);

Expand Down
2 changes: 1 addition & 1 deletion src/ansi-c/c_typecheck_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2076,7 +2076,7 @@ bool c_typecheck_baset::builtin_factory(const irep_idt &identifier)
{
return ::builtin_factory(
identifier,
config.ansi_c.ts_18661_3_Floatn_types,
config.ansi_c.float16_type,
symbol_table,
get_message_handler());
}
Expand Down

This file was deleted.

12 changes: 12 additions & 0 deletions src/ansi-c/gcc_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,16 @@ void configure_gcc(const gcc_versiont &gcc_version)
config.ansi_c.gcc__float128_type =
gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(4u, gcc_float128_minor_version);

config.ansi_c.float16_type =
(gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(12u)) ||
(gcc_version.flavor == gcc_versiont::flavort::CLANG &&
gcc_version.is_at_least(15u));

config.ansi_c.bf16_type =
(gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(13u)) ||
(gcc_version.flavor == gcc_versiont::flavort::CLANG &&
gcc_version.is_at_least(15u));
}
17 changes: 7 additions & 10 deletions src/ansi-c/literals/parse_float.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ parse_floatt::parse_floatt(const std::string &src)
p++;

// get exponent
while(*p!=0 && *p!='f' && *p!='l' &&
*p!='w' && *p!='q' && *p!='d')
while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' &&
*p != 'd' && *p != 'b')
{
str_exponent+=*p;
p++;
Expand Down Expand Up @@ -121,10 +121,8 @@ parse_floatt::parse_floatt(const std::string &src)
p++;

// get fraction part
while(*p!=0 && *p!='e' &&
*p!='f' && *p!='l' &&
*p!='w' && *p!='q' && *p!='d' &&
*p!='i' && *p!='j')
while(*p != 0 && *p != 'e' && *p != 'f' && *p != 'l' && *p != 'w' &&
*p != 'q' && *p != 'd' && *p != 'i' && *p != 'j' && *p != 'b')
{
str_fraction_part+=*p;
p++;
Expand All @@ -139,9 +137,8 @@ parse_floatt::parse_floatt(const std::string &src)
p++;

// get exponent
while(*p!=0 && *p!='f' && *p!='l' &&
*p!='w' && *p!='q' && *p!='d' &&
*p!='i' && *p!='j')
while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' &&
*p != 'd' && *p != 'i' && *p != 'j' && *p != 'b')
{
str_exponent+=*p;
p++;
Expand Down Expand Up @@ -173,7 +170,7 @@ parse_floatt::parse_floatt(const std::string &src)
is_float80=false;
is_float128=is_float128x=false;

if(strcmp(p, "f16")==0)
if(strcmp(p, "f16") == 0 || strcmp(p, "bf16") == 0)
is_float16=true;
else if(strcmp(p, "f32")==0)
is_float32=true;
Expand Down
23 changes: 19 additions & 4 deletions src/ansi-c/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,13 @@ hexfloat1 "0"[xX]{hexdigit}*"."{hexdigit}+[pP][+-]?{integer}
hexfloat2 "0"[xX]{hexdigit}*"."[pP][+-]?{integer}
hexfloat3 "0"[xX]{hexdigit}*[pP][+-]?{integer}
float_suffix [fFlLiIjJ]*
gcc_ext_float_suffix [wWqQ]|[dD][fFdDlL]?|"f16"|"f32"|"f64"|"f128"|"f32x"|"f64x"|"f128x"
clang_ext_float_suffix [qQ]|"f16"|"F16"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these are standardised in the C++ standards; e.g., bf16 is C++23. They are not clang extensions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC and Clang support these at varying versions, and while the standard appears to specify them I wasn't able to make them work when using -std=c++23 (Clang) or /std:c++latest (MSVC).

gcc_ext_float_width (("bf"|"BF")"16")|([fF]("32"|"64"|"128"|"32x"|"64x"|"128x"))
gcc_ext_float_suffix {clang_ext_float_suffix}|[wW]|[dD][fFdDlL]?|{gcc_ext_float_width}
float {float1}|{float2}|{float3}|{hexfloat1}|{hexfloat2}|{hexfloat3}
float_s {float}{float_suffix}|{integer}[fF]
gcc_ext_float_s {float}{gcc_ext_float_suffix}
clang_ext_float_s {float}{clang_ext_float_suffix}
cppstart {ws}"#"{ws}
cpplineno {cppstart}"line"*{ws}{integer}{ws}.*{newline}
cppdirective {cppstart}({newline}|[^p].*|"p"[^r].*|"pr"[^a].*|"pra"[^g].*|"prag"[^m].*|"pragm"[^a].*)
Expand Down Expand Up @@ -524,13 +527,13 @@ void ansi_c_scanner_init()
return make_identifier();
}

"_Float16" { if(PARSER.ts_18661_3_Floatn_types)
"_Float16" { if(PARSER.float16_type)
{ loc(); return TOK_GCC_FLOAT16; }
else
return make_identifier();
}

"__bf16" { if(PARSER.ts_18661_3_Floatn_types)
"__bf16" { if(PARSER.bf16_type)
{ loc(); return TOK_GCC_FLOAT16; }
else
return make_identifier();
Expand Down Expand Up @@ -1561,9 +1564,21 @@ __decltype { if(PARSER.cpp98 &&
return TOK_INTEGER;
}

{clang_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC &&
PARSER.mode != configt::ansi_ct::flavourt::CLANG)
{
yyansi_cerror("Floating-point constant with unsupported extension");
return TOK_SCANNER_ERROR;
}
newstack(yyansi_clval);
parser_stack(yyansi_clval)=convert_float_literal(yytext);
PARSER.set_source_location(parser_stack(yyansi_clval));
return TOK_FLOATING;
}

{gcc_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC)
{
yyansi_cerror("Preprocessor directive found");
yyansi_cerror("Floating-point constant with unsupported extension");
return TOK_SCANNER_ERROR;
}
newstack(yyansi_clval);
Expand Down
19 changes: 18 additions & 1 deletion src/cpp/cpp_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,36 @@ Author: Daniel Kroening, [email protected]

#include <util/config.h>

#include <ansi-c/gcc_version.h>

cpp_parsert cpp_parser;

bool cpp_parse();

bool cpp_parsert::parse()
{
if(!support_float16.has_value())
{
if(config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::GCC)
{
gcc_versiont gcc_version;
gcc_version.get("gcc");
support_float16 = gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(13u);
}
else
support_float16 = false;
}

// We use the ANSI-C scanner
ansi_c_parser.cpp98=true;
ansi_c_parser.cpp11 =
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP11 ||
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP14 ||
config.cpp.cpp_standard == configt::cppt::cpp_standardt::CPP17;
ansi_c_parser.ts_18661_3_Floatn_types=false;
ansi_c_parser.ts_18661_3_Floatn_types = false; // these are still typedefs
ansi_c_parser.float16_type = *support_float16;
ansi_c_parser.bf16_type = *support_float16;
ansi_c_parser.in=in;
ansi_c_parser.mode=mode;
ansi_c_parser.set_file(get_file());
Expand Down
14 changes: 10 additions & 4 deletions src/cpp/cpp_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Author: Daniel Kroening, [email protected]
#include "cpp_parse_tree.h"
#include "cpp_token_buffer.h"

#include <optional>

class cpp_parsert:public parsert
{
public:
Expand All @@ -34,10 +36,11 @@ class cpp_parsert:public parsert
asm_block_following=false;
}

cpp_parsert():
mode(configt::ansi_ct::flavourt::ANSI),
recognize_wchar_t(true),
asm_block_following(false)
cpp_parsert()
: mode(configt::ansi_ct::flavourt::ANSI),
recognize_wchar_t(true),
asm_block_following(false),
support_float16(std::nullopt)
{
}

Expand Down Expand Up @@ -65,6 +68,9 @@ class cpp_parsert:public parsert
// scanner
unsigned parenthesis_counter;
bool asm_block_following;

protected:
std::optional<bool> support_float16;
};

extern cpp_parsert cpp_parser;
Expand Down
Loading
Loading