Skip to content

Commit 94990a8

Browse files
committed
Refactor how we define simple intrinsics
Intrinsics were hidden behind the GCC abstract. This removes it by keeping all of this logic within rust-intrinsic.cc so that we can make mappings of the rustc name to GCC ones. We have a big comment from the mappings used over to LLVM builtins which we can use to help guide how we do this for GCC.
1 parent a08ac0c commit 94990a8

File tree

3 files changed

+143
-140
lines changed

3 files changed

+143
-140
lines changed

gcc/rust/backend/rust-compile-intrinsic.cc

Lines changed: 143 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,152 @@
1515
// <http://www.gnu.org/licenses/>.
1616

1717
#include "rust-compile-intrinsic.h"
18+
#include "langhooks.h"
1819
#include "rust-compile-type.h"
1920
#include "rust-compile-fnparam.h"
2021
#include "rust-tree.h"
2122

2223
namespace Rust {
2324
namespace Compile {
2425

26+
// https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs
27+
// https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs
28+
// https://github.com/Rust-GCC/gccrs/issues/658
29+
//
30+
// let llvm_name = match name {
31+
// sym::sqrtf32 => "llvm.sqrt.f32",
32+
// sym::sqrtf64 => "llvm.sqrt.f64",
33+
// sym::powif32 => "llvm.powi.f32",
34+
// sym::powif64 => "llvm.powi.f64",
35+
// sym::sinf32 => "llvm.sin.f32",
36+
// sym::sinf64 => "llvm.sin.f64",
37+
// sym::cosf32 => "llvm.cos.f32",
38+
// sym::cosf64 => "llvm.cos.f64",
39+
// sym::powf32 => "llvm.pow.f32",
40+
// sym::powf64 => "llvm.pow.f64",
41+
// sym::expf32 => "llvm.exp.f32",
42+
// sym::expf64 => "llvm.exp.f64",
43+
// sym::exp2f32 => "llvm.exp2.f32",
44+
// sym::exp2f64 => "llvm.exp2.f64",
45+
// sym::logf32 => "llvm.log.f32",
46+
// sym::logf64 => "llvm.log.f64",
47+
// sym::log10f32 => "llvm.log10.f32",
48+
// sym::log10f64 => "llvm.log10.f64",
49+
// sym::log2f32 => "llvm.log2.f32",
50+
// sym::log2f64 => "llvm.log2.f64",
51+
// sym::fmaf32 => "llvm.fma.f32",
52+
// sym::fmaf64 => "llvm.fma.f64",
53+
// sym::fabsf32 => "llvm.fabs.f32",
54+
// sym::fabsf64 => "llvm.fabs.f64",
55+
// sym::minnumf32 => "llvm.minnum.f32",
56+
// sym::minnumf64 => "llvm.minnum.f64",
57+
// sym::maxnumf32 => "llvm.maxnum.f32",
58+
// sym::maxnumf64 => "llvm.maxnum.f64",
59+
// sym::copysignf32 => "llvm.copysign.f32",
60+
// sym::copysignf64 => "llvm.copysign.f64",
61+
// sym::floorf32 => "llvm.floor.f32",
62+
// sym::floorf64 => "llvm.floor.f64",
63+
// sym::ceilf32 => "llvm.ceil.f32",
64+
// sym::ceilf64 => "llvm.ceil.f64",
65+
// sym::truncf32 => "llvm.trunc.f32",
66+
// sym::truncf64 => "llvm.trunc.f64",
67+
// sym::rintf32 => "llvm.rint.f32",
68+
// sym::rintf64 => "llvm.rint.f64",
69+
// sym::nearbyintf32 => "llvm.nearbyint.f32",
70+
// sym::nearbyintf64 => "llvm.nearbyint.f64",
71+
// sym::roundf32 => "llvm.round.f32",
72+
// sym::roundf64 => "llvm.round.f64",
73+
// _ => return None,
74+
// };
75+
// Some(cx.get_intrinsic(&llvm_name))
76+
class SimpleIntrinsics
77+
{
78+
public:
79+
static SimpleIntrinsics &get ()
80+
{
81+
static SimpleIntrinsics instance;
82+
return instance;
83+
}
84+
85+
bool lookup_simple_builtin (const std::string &name, tree *builtin)
86+
{
87+
auto it = rust_intrinsic_to_gcc_builtin.find (name);
88+
if (it == rust_intrinsic_to_gcc_builtin.end ())
89+
return false;
90+
91+
return lookup_gcc_builtin (it->second, builtin);
92+
}
93+
94+
private:
95+
static const int builtin_const = 1 << 0;
96+
static const int builtin_noreturn = 1 << 1;
97+
static const int builtin_novops = 1 << 2;
98+
99+
SimpleIntrinsics () { setup (); }
100+
101+
void setup ()
102+
{
103+
tree math_function_type_f32
104+
= build_function_type_list (float_type_node, float_type_node, NULL_TREE);
105+
106+
define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf",
107+
math_function_type_f32, builtin_const);
108+
109+
define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf",
110+
math_function_type_f32, builtin_const);
111+
}
112+
113+
// Define a builtin function. BCODE is the builtin function code
114+
// defined by builtins.def. NAME is the name of the builtin function.
115+
// LIBNAME is the name of the corresponding library function, and is
116+
// NULL if there isn't one. FNTYPE is the type of the function.
117+
// CONST_P is true if the function has the const attribute.
118+
// NORETURN_P is true if the function has the noreturn attribute.
119+
void define_builtin (const std::string rust_name, built_in_function bcode,
120+
const char *name, const char *libname, tree fntype,
121+
int flags)
122+
{
123+
tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL,
124+
libname, NULL_TREE);
125+
if ((flags & builtin_const) != 0)
126+
TREE_READONLY (decl) = 1;
127+
if ((flags & builtin_noreturn) != 0)
128+
TREE_THIS_VOLATILE (decl) = 1;
129+
if ((flags & builtin_novops) != 0)
130+
DECL_IS_NOVOPS (decl) = 1;
131+
set_builtin_decl (bcode, decl, true);
132+
this->builtin_functions_[name] = decl;
133+
if (libname != NULL)
134+
{
135+
decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL,
136+
NULL, NULL_TREE);
137+
if ((flags & builtin_const) != 0)
138+
TREE_READONLY (decl) = 1;
139+
if ((flags & builtin_noreturn) != 0)
140+
TREE_THIS_VOLATILE (decl) = 1;
141+
if ((flags & builtin_novops) != 0)
142+
DECL_IS_NOVOPS (decl) = 1;
143+
this->builtin_functions_[libname] = decl;
144+
}
145+
146+
rust_intrinsic_to_gcc_builtin[rust_name] = name;
147+
}
148+
149+
bool lookup_gcc_builtin (const std::string &name, tree *builtin)
150+
{
151+
auto it = builtin_functions_.find (name);
152+
if (it == builtin_functions_.end ())
153+
return false;
154+
155+
*builtin = it->second;
156+
return true;
157+
}
158+
159+
// A mapping of the GCC built-ins exposed to GCC Rust.
160+
std::map<std::string, tree> builtin_functions_;
161+
std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin;
162+
};
163+
25164
static tree
26165
offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
27166

