diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-09-09 13:45:33 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 13:45:33 +0000 |
commit | 55f60bd6fe2db6831762e243577515824e2fca5c (patch) | |
tree | b7fa367ee6c97ae3a5b9ab69bb7b1be0e02418c4 | |
parent | 38f2795947ab8d8080bab81c5e2ccdd24981cbcc (diff) | |
parent | 4faa7d7765f5840779c542430ca6aa9118008a5b (diff) | |
download | gcc-55f60bd6fe2db6831762e243577515824e2fca5c.zip gcc-55f60bd6fe2db6831762e243577515824e2fca5c.tar.gz gcc-55f60bd6fe2db6831762e243577515824e2fca5c.tar.bz2 |
Merge #659
659: Initial intrinsics builtin block r=philberty a=philberty
This is the initial piece to get the simple intrinsic's mapped over to GCC ones. The
GCC wrapper contains a mapping system of rust names over to the builtin gcc names
as far as I can tell gcc will allow for fallback onto linking against -lm.
I think this will be a nice piece of work for new contributors, given the number of intrinsics
Addresses #658
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Co-authored-by: Thomas Schwinge <thomas@codesourcery.com>
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.h | 2 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-extern.h | 10 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 91 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.h | 39 | ||||
-rw-r--r-- | gcc/rust/rust-backend.h | 4 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 508 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 34 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-stmt.h | 11 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 13 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 11 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 50 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/intrinsics-1.rs | 16 |
14 files changed, 473 insertions, 319 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 14294f3..0e181a6 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -87,6 +87,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-type.o \ rust/rust-lint-marklive.o \ rust/rust-hir-type-check-path.o \ + rust/rust-compile-intrinsic.o \ $(END) # removed object files from here diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index c0cfacf..5a26862 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -1,5 +1,3 @@ - - // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index a0ad200..d78a566 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -20,6 +20,7 @@ #define RUST_COMPILE_EXTERN_ITEM #include "rust-compile-base.h" +#include "rust-compile-intrinsic.h" #include "rust-compile-tyty.h" #include "rust-compile-implitem.h" #include "rust-compile-var-decl.h" @@ -118,6 +119,15 @@ public: fntype->override_context (); } + if (fntype->get_abi () == TyTy::FnType::ABI::INTRINSIC) + { + Intrinsics compile (ctx); + Bfunction *fndecl = compile.compile (fntype); + ctx->insert_function_decl (fntype->get_ty_ref (), fndecl, fntype); + return; + } + + rust_assert (fntype->get_abi () == TyTy::FnType::ABI::C); ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); const unsigned int flags diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc new file mode 100644 index 0000000..4068a7a --- /dev/null +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -0,0 +1,91 @@ +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-compile-intrinsic.h" + +namespace Rust { +namespace Compile { + +Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} + +Bfunction * +Intrinsics::compile (TyTy::FnType *fntype) +{ + rust_assert (fntype->get_abi () == TyTy::FnType::ABI::INTRINSIC); + + // https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs + // https://github.com/Rust-GCC/gccrs/issues/658 + + // let llvm_name = match name { + // sym::sqrtf32 => "llvm.sqrt.f32", + // sym::sqrtf64 => "llvm.sqrt.f64", + // sym::powif32 => "llvm.powi.f32", + // sym::powif64 => "llvm.powi.f64", + // sym::sinf32 => "llvm.sin.f32", + // sym::sinf64 => "llvm.sin.f64", + // sym::cosf32 => "llvm.cos.f32", + // sym::cosf64 => "llvm.cos.f64", + // sym::powf32 => "llvm.pow.f32", + // sym::powf64 => "llvm.pow.f64", + // sym::expf32 => "llvm.exp.f32", + // sym::expf64 => "llvm.exp.f64", + // sym::exp2f32 => "llvm.exp2.f32", + // sym::exp2f64 => "llvm.exp2.f64", + // sym::logf32 => "llvm.log.f32", + // sym::logf64 => "llvm.log.f64", + // sym::log10f32 => "llvm.log10.f32", + // sym::log10f64 => "llvm.log10.f64", + // sym::log2f32 => "llvm.log2.f32", + // sym::log2f64 => "llvm.log2.f64", + // sym::fmaf32 => "llvm.fma.f32", + // sym::fmaf64 => "llvm.fma.f64", + // sym::fabsf32 => "llvm.fabs.f32", + // sym::fabsf64 => "llvm.fabs.f64", + // sym::minnumf32 => "llvm.minnum.f32", + // sym::minnumf64 => "llvm.minnum.f64", + // sym::maxnumf32 => "llvm.maxnum.f32", + // sym::maxnumf64 => "llvm.maxnum.f64", + // sym::copysignf32 => "llvm.copysign.f32", + // sym::copysignf64 => "llvm.copysign.f64", + // sym::floorf32 => "llvm.floor.f32", + // sym::floorf64 => "llvm.floor.f64", + // sym::ceilf32 => "llvm.ceil.f32", + // sym::ceilf64 => "llvm.ceil.f64", + // sym::truncf32 => "llvm.trunc.f32", + // sym::truncf64 => "llvm.trunc.f64", + // sym::rintf32 => "llvm.rint.f32", + // sym::rintf64 => "llvm.rint.f64", + // sym::nearbyintf32 => "llvm.nearbyint.f32", + // sym::nearbyintf64 => "llvm.nearbyint.f64", + // sym::roundf32 => "llvm.round.f32", + // sym::roundf64 => "llvm.round.f64", + // _ => return None, + // }; + // Some(cx.get_intrinsic(&llvm_name)) + + Bfunction *builtin = ctx->get_backend ()->lookup_builtin_by_rust_name ( + fntype->get_identifier ()); + if (builtin != nullptr) + return builtin; + + Location locus = ctx->get_mappings ()->lookup_location (fntype->get_ref ()); + rust_error_at (locus, "unknown builtin"); + + return ctx->get_backend ()->error_function (); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-intrinsic.h b/gcc/rust/backend/rust-compile-intrinsic.h new file mode 100644 index 0000000..25e298a --- /dev/null +++ b/gcc/rust/backend/rust-compile-intrinsic.h @@ -0,0 +1,39 @@ +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_INTRINSIC +#define RUST_COMPILE_INTRINSIC + +#include "rust-compile-context.h" + +namespace Rust { +namespace Compile { + +class Intrinsics +{ +public: + Intrinsics (Context *ctx); + + Bfunction *compile (TyTy::FnType *fntype); + +private: + Context *ctx; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_INTRINSIC diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 1af76cf..105b2ea 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -842,7 +842,9 @@ public: // Look up a named built-in function in the current backend implementation. // Returns NULL if no built-in function by that name exists. - virtual Bfunction *lookup_builtin (const std::string &) = 0; + virtual Bfunction *lookup_gcc_builtin (const std::string &) = 0; + + virtual Bfunction *lookup_builtin_by_rust_name (const std::string &) = 0; // Utility. diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 1edb7f1..4c1dda8 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -512,7 +512,9 @@ public: bool function_set_body (Bfunction *function, Bstatement *code_stmt); - Bfunction *lookup_builtin (const std::string &); + Bfunction *lookup_gcc_builtin (const std::string &); + + Bfunction *lookup_builtin_by_rust_name (const std::string &); void write_global_definitions (const std::vector<Btype *> &, const std::vector<Bexpression *> &, @@ -546,11 +548,13 @@ private: static const int builtin_noreturn = 1 << 1; static const int builtin_novops = 1 << 2; - void define_builtin (built_in_function bcode, const char *name, - const char *libname, tree fntype, int flags); + void define_builtin (const std::string rust_name, built_in_function bcode, + const char *name, const char *libname, tree fntype, + int flags); // A mapping of the GCC built-ins exposed to GCCRust. std::map<std::string, Bfunction *> builtin_functions_; + std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin; }; // A helper function to create a GCC identifier from a C++ string. @@ -567,303 +571,230 @@ Gcc_backend::Gcc_backend () { /* We need to define the fetch_and_add functions, since we use them for ++ and --. */ - tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree (); - tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); - this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", - NULL, build_function_type_list (t, p, t, NULL_TREE), 0); - - t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree (); - p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); - this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", - NULL, build_function_type_list (t, p, t, NULL_TREE), 0); - - t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree (); - p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); - this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", - NULL, build_function_type_list (t, p, t, NULL_TREE), 0); - - t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree (); - p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); - this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", - NULL, build_function_type_list (t, p, t, NULL_TREE), 0); - - // We use __builtin_expect for magic import functions. - this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL, - build_function_type_list (long_integer_type_node, - long_integer_type_node, - long_integer_type_node, - NULL_TREE), - builtin_const); - - // We use __builtin_memcmp for struct comparisons. - this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", - build_function_type_list (integer_type_node, - const_ptr_type_node, - const_ptr_type_node, - size_type_node, NULL_TREE), - 0); - - // We use __builtin_memmove for copying data. - this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", - build_function_type_list (void_type_node, ptr_type_node, - const_ptr_type_node, - size_type_node, NULL_TREE), - 0); - - // We use __builtin_memset for zeroing data. - this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset", - build_function_type_list (void_type_node, ptr_type_node, - integer_type_node, - size_type_node, NULL_TREE), - 0); - - // Used by runtime/internal/sys and math/bits. - this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz", - build_function_type_list (integer_type_node, - unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", - build_function_type_list (integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz", - build_function_type_list (integer_type_node, - unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll", - build_function_type_list (integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", - build_function_type_list (integer_type_node, - unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll", - "popcountll", - build_function_type_list (integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", - build_function_type_list (uint16_type_node, - uint16_type_node, NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", - build_function_type_list (uint32_type_node, - uint32_type_node, NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", - build_function_type_list (uint64_type_node, - uint64_type_node, NULL_TREE), - builtin_const); + // tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree (); + // tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1, + // "__sync_fetch_and_add_1", + // NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + // t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree (); + // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, + // "__sync_fetch_and_add_2", + // NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + // t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree (); + // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4, + // "__sync_fetch_and_add_4", + // NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + // t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree (); + // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8, + // "__sync_fetch_and_add_8", + // NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + // // We use __builtin_expect for magic import functions. + // this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL, + // build_function_type_list (long_integer_type_node, + // long_integer_type_node, + // long_integer_type_node, + // NULL_TREE), + // builtin_const); + + // // We use __builtin_memcmp for struct comparisons. + // this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", + // build_function_type_list (integer_type_node, + // const_ptr_type_node, + // const_ptr_type_node, + // size_type_node, NULL_TREE), + // 0); + + // // We use __builtin_memmove for copying data. + // this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", + // build_function_type_list (void_type_node, ptr_type_node, + // const_ptr_type_node, + // size_type_node, NULL_TREE), + // 0); + + // // We use __builtin_memset for zeroing data. + // this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset", + // build_function_type_list (void_type_node, ptr_type_node, + // integer_type_node, + // size_type_node, NULL_TREE), + // 0); + + // // Used by runtime/internal/sys and math/bits. + // this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz", + // build_function_type_list (integer_type_node, + // unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", + // build_function_type_list (integer_type_node, + // long_long_unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz", + // build_function_type_list (integer_type_node, + // unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll", + // build_function_type_list (integer_type_node, + // long_long_unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", + // build_function_type_list (integer_type_node, + // unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll", + // "popcountll", + // build_function_type_list (integer_type_node, + // long_long_unsigned_type_node, + // NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", + // build_function_type_list (uint16_type_node, + // uint16_type_node, NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", + // build_function_type_list (uint32_type_node, + // uint32_type_node, NULL_TREE), + // builtin_const); + // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", + // build_function_type_list (uint64_type_node, + // uint64_type_node, NULL_TREE), + // builtin_const); // We provide some functions for the math library. - tree math_function_type - = build_function_type_list (double_type_node, double_type_node, NULL_TREE); - tree math_function_type_long - = build_function_type_list (long_double_type_node, long_double_type_node, - NULL_TREE); - tree math_function_type_two - = build_function_type_list (double_type_node, double_type_node, - double_type_node, NULL_TREE); - tree math_function_type_long_two - = build_function_type_list (long_double_type_node, long_double_type_node, - long_double_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ACOS, "__builtin_acos", "acos", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_ASIN, "__builtin_asin", "asin", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_ASINL, "__builtin_asinl", "asinl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_ATAN, "__builtin_atan", "atan", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_ATANL, "__builtin_atanl", "atanl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_ATAN2, "__builtin_atan2", "atan2", - math_function_type_two, builtin_const); - this->define_builtin (BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", - math_function_type_long_two, builtin_const); - this->define_builtin (BUILT_IN_CEIL, "__builtin_ceil", "ceil", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_CEILL, "__builtin_ceill", "ceill", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_COS, "__builtin_cos", "cos", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_COSL, "__builtin_cosl", "cosl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_EXP, "__builtin_exp", "exp", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_EXPL, "__builtin_expl", "expl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_EXPM1, "__builtin_expm1", "expm1", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_FABS, "__builtin_fabs", "fabs", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_FLOOR, "__builtin_floor", "floor", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_FLOORL, "__builtin_floorl", "floorl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_FMOD, "__builtin_fmod", "fmod", - math_function_type_two, builtin_const); - this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", - math_function_type_long_two, builtin_const); - this->define_builtin (BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", - build_function_type_list (double_type_node, - double_type_node, - integer_type_node, NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", - build_function_type_list (long_double_type_node, - long_double_type_node, - integer_type_node, NULL_TREE), - builtin_const); - this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_LOGL, "__builtin_logl", "logl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_LOG1P, "__builtin_log1p", "log1p", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_LOG10, "__builtin_log10", "log10", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_LOG10L, "__builtin_log10l", "log10l", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_LOG2, "__builtin_log2", "log2", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_LOG2L, "__builtin_log2l", "log2l", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_SIN, "__builtin_sin", "sin", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_SINL, "__builtin_sinl", "sinl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_TAN, "__builtin_tan", "tan", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_TANL, "__builtin_tanl", "tanl", - math_function_type_long, builtin_const); - this->define_builtin (BUILT_IN_TRUNC, "__builtin_trunc", "trunc", - math_function_type, builtin_const); - this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", - math_function_type_long, builtin_const); + tree math_function_type_f32 + = build_function_type_list (float_type_node, float_type_node, NULL_TREE); + + this->define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf", + math_function_type_f32, builtin_const); + + this->define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf", + math_function_type_f32, builtin_const); // We use __builtin_return_address in the thunk we build for // functions which call recover, and for runtime.getcallerpc. - t = build_function_type_list (ptr_type_node, unsigned_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", - NULL, t, 0); + // t = build_function_type_list (ptr_type_node, unsigned_type_node, + // NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS, + // "__builtin_return_address", + // NULL, t, 0); // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. - t = build_function_type_list (ptr_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t, 0); + // t = build_function_type_list (ptr_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t, + // 0); // The runtime calls __builtin_extract_return_addr when recording // the address to which a function returns. - this->define_builtin ( - BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL, - build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0); + // this->define_builtin ( + // BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL, + // build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0); // The compiler uses __builtin_trap for some exception handling // cases. - this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL, - build_function_type (void_type_node, void_list_node), - builtin_noreturn); + // this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL, + // build_function_type (void_type_node, void_list_node), + // builtin_noreturn); // The runtime uses __builtin_prefetch. - this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, - build_varargs_function_type_list (void_type_node, - const_ptr_type_node, - NULL_TREE), - builtin_novops); + // this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, + // build_varargs_function_type_list (void_type_node, + // const_ptr_type_node, + // NULL_TREE), + // builtin_novops); // The compiler uses __builtin_unreachable for cases that cannot // occur. - this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, - build_function_type (void_type_node, void_list_node), - builtin_const | builtin_noreturn); + // this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, + // build_function_type (void_type_node, void_list_node), + // builtin_const | builtin_noreturn); // We provide some atomic functions. - t = build_function_type_list (uint32_type_node, ptr_type_node, - integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, 0); - - t = build_function_type_list (uint64_type_node, ptr_type_node, - integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, 0); - - t = build_function_type_list (void_type_node, ptr_type_node, uint32_type_node, - integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t, - 0); - - t = build_function_type_list (void_type_node, ptr_type_node, uint64_type_node, - integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t, - 0); - - t = build_function_type_list (uint32_type_node, ptr_type_node, - uint32_type_node, integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, - t, 0); - - t = build_function_type_list (uint64_type_node, ptr_type_node, - uint64_type_node, integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, - t, 0); - - t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, - uint32_type_node, boolean_type_node, - integer_type_node, integer_type_node, - NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, - "__atomic_compare_exchange_4", NULL, t, 0); - - t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, - uint64_type_node, boolean_type_node, - integer_type_node, integer_type_node, - NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, - "__atomic_compare_exchange_8", NULL, t, 0); - - t = build_function_type_list (uint32_type_node, ptr_type_node, - uint32_type_node, integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", - NULL, t, 0); - - t = build_function_type_list (uint64_type_node, ptr_type_node, - uint64_type_node, integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", - NULL, t, 0); - - t = build_function_type_list (unsigned_char_type_node, ptr_type_node, - unsigned_char_type_node, integer_type_node, - NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", - NULL, t, 0); - this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", - NULL, t, 0); - - t = build_function_type_list (unsigned_char_type_node, ptr_type_node, - unsigned_char_type_node, integer_type_node, - NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, - t, 0); - this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, - t, 0); + // t = build_function_type_list (uint32_type_node, ptr_type_node, + // integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, + // 0); + + // t = build_function_type_list (uint64_type_node, ptr_type_node, + // integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, + // 0); + + // t = build_function_type_list (void_type_node, ptr_type_node, + // uint32_type_node, + // integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t, + // 0); + + // t = build_function_type_list (void_type_node, ptr_type_node, + // uint64_type_node, + // integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t, + // 0); + + // t = build_function_type_list (uint32_type_node, ptr_type_node, + // uint32_type_node, integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", + // NULL, + // t, 0); + + // t = build_function_type_list (uint64_type_node, ptr_type_node, + // uint64_type_node, integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", + // NULL, + // t, 0); + + // t = build_function_type_list (boolean_type_node, ptr_type_node, + // ptr_type_node, + // uint32_type_node, boolean_type_node, + // integer_type_node, integer_type_node, + // NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, + // "__atomic_compare_exchange_4", NULL, t, 0); + + // t = build_function_type_list (boolean_type_node, ptr_type_node, + // ptr_type_node, + // uint64_type_node, boolean_type_node, + // integer_type_node, integer_type_node, + // NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, + // "__atomic_compare_exchange_8", NULL, t, 0); + + // t = build_function_type_list (uint32_type_node, ptr_type_node, + // uint32_type_node, integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", + // NULL, t, 0); + + // t = build_function_type_list (uint64_type_node, ptr_type_node, + // uint64_type_node, integer_type_node, NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", + // NULL, t, 0); + + // t = build_function_type_list (unsigned_char_type_node, ptr_type_node, + // unsigned_char_type_node, integer_type_node, + // NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", + // NULL, t, 0); + // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", + // NULL, t, 0); + + // t = build_function_type_list (unsigned_char_type_node, ptr_type_node, + // unsigned_char_type_node, integer_type_node, + // NULL_TREE); + // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", + // NULL, + // t, 0); + // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", + // NULL, + // t, 0); } // Get an unnamed integer type. @@ -3490,13 +3421,23 @@ Gcc_backend::function_set_body (Bfunction *function, Bstatement *code_stmt) // Returns NULL if no built-in function by that name exists. Bfunction * -Gcc_backend::lookup_builtin (const std::string &name) +Gcc_backend::lookup_gcc_builtin (const std::string &name) { if (this->builtin_functions_.count (name) != 0) return this->builtin_functions_[name]; return NULL; } +Bfunction * +Gcc_backend::lookup_builtin_by_rust_name (const std::string &name) +{ + auto it = rust_intrinsic_to_gcc_builtin.find (name); + if (it == rust_intrinsic_to_gcc_builtin.end ()) + return NULL; + + return lookup_gcc_builtin (it->second); +} + // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as // emit early debugging information. @@ -3587,7 +3528,8 @@ Gcc_backend::write_export_data (const char *bytes, unsigned int size) // NORETURN_P is true if the function has the noreturn attribute. void -Gcc_backend::define_builtin (built_in_function bcode, const char *name, +Gcc_backend::define_builtin (const std::string rust_name, + built_in_function bcode, const char *name, const char *libname, tree fntype, int flags) { tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, @@ -3612,6 +3554,8 @@ Gcc_backend::define_builtin (built_in_function bcode, const char *name, DECL_IS_NOVOPS (decl) = 1; this->builtin_functions_[libname] = this->make_function (decl); } + + rust_intrinsic_to_gcc_builtin[rust_name] = name; } // Return the backend generator. diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 59ea4ef..b1eb2e3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -33,9 +33,9 @@ class TypeCheckTopLevelExternItem : public TypeCheckBase using Rust::Resolver::TypeCheckBase::visit; public: - static void Resolve (HIR::ExternalItem *item) + static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent) { - TypeCheckTopLevelExternItem resolver; + TypeCheckTopLevelExternItem resolver (parent); item->accept_vis (resolver); } @@ -115,16 +115,21 @@ public: if (function.is_variadic ()) flags |= FNTYPE_IS_VARADIC_FLAG; - auto fnType - = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_item_name (), flags, std::move (params), - ret_type, std::move (substitutions)); + auto fnType = new TyTy::FnType ( + function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), function.get_item_name (), flags, + TyTy::FnType::get_abi_from_string (parent.get_abi (), + parent.get_locus ()), + std::move (params), ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } private: - TypeCheckTopLevelExternItem () : TypeCheckBase () {} + TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent) + : TypeCheckBase (), parent (parent) + {} + + const HIR::ExternBlock &parent; }; class TypeCheckTopLevelImplItem : public TypeCheckBase @@ -233,11 +238,14 @@ public: context->insert_type (param.get_mappings (), param_tyty); } - auto fnType = new TyTy::FnType ( - function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), function.get_function_name (), - function.is_method () ? FNTYPE_IS_METHOD_FLAG : FNTYPE_DEFAULT_FLAGS, - std::move (params), ret_type, std::move (substitutions)); + auto fnType + = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_function_name (), + function.is_method () ? FNTYPE_IS_METHOD_FLAG + : FNTYPE_DEFAULT_FLAGS, + TyTy::FnType::ABI::RUST, std::move (params), ret_type, + std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 77cbc06..54280e8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -329,11 +329,12 @@ public: context->insert_type (param.get_mappings (), param_tyty); } - auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_function_name (), false, - std::move (params), ret_type, - std::move (substitutions)); + auto fnType + = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_function_name (), FNTYPE_DEFAULT_FLAGS, + TyTy::FnType::ABI::RUST, std::move (params), ret_type, + std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); TyTy::FnType *resolved_fn_type = fnType; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 5bffe13..6ec17a9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -287,11 +287,12 @@ public: context->insert_type (param.get_mappings (), param_tyty); } - auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_function_name (), - FNTYPE_DEFAULT_FLAGS, std::move (params), - ret_type, std::move (substitutions)); + auto fnType + = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_function_name (), FNTYPE_DEFAULT_FLAGS, + TyTy::FnType::ABI::RUST, std::move (params), ret_type, + std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } @@ -337,7 +338,7 @@ public: { for (auto &item : extern_block.get_extern_items ()) { - TypeCheckTopLevelExternItem::Resolve (item.get ()); + TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 453f743..bee2748 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -546,11 +546,12 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const context->insert_type (param.get_mappings (), param_tyty); } - auto resolved - = new TyTy::FnType (fn.get_mappings ().get_hirid (), - fn.get_mappings ().get_defid (), - function.get_function_name (), function.is_method (), - std::move (params), ret_type, substitutions); + auto resolved = new TyTy::FnType ( + fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (), + function.get_function_name (), + function.is_method () ? FNTYPE_IS_METHOD_FLAG : FNTYPE_DEFAULT_FLAGS, + TyTy::FnType::ABI::RUST, std::move (params), ret_type, substitutions); + context->insert_type (fn.get_mappings (), resolved); return resolved; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 7eb717f..316caea 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -882,7 +882,7 @@ FnType::clone () const std::pair<HIR::Pattern *, BaseType *> (p.first, p.second->clone ())); return new FnType (get_ref (), get_ty_ref (), get_id (), get_identifier (), - flags, std::move (cloned_params), + flags, abi, std::move (cloned_params), get_return_type ()->clone (), clone_substs (), get_combined_refs ()); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 0dfae37..7f149a9 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1071,12 +1071,51 @@ private: class FnType : public BaseType, public SubstitutionRef { public: + // FIXME these could be constants #define FNTYPE_DEFAULT_FLAGS 0x00 #define FNTYPE_IS_METHOD_FLAG 0x01 #define FNTYPE_IS_EXTERN_FLAG 0x02 #define FNTYPE_IS_VARADIC_FLAG 0X04 - FnType (HirId ref, DefId id, std::string identifier, uint8_t flags, + enum ABI + { + UNKNOWN, + RUST, + INTRINSIC, + C, + }; + + static ABI get_abi_from_string (const std::string &abi, Location locus) + { + if (abi.compare ("rust") == 0) + return ABI::C; + else if (abi.compare ("rust-intrinsic") == 0) + return ABI::INTRINSIC; + else if (abi.compare ("C") == 0) + return ABI::C; + + rust_error_at (locus, "unknown abi specified"); + return ABI::UNKNOWN; + } + + static std::string get_string_from_abi (ABI abi) + { + switch (abi) + { + case ABI::RUST: + return "rust"; + case ABI::INTRINSIC: + return "rust-intrinsic"; + case ABI::C: + return "C"; + + case ABI::UNKNOWN: + return "unknown"; + } + return "unknown"; + } + + FnType (HirId ref, DefId id, std::string identifier, uint8_t flags, ABI abi, std::vector<std::pair<HIR::Pattern *, BaseType *>> params, BaseType *type, std::vector<SubstitutionParamMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) @@ -1084,14 +1123,14 @@ public: SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), params (std::move (params)), type (type), flags (flags), - identifier (identifier), id (id) + identifier (identifier), id (id), abi (abi) { LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); } FnType (HirId ref, HirId ty_ref, DefId id, std::string identifier, - uint8_t flags, + uint8_t flags, ABI abi, std::vector<std::pair<HIR::Pattern *, BaseType *>> params, BaseType *type, std::vector<SubstitutionParamMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) @@ -1099,7 +1138,7 @@ public: SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), params (params), type (type), flags (flags), identifier (identifier), - id (id) + id (id), abi (abi) { LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); @@ -1184,12 +1223,15 @@ public: FnType * handle_substitions (SubstitutionArgumentMappings mappings) override final; + ABI get_abi () const { return abi; } + private: std::vector<std::pair<HIR::Pattern *, BaseType *>> params; BaseType *type; uint8_t flags; std::string identifier; DefId id; + ABI abi; }; class FnPtr : public BaseType diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs new file mode 100644 index 0000000..3c604df --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs @@ -0,0 +1,16 @@ +// { dg-additional-options -fdump-tree-original } + +extern "rust-intrinsic" { + pub fn sqrtf32(x: f32) -> f32; + pub fn sinf32(x: f32) -> f32; +} + +fn main() { + let mut f32; + + f32 = sqrtf32(5f32); + // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(5\.0e\+0\);$} 1 original } } + + f32 = sinf32(39f32); + // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } } +} |