Skip to content

fix up __float128 and _Float128 support #4629

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

Merged
merged 2 commits into from
May 15, 2019
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
3 changes: 2 additions & 1 deletion regression/ansi-c/gcc_version1/gcc-5.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ typedef float _Float32;
typedef double _Float32x;
typedef double _Float64;
typedef long double _Float64x;
typedef long double _Float128;
typedef long double _Float128x;

// But this type should:
_Float128 f128;
__float128 f128;
2 changes: 2 additions & 0 deletions regression/ansi-c/gcc_version1/gcc-7.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ _Float64 f64;
_Float64x f64x;
_Float128 f128;
_Float128x f128x;

__float128 gcc_f128;
50 changes: 35 additions & 15 deletions regression/cbmc/ts18661_typedefs/main.c
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
#if defined(__GNUC__) && !defined(__clang__)
#if defined(__GNUC__)

#include <features.h> // For __GNUC_PREREQ
# ifdef __clang__

#ifdef __x86_64__
#define FLOAT128_MINOR_VERSION 3
#else
#define FLOAT128_MINOR_VERSION 5
#endif
# define HAS_FLOAT128

#if __GNUC__ >= 7
#define HAS_FLOATN
#elif __GNUC_PREREQ(4, FLOAT128_MINOR_VERSION)
#define HAS_FLOAT128
#endif
# else

# include <features.h> // For __GNUC_PREREQ

# ifdef __x86_64__
# define FLOAT128_MINOR_VERSION 3
# else
# define FLOAT128_MINOR_VERSION 5
# endif

# if __GNUC__ >= 7
# define HAS_FLOATN
# endif

# if __GNUC_PREREQ(4, FLOAT128_MINOR_VERSION)
# define HAS_FLOAT128
# endif

# endif

#endif

#ifndef HAS_FLOATN
#ifdef HAS_FLOATN
typedef _Float32 f1;
typedef _Float32x f2;
typedef _Float64 f3;
typedef _Float64x f4;
typedef _Float128 f5;
typedef _Float128x f6;
#else
typedef float _Float32;
typedef double _Float32x;
typedef double _Float64;
typedef long double _Float64x;
typedef long double _Float128;
typedef long double _Float128x;
#endif

#if !defined(HAS_FLOATN) && !defined(HAS_FLOAT128)
typedef long double _Float128;
#if defined(HAS_FLOAT128)
typedef __float128 f7;
#else
typedef long double __float128;
#endif

int main(int argc, char** argv) {
Expand Down
12 changes: 10 additions & 2 deletions src/ansi-c/ansi_c_internal_additions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,12 @@ void ansi_c_internal_additions(std::string &code)
// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
// For clang, __float128 is a keyword.
// For gcc, this is a typedef and not a keyword.
if(config.ansi_c.mode != configt::ansi_ct::flavourt::CLANG)
if(
config.ansi_c.mode != configt::ansi_ct::flavourt::CLANG &&
config.ansi_c.gcc__float128_type)
{
code += "typedef " CPROVER_PREFIX "Float128 __float128;\n";
}
}
else if(config.ansi_c.arch == "ppc64le")
{
Expand All @@ -222,8 +226,12 @@ void ansi_c_internal_additions(std::string &code)
// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
// For clang, __float128 is a keyword.
// For gcc, this is a typedef and not a keyword.
if(config.ansi_c.mode != configt::ansi_ct::flavourt::CLANG)
if(
config.ansi_c.mode != configt::ansi_ct::flavourt::CLANG &&
config.ansi_c.gcc__float128_type)
{
code+="typedef long double __float128;\n";
}
}