@@ -36,60 +175,10 @@ Intrinsics::compile (TyTy::FnType *fntype)
36175
{
37176
rust_assert (fntype->get_abi () == ABI::INTRINSIC);
38177

39-
// https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs
40-
// https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs
41-
// https://github.com/Rust-GCC/gccrs/issues/658
42-
43-
// let llvm_name = match name {
44-
// sym::sqrtf32 => "llvm.sqrt.f32",
45-
// sym::sqrtf64 => "llvm.sqrt.f64",
46-
// sym::powif32 => "llvm.powi.f32",
47-
// sym::powif64 => "llvm.powi.f64",
48-
// sym::sinf32 => "llvm.sin.f32",
49-
// sym::sinf64 => "llvm.sin.f64",
50-
// sym::cosf32 => "llvm.cos.f32",
51-
// sym::cosf64 => "llvm.cos.f64",
52-
// sym::powf32 => "llvm.pow.f32",
53-
// sym::powf64 => "llvm.pow.f64",
54-
// sym::expf32 => "llvm.exp.f32",
55-
// sym::expf64 => "llvm.exp.f64",
56-
// sym::exp2f32 => "llvm.exp2.f32",
57-
// sym::exp2f64 => "llvm.exp2.f64",
58-
// sym::logf32 => "llvm.log.f32",
59-
// sym::logf64 => "llvm.log.f64",
60-
// sym::log10f32 => "llvm.log10.f32",
61-
// sym::log10f64 => "llvm.log10.f64",
62-
// sym::log2f32 => "llvm.log2.f32",
63-
// sym::log2f64 => "llvm.log2.f64",
64-
// sym::fmaf32 => "llvm.fma.f32",
65-
// sym::fmaf64 => "llvm.fma.f64",
66-
// sym::fabsf32 => "llvm.fabs.f32",
67-
// sym::fabsf64 => "llvm.fabs.f64",
68-
// sym::minnumf32 => "llvm.minnum.f32",
69-
// sym::minnumf64 => "llvm.minnum.f64",
70-
// sym::maxnumf32 => "llvm.maxnum.f32",
71-
// sym::maxnumf64 => "llvm.maxnum.f64",
72-
// sym::copysignf32 => "llvm.copysign.f32",
73-
// sym::copysignf64 => "llvm.copysign.f64",
74-
// sym::floorf32 => "llvm.floor.f32",
75-
// sym::floorf64 => "llvm.floor.f64",
76-
// sym::ceilf32 => "llvm.ceil.f32",
77-
// sym::ceilf64 => "llvm.ceil.f64",
78-
// sym::truncf32 => "llvm.trunc.f32",
79-
// sym::truncf64 => "llvm.trunc.f64",
80-
// sym::rintf32 => "llvm.rint.f32",
81-
// sym::rintf64 => "llvm.rint.f64",
82-
// sym::nearbyintf32 => "llvm.nearbyint.f32",
83-
// sym::nearbyintf64 => "llvm.nearbyint.f64",
84-
// sym::roundf32 => "llvm.round.f32",
85-
// sym::roundf64 => "llvm.round.f64",
86-
// _ => return None,
87-
// };
88-
// Some(cx.get_intrinsic(&llvm_name))
89-
90-
tree builtin = ctx->get_backend ()->lookup_builtin_by_rust_name (
91-
fntype->get_identifier ());
92-
if (builtin != nullptr)
178+
tree builtin = error_mark_node;
179+
SimpleIntrinsics &simple_intrinsics = SimpleIntrinsics::get ();
180+
if (simple_intrinsics.lookup_simple_builtin (fntype->get_identifier (),
181+
&builtin))
93182
return builtin;
94183

95184
// is it an generic builtin?

gcc/rust/rust-backend.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -504,12 +504,6 @@ class Backend
504504
const std::vector<Bvariable *> &param_vars)
505505
= 0;
506506

507-
// Look up a named built-in function in the current backend implementation.
508-
// Returns NULL if no built-in function by that name exists.
509-
virtual tree lookup_gcc_builtin (const std::string &) = 0;
510-
511-
virtual tree lookup_builtin_by_rust_name (const std::string &) = 0;
512-
513507
// Utility.
514508

515509
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,

gcc/rust/rust-gcc.cc

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -344,19 +344,6 @@ class Gcc_backend : public Backend
344344
tree non_zero_size_type (tree);
345345

346346
tree convert_tree (tree, tree, Location);
347-
348-
private:
349-
static const int builtin_const = 1 << 0;
350-
static const int builtin_noreturn = 1 << 1;
351-
static const int builtin_novops = 1 << 2;
352-
353-
void define_builtin (const std::string rust_name, built_in_function bcode,
354-
const char *name, const char *libname, tree fntype,
355-
int flags);
356-
357-
// A mapping of the GCC built-ins exposed to GCCRust.
358-
std::map<std::string, tree> builtin_functions_;
359-
std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin;
360347
};
361348

362349
// A helper function to create a GCC identifier from a C++ string.
@@ -473,14 +460,6 @@ Gcc_backend::Gcc_backend ()
473460
// builtin_const);
474461

475462
// We provide some functions for the math library.
476-
tree math_function_type_f32
477-
= build_function_type_list (float_type_node, float_type_node, NULL_TREE);
478-
479-
this->define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf",
480-
math_function_type_f32, builtin_const);
481-
482-
this->define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf",
483-
math_function_type_f32, builtin_const);
484463