if(
Expand Down
1 change: 0 additions & 1 deletion src/ansi-c/ansi_c_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ bool ansi_c_languaget::parse(
ansi_c_parser.set_message_handler(get_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.Float128_type = config.ansi_c.Float128_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
22 changes: 9 additions & 13 deletions src/ansi-c/ansi_c_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@ class ansi_c_parsert:public parsert
public:
ansi_c_parse_treet parse_tree;

ansi_c_parsert():
tag_following(false),
asm_block_following(false),
parenthesis_counter(0),
mode(modet::NONE),
cpp98(false),
cpp11(false),
for_has_scope(false),
ts_18661_3_Floatn_types(false),
Float128_type(false)
ansi_c_parsert()
: tag_following(false),
asm_block_following(false),
parenthesis_counter(0),
mode(modet::NONE),
cpp98(false),
cpp11(false),
for_has_scope(false),
ts_18661_3_Floatn_types(false)
{
}

Expand Down Expand Up @@ -84,9 +83,6 @@ class ansi_c_parsert:public parsert
// ISO/IEC TS 18661-3:2015
bool ts_18661_3_Floatn_types;

// Does the compiler version emulated provide _Float128?
bool Float128_type;

typedef ansi_c_identifiert identifiert;
typedef ansi_c_scopet scopet;

Expand Down
20 changes: 20 additions & 0 deletions src/ansi-c/gcc_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,23 @@ std::ostream &operator<<(std::ostream &out, const gcc_versiont &v)
{
return out << v.v_major << '.' << v.v_minor << '.' << v.v_patchlevel;
}

void configure_gcc(const gcc_versiont &gcc_version)
{
// ISO/IEC TS 18661-3:2015 support was introduced with gcc 7.0
if(
gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(7u))
{
config.ansi_c.ts_18661_3_Floatn_types = true;
}

const auto gcc_float128_minor_version =
config.ansi_c.arch == "x86_64" ? 3u : 5u;

// __float128 exists (as a typedef) since gcc 4.5 everywhere,
// and since 4.3 on x86_64
config.ansi_c.gcc__float128_type =
gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(4u, gcc_float128_minor_version);
}
2 changes: 2 additions & 0 deletions src/ansi-c/gcc_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class gcc_versiont
}
};

void configure_gcc(const gcc_versiont &);

std::ostream &operator<<(std::ostream &, const gcc_versiont &);

#endif
2 changes: 1 addition & 1 deletion src/ansi-c/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ void ansi_c_scanner_init()
return make_identifier();
}

"_Float128" { if(PARSER.Float128_type)
"_Float128" { if(PARSER.ts_18661_3_Floatn_types)
{ loc(); return TOK_GCC_FLOAT128; }
else
return make_identifier();
Expand Down
9 changes: 9 additions & 0 deletions src/cbmc/cbmc_parse_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Author: Daniel Kroening, [email protected]

#include <ansi-c/c_preprocess.h>
#include <ansi-c/cprover_library.h>
#include <ansi-c/gcc_version.h>

#include <assembler/remove_asm.h>

Expand Down Expand Up @@ -490,6 +491,14 @@ int cbmc_parse_optionst::doit()

register_languages();

// configure gcc, if required
if(config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::GCC)
{
gcc_versiont gcc_version;
gcc_version.get("gcc");
configure_gcc(gcc_version);
}

if(cmdline.isset("test-preprocessor"))
return test_c_preprocessor(ui_message_handler)
? CPROVER_EXIT_PREPROCESSOR_TEST_FAILED
Expand Down
1 change: 0 additions & 1 deletion src/cpp/cpp_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ bool cpp_parsert::parse()
config.cpp.cpp_standard==configt::cppt::cpp_standardt::CPP11 ||
config.cpp.cpp_standard==configt::cppt::cpp_standardt::CPP14;
ansi_c_parser.ts_18661_3_Floatn_types=false;
ansi_c_parser.Float128_type = false;
ansi_c_parser.in=in;
ansi_c_parser.mode=mode;
ansi_c_parser.set_file(get_file());
Expand Down
15 changes: 3 additions & 12 deletions src/goto-cc/gcc_mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,22 +531,13 @@ int gcc_modet::doit()
if(cmdline.isset("-fsingle-precision-constant"))
config.ansi_c.single_precision_constant=true;

// ISO/IEC TS 18661-3:2015 support was introduced with gcc 7.0
if(gcc_version.flavor==gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(7))
config.ansi_c.ts_18661_3_Floatn_types=true;

const auto gcc_float128_minor_version =
config.ansi_c.arch == "x86_64" ? 3u : 5u;

config.ansi_c.Float128_type =
gcc_version.flavor == gcc_versiont::flavort::GCC &&
gcc_version.is_at_least(4u, gcc_float128_minor_version);

// -fshort-double makes double the same as float
if(cmdline.isset("fshort-double"))
config.ansi_c.double_width=config.ansi_c.single_width;

// configure version-specific gcc settings
configure_gcc(gcc_version);

switch(compiler.mode)
{
case compilet::LINK_LIBRARY:
Expand Down
2 changes: 1 addition & 1 deletion src/util/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ bool configt::set(const cmdlinet &cmdline)
}

if(ansi_c.preprocessor == ansi_ct::preprocessort::GCC)
ansi_c.Float128_type = true;
ansi_c.gcc__float128_type = true;

set_arch(arch);

Expand Down
2 changes: 1 addition & 1 deletion src/util/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class configt
bool char_is_unsigned, wchar_t_is_unsigned;
bool for_has_scope;
bool ts_18661_3_Floatn_types; // ISO/IEC TS 18661-3:2015
bool Float128_type;
bool gcc__float128_type; // __float128, a gcc extension since 4.3/4.5
bool single_precision_constant;
enum class c_standardt { C89, C99, C11 } c_standard;
static c_standardt default_c_standard();
Expand Down