485464
// We use __builtin_return_address in the thunk we build for
486465
// functions which call recover, and for runtime.getcallerpc.
@@ -2661,27 +2640,6 @@ Gcc_backend::function_set_parameters (
26612640
return true;
26622641
}
26632642

2664-
// Look up a named built-in function in the current backend implementation.
2665-
// Returns NULL if no built-in function by that name exists.
2666-
2667-
tree
2668-
Gcc_backend::lookup_gcc_builtin (const std::string &name)
2669-
{
2670-
if (this->builtin_functions_.count (name) != 0)
2671-
return this->builtin_functions_[name];
2672-
return NULL;
2673-
}
2674-
2675-
tree
2676-
Gcc_backend::lookup_builtin_by_rust_name (const std::string &name)
2677-
{
2678-
auto it = rust_intrinsic_to_gcc_builtin.find (name);
2679-
if (it == rust_intrinsic_to_gcc_builtin.end ())
2680-
return NULL;
2681-
2682-
return lookup_gcc_builtin (it->second);
2683-
}
2684-
26852643
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
26862644
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
26872645
// emit early debugging information.
@@ -2763,44 +2721,6 @@ Gcc_backend::write_export_data (const char *bytes, unsigned int size)
27632721
rust_write_export_data (bytes, size);
27642722
}
27652723

2766-
// Define a builtin function. BCODE is the builtin function code
2767-
// defined by builtins.def. NAME is the name of the builtin function.
2768-
// LIBNAME is the name of the corresponding library function, and is
2769-
// NULL if there isn't one. FNTYPE is the type of the function.
2770-
// CONST_P is true if the function has the const attribute.
2771-
// NORETURN_P is true if the function has the noreturn attribute.
2772-
2773-
void
2774-
Gcc_backend::define_builtin (const std::string rust_name,
2775-
built_in_function bcode, const char *name,
2776-
const char *libname, tree fntype, int flags)
2777-
{
2778-
tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL,
2779-
libname, NULL_TREE);
2780-
if ((flags & builtin_const) != 0)
2781-
TREE_READONLY (decl) = 1;
2782-
if ((flags & builtin_noreturn) != 0)
2783-
TREE_THIS_VOLATILE (decl) = 1;
2784-
if ((flags & builtin_novops) != 0)
2785-
DECL_IS_NOVOPS (decl) = 1;
2786-
set_builtin_decl (bcode, decl, true);
2787-
this->builtin_functions_[name] = decl;
2788-
if (libname != NULL)
2789-
{
2790-
decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL,
2791-
NULL, NULL_TREE);
2792-
if ((flags & builtin_const) != 0)
2793-
TREE_READONLY (decl) = 1;
2794-
if ((flags & builtin_noreturn) != 0)
2795-
TREE_THIS_VOLATILE (decl) = 1;
2796-
if ((flags & builtin_novops) != 0)
2797-
DECL_IS_NOVOPS (decl) = 1;
2798-
this->builtin_functions_[libname] = decl;
2799-
}
2800-
2801-
rust_intrinsic_to_gcc_builtin[rust_name] = name;
2802-
}
2803-
28042724
// Return the backend generator.
28052725

28062726
Backend *

0 commit comments

Comments
 (0)