mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 17:11:01 +08:00
go-gcc.cc: #include "langhooks.h".
* go-gcc.cc: #include "langhooks.h". (Gcc_backend::Gcc_backend): Add constructor. (Gcc_backend::lookup_function): New function. (Gcc_backend::define_builtin): New private function. (Gcc_backend::gcc_backend): Remove. (go_get_backend): Use new to create new Gcc_backend. From-SVN: r209941
This commit is contained in:
parent
6657487103
commit
90cbaa2978
@ -1,3 +1,12 @@
|
||||
2014-04-30 Chris Manghane <cmang@google.com>
|
||||
|
||||
* go-gcc.cc: #include "langhooks.h".
|
||||
(Gcc_backend::Gcc_backend): Add constructor.
|
||||
(Gcc_backend::lookup_function): New function.
|
||||
(Gcc_backend::define_builtin): New private function.
|
||||
(Gcc_backend::gcc_backend): Remove.
|
||||
(go_get_backend): Use new to create new Gcc_backend.
|
||||
|
||||
2014-04-25 Chris Manghane <cmang@google.com>
|
||||
|
||||
* go-gcc.cc: Include "cgraph.h" and "gimplify.h".
|
||||
|
219
gcc/go/go-gcc.cc
219
gcc/go/go-gcc.cc
@ -34,6 +34,7 @@
|
||||
#include "basic-block.h"
|
||||
#include "gimple-expr.h"
|
||||
#include "gimplify.h"
|
||||
#include "langhooks.h"
|
||||
#include "toplev.h"
|
||||
#include "output.h"
|
||||
#include "real.h"
|
||||
@ -131,6 +132,8 @@ class Blabel : public Gcc_tree
|
||||
class Gcc_backend : public Backend
|
||||
{
|
||||
public:
|
||||
Gcc_backend();
|
||||
|
||||
// Types.
|
||||
|
||||
Btype*
|
||||
@ -425,6 +428,9 @@ class Gcc_backend : public Backend
|
||||
bool
|
||||
function_set_body(Bfunction* function, Bstatement* code_stmt);
|
||||
|
||||
Bfunction*
|
||||
lookup_builtin(const std::string&);
|
||||
|
||||
void
|
||||
write_global_definitions(const std::vector<Btype*>&,
|
||||
const std::vector<Bexpression*>&,
|
||||
@ -459,6 +465,14 @@ class Gcc_backend : public Backend
|
||||
|
||||
tree
|
||||
non_zero_size_type(tree);
|
||||
|
||||
private:
|
||||
void
|
||||
define_builtin(built_in_function bcode, const char* name, const char* libname,
|
||||
tree fntype, bool const_p);
|
||||
|
||||
// A mapping of the GCC built-ins exposed to GCCGo.
|
||||
std::map<std::string, Bfunction*> builtin_functions_;
|
||||
};
|
||||
|
||||
// A helper function.
|
||||
@ -469,6 +483,172 @@ get_identifier_from_string(const std::string& str)
|
||||
return get_identifier_with_length(str.data(), str.length());
|
||||
}
|
||||
|
||||
// Define the built-in functions that are exposed to GCCGo.
|
||||
|
||||
Gcc_backend::Gcc_backend()
|
||||
{
|
||||
/* We need to define the fetch_and_add functions, since we use them
|
||||
for ++ and --. */
|
||||
tree t = this->integer_type(BITS_PER_UNIT, 1)->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),
|
||||
false);
|
||||
|
||||
t = this->integer_type(BITS_PER_UNIT * 2, 1)->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),
|
||||
false);
|
||||
|
||||
t = this->integer_type(BITS_PER_UNIT * 4, 1)->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),
|
||||
false);
|
||||
|
||||
t = this->integer_type(BITS_PER_UNIT * 8, 1)->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),
|
||||
false);
|
||||
|
||||
// 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),
|
||||
true);
|
||||
|
||||
// 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),
|
||||
false);
|
||||
|
||||
// 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,
|
||||
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, true);
|
||||
this->define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2",
|
||||
math_function_type_two, true);
|
||||
this->define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l",
|
||||
math_function_type_long_two, true);
|
||||
this->define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_COS, "__builtin_cos", "cos",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod",
|
||||
math_function_type_two, true);
|
||||
this->define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl",
|
||||
math_function_type_long_two, true);
|
||||
this->define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp",
|
||||
build_function_type_list(double_type_node,
|
||||
double_type_node,
|
||||
integer_type_node,
|
||||
NULL_TREE),
|
||||
true);
|
||||
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),
|
||||
true);
|
||||
this->define_builtin(BUILT_IN_LOG, "__builtin_log", "log",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl",
|
||||
math_function_type_long, true);
|
||||
this->define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc",
|
||||
math_function_type, true);
|
||||
this->define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl",
|
||||
math_function_type_long, true);
|
||||
|
||||
// We use __builtin_return_address in the thunk we build for
|
||||
// functions which call recover.
|
||||
this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
|
||||
NULL,
|
||||
build_function_type_list(ptr_type_node,
|
||||
unsigned_type_node,
|
||||
NULL_TREE),
|
||||
false);
|
||||
|
||||
// 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),
|
||||
false);
|
||||
}
|
||||
|
||||
// Get an unnamed integer type.
|
||||
|
||||
Btype*
|
||||
@ -2598,6 +2778,17 @@ Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look up a named built-in function in the current backend implementation.
|
||||
// Returns NULL if no built-in function by that name exists.
|
||||
|
||||
Bfunction*
|
||||
Gcc_backend::lookup_builtin(const std::string& name)
|
||||
{
|
||||
if (this->builtin_functions_.count(name) != 0)
|
||||
return this->builtin_functions_[name];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
|
||||
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
|
||||
|
||||
@ -2680,16 +2871,38 @@ Gcc_backend::write_global_definitions(
|
||||
delete[] defs;
|
||||
}
|
||||
|
||||
// The single backend.
|
||||
// Define a builtin function. BCODE is the builtin function code
|
||||
// defined by builtins.def. NAME is the name of the builtin function.
|
||||
// LIBNAME is the name of the corresponding library function, and is
|
||||
// NULL if there isn't one. FNTYPE is the type of the function.
|
||||
// CONST_P is true if the function has the const attribute.
|
||||
|
||||
static Gcc_backend gcc_backend;
|
||||
void
|
||||
Gcc_backend::define_builtin(built_in_function bcode, const char* name,
|
||||
const char* libname, tree fntype, bool const_p)
|
||||
{
|
||||
tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL,
|
||||
libname, NULL_TREE);
|
||||
if (const_p)
|
||||
TREE_READONLY(decl) = 1;
|
||||
set_builtin_decl(bcode, decl, true);
|
||||
this->builtin_functions_[name] = this->make_function(decl);
|
||||
if (libname != NULL)
|
||||
{
|
||||
decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL,
|
||||
NULL, NULL_TREE);
|
||||
if (const_p)
|
||||
TREE_READONLY(decl) = 1;
|
||||
this->builtin_functions_[libname] = this->make_function(decl);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the backend generator.
|
||||
|
||||
Backend*
|
||||
go_get_backend()
|
||||
{
|
||||
return &gcc_backend;
|
||||
return new Gcc_backend();
|
||||
}
|
||||
|
||||
// FIXME: Temporary functions while converting to the new backend
|
||||
|
@ -660,6 +660,11 @@ class Backend
|
||||
virtual bool
|
||||
function_set_body(Bfunction* function, Bstatement* code_stmt) = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// Utility.
|
||||
|
||||
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
|
||||
|
@ -34,9 +34,6 @@ go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
|
||||
|
||||
if (relative_import_path != NULL)
|
||||
::gogo->set_relative_import_path(relative_import_path);
|
||||
|
||||
// FIXME: This should be in the gcc dependent code.
|
||||
::gogo->define_builtin_function_trees();
|
||||
}
|
||||
|
||||
// Parse the input files.
|
||||
|
@ -36,266 +36,6 @@ saw_errors()
|
||||
return errorcount != 0 || sorrycount != 0;
|
||||
}
|
||||
|
||||
// A helper function.
|
||||
|
||||
static inline tree
|
||||
get_identifier_from_string(const std::string& str)
|
||||
{
|
||||
return get_identifier_with_length(str.data(), str.length());
|
||||
}
|
||||
|
||||
// Builtin functions.
|
||||
|
||||
static std::map<std::string, tree> builtin_functions;
|
||||
|
||||
// Define a builtin function. BCODE is the builtin function code
|
||||
// defined by builtins.def. NAME is the name of the builtin function.
|
||||
// LIBNAME is the name of the corresponding library function, and is
|
||||
// NULL if there isn't one. FNTYPE is the type of the function.
|
||||
// CONST_P is true if the function has the const attribute.
|
||||
|
||||
static void
|
||||
define_builtin(built_in_function bcode, const char* name, const char* libname,
|
||||
tree fntype, bool const_p)
|
||||
{
|
||||
tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL,
|
||||
libname, NULL_TREE);
|
||||
if (const_p)
|
||||
TREE_READONLY(decl) = 1;
|
||||
set_builtin_decl(bcode, decl, true);
|
||||
builtin_functions[name] = decl;
|
||||
if (libname != NULL)
|
||||
{
|
||||
decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL,
|
||||
NULL, NULL_TREE);
|
||||
if (const_p)
|
||||
TREE_READONLY(decl) = 1;
|
||||
builtin_functions[libname] = decl;
|
||||
}
|
||||
}
|
||||
|
||||
// Create trees for implicit builtin functions.
|
||||
|
||||
void
|
||||
Gogo::define_builtin_function_trees()
|
||||
{
|
||||
/* We need to define the fetch_and_add functions, since we use them
|
||||
for ++ and --. */
|
||||
tree t = go_type_for_size(BITS_PER_UNIT, 1);
|
||||
tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
|
||||
define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", NULL,
|
||||
build_function_type_list(t, p, t, NULL_TREE), false);
|
||||
|
||||
t = go_type_for_size(BITS_PER_UNIT * 2, 1);
|
||||
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
|
||||
define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", NULL,
|
||||
build_function_type_list(t, p, t, NULL_TREE), false);
|
||||
|
||||
t = go_type_for_size(BITS_PER_UNIT * 4, 1);
|
||||
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
|
||||
define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", NULL,
|
||||
build_function_type_list(t, p, t, NULL_TREE), false);
|
||||
|
||||
t = go_type_for_size(BITS_PER_UNIT * 8, 1);
|
||||
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
|
||||
define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", NULL,
|
||||
build_function_type_list(t, p, t, NULL_TREE), false);
|
||||
|
||||
// We use __builtin_expect for magic import functions.
|
||||
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),
|
||||
true);
|
||||
|
||||
// We use __builtin_memcmp for struct comparisons.
|
||||
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),
|
||||
false);
|
||||
|
||||
// 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,
|
||||
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);
|
||||
define_builtin(BUILT_IN_ACOS, "__builtin_acos", "acos",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2",
|
||||
math_function_type_two, true);
|
||||
define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l",
|
||||
math_function_type_long_two, true);
|
||||
define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_COS, "__builtin_cos", "cos",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod",
|
||||
math_function_type_two, true);
|
||||
define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl",
|
||||
math_function_type_long_two, true);
|
||||
define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp",
|
||||
build_function_type_list(double_type_node,
|
||||
double_type_node,
|
||||
integer_type_node,
|
||||
NULL_TREE),
|
||||
true);
|
||||
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),
|
||||
true);
|
||||
define_builtin(BUILT_IN_LOG, "__builtin_log", "log",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl",
|
||||
math_function_type_long, true);
|
||||
define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc",
|
||||
math_function_type, true);
|
||||
define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl",
|
||||
math_function_type_long, true);
|
||||
|
||||
// We use __builtin_return_address in the thunk we build for
|
||||
// functions which call recover.
|
||||
define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", NULL,
|
||||
build_function_type_list(ptr_type_node,
|
||||
unsigned_type_node,
|
||||
NULL_TREE),
|
||||
false);
|
||||
|
||||
// The compiler uses __builtin_trap for some exception handling
|
||||
// cases.
|
||||
define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL,
|
||||
build_function_type(void_type_node, void_list_node),
|
||||
false);
|
||||
}
|
||||
|
||||
// Get the backend representation.
|
||||
|
||||
Bfunction*
|
||||
Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
|
||||
{
|
||||
if (this->fndecl_ == NULL)
|
||||
{
|
||||
// Let Go code use an asm declaration to pick up a builtin
|
||||
// function.
|
||||
if (!this->asm_name_.empty())
|
||||
{
|
||||
std::map<std::string, tree>::const_iterator p =
|
||||
builtin_functions.find(this->asm_name_);
|
||||
if (p != builtin_functions.end())
|
||||
{
|
||||
this->fndecl_ = tree_to_function(p->second);
|
||||
return this->fndecl_;
|
||||
}
|
||||
}
|
||||
|
||||
std::string asm_name;
|
||||
if (this->asm_name_.empty())
|
||||
{
|
||||
asm_name = (no->package() == NULL
|
||||
? gogo->pkgpath_symbol()
|
||||
: no->package()->pkgpath_symbol());
|
||||
asm_name.append(1, '.');
|
||||
asm_name.append(Gogo::unpack_hidden_name(no->name()));
|
||||
if (this->fntype_->is_method())
|
||||
{
|
||||
asm_name.append(1, '.');
|
||||
Type* rtype = this->fntype_->receiver()->type();
|
||||
asm_name.append(rtype->mangled_name(gogo));
|
||||
}
|
||||
}
|
||||
|
||||
Btype* functype = this->fntype_->get_backend_fntype(gogo);
|
||||
this->fndecl_ =
|
||||
gogo->backend()->function(functype, no->get_id(gogo), asm_name,
|
||||
true, true, true, false, false,
|
||||
this->location());
|
||||
}
|
||||
|
||||
return this->fndecl_;
|
||||
}
|
||||
|
||||
// Build the descriptor for a function declaration. This won't
|
||||
// necessarily happen if the package has just a declaration for the
|
||||
// function and no other reference to it, but we may still need the
|
||||
// descriptor for references from other packages.
|
||||
void
|
||||
Function_declaration::build_backend_descriptor(Gogo* gogo)
|
||||
{
|
||||
if (this->descriptor_ != NULL)
|
||||
{
|
||||
Translate_context context(gogo, NULL, NULL, NULL);
|
||||
this->descriptor_->get_tree(&context);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the integer type to use for a size.
|
||||
|
||||
GO_EXTERN_C
|
||||
@ -380,121 +120,3 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
// Build a constructor for a slice. SLICE_TYPE_TREE is the type of
|
||||
// the slice. VALUES is the value pointer and COUNT is the number of
|
||||
// entries. If CAPACITY is not NULL, it is the capacity; otherwise
|
||||
// the capacity and the count are the same.
|
||||
|
||||
tree
|
||||
Gogo::slice_constructor(tree slice_type_tree, tree values, tree count,
|
||||
tree capacity)
|
||||
{
|
||||
go_assert(TREE_CODE(slice_type_tree) == RECORD_TYPE);
|
||||
|
||||
vec<constructor_elt, va_gc> *init;
|
||||
vec_alloc(init, 3);
|
||||
|
||||
tree field = TYPE_FIELDS(slice_type_tree);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__values") == 0);
|
||||
constructor_elt empty = {NULL, NULL};
|
||||
constructor_elt* elt = init->quick_push(empty);
|
||||
elt->index = field;
|
||||
go_assert(TYPE_MAIN_VARIANT(TREE_TYPE(field))
|
||||
== TYPE_MAIN_VARIANT(TREE_TYPE(values)));
|
||||
elt->value = values;
|
||||
|
||||
count = fold_convert(sizetype, count);
|
||||
if (capacity == NULL_TREE)
|
||||
{
|
||||
count = save_expr(count);
|
||||
capacity = count;
|
||||
}
|
||||
|
||||
field = DECL_CHAIN(field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__count") == 0);
|
||||
elt = init->quick_push(empty);
|
||||
elt->index = field;
|
||||
elt->value = fold_convert(TREE_TYPE(field), count);
|
||||
|
||||
field = DECL_CHAIN(field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__capacity") == 0);
|
||||
elt = init->quick_push(empty);
|
||||
elt->index = field;
|
||||
elt->value = fold_convert(TREE_TYPE(field), capacity);
|
||||
|
||||
return build_constructor(slice_type_tree, init);
|
||||
}
|
||||
|
||||
// Mark a function as a builtin library function.
|
||||
|
||||
void
|
||||
Gogo::mark_fndecl_as_builtin_library(tree fndecl)
|
||||
{
|
||||
DECL_EXTERNAL(fndecl) = 1;
|
||||
TREE_PUBLIC(fndecl) = 1;
|
||||
DECL_ARTIFICIAL(fndecl) = 1;
|
||||
TREE_NOTHROW(fndecl) = 1;
|
||||
DECL_VISIBILITY(fndecl) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED(fndecl) = 1;
|
||||
}
|
||||
|
||||
// Build a call to a builtin function.
|
||||
|
||||
tree
|
||||
Gogo::call_builtin(tree* pdecl, Location location, const char* name,
|
||||
int nargs, tree rettype, ...)
|
||||
{
|
||||
if (rettype == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
tree* types = new tree[nargs];
|
||||
tree* args = new tree[nargs];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, rettype);
|
||||
for (int i = 0; i < nargs; ++i)
|
||||
{
|
||||
types[i] = va_arg(ap, tree);
|
||||
args[i] = va_arg(ap, tree);
|
||||
if (types[i] == error_mark_node || args[i] == error_mark_node)
|
||||
{
|
||||
delete[] types;
|
||||
delete[] args;
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (*pdecl == NULL_TREE)
|
||||
{
|
||||
tree fnid = get_identifier(name);
|
||||
|
||||
tree argtypes = NULL_TREE;
|
||||
tree* pp = &argtypes;
|
||||
for (int i = 0; i < nargs; ++i)
|
||||
{
|
||||
*pp = tree_cons(NULL_TREE, types[i], NULL_TREE);
|
||||
pp = &TREE_CHAIN(*pp);
|
||||
}
|
||||
*pp = void_list_node;
|
||||
|
||||
tree fntype = build_function_type(rettype, argtypes);
|
||||
|
||||
*pdecl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL, fnid, fntype);
|
||||
Gogo::mark_fndecl_as_builtin_library(*pdecl);
|
||||
go_preserve_from_gc(*pdecl);
|
||||
}
|
||||
|
||||
tree fnptr = build_fold_addr_expr(*pdecl);
|
||||
if (CAN_HAVE_LOCATION_P(fnptr))
|
||||
SET_EXPR_LOCATION(fnptr, location.gcc_location());
|
||||
|
||||
tree ret = build_call_array(rettype, fnptr, nargs, args);
|
||||
SET_EXPR_LOCATION(ret, location.gcc_location());
|
||||
|
||||
delete[] types;
|
||||
delete[] args;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -4855,6 +4855,66 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
|
||||
return this->fndecl_;
|
||||
}
|
||||
|
||||
// Get the backend representation.
|
||||
|
||||
Bfunction*
|
||||
Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
|
||||
{
|
||||
if (this->fndecl_ == NULL)
|
||||
{
|
||||
// Let Go code use an asm declaration to pick up a builtin
|
||||
// function.
|
||||
if (!this->asm_name_.empty())
|
||||
{
|
||||
Bfunction* builtin_decl =
|
||||
gogo->backend()->lookup_builtin(this->asm_name_);
|
||||
if (builtin_decl != NULL)
|
||||
{
|
||||
this->fndecl_ = builtin_decl;
|
||||
return this->fndecl_;
|
||||
}
|
||||
}
|
||||
|
||||
std::string asm_name;
|
||||
if (this->asm_name_.empty())
|
||||
{
|
||||
asm_name = (no->package() == NULL
|
||||
? gogo->pkgpath_symbol()
|
||||
: no->package()->pkgpath_symbol());
|
||||
asm_name.append(1, '.');
|
||||
asm_name.append(Gogo::unpack_hidden_name(no->name()));
|
||||
if (this->fntype_->is_method())
|
||||
{
|
||||
asm_name.append(1, '.');
|
||||
Type* rtype = this->fntype_->receiver()->type();
|
||||
asm_name.append(rtype->mangled_name(gogo));
|
||||
}
|
||||
}
|
||||
|
||||
Btype* functype = this->fntype_->get_backend_fntype(gogo);
|
||||
this->fndecl_ =
|
||||
gogo->backend()->function(functype, no->get_id(gogo), asm_name,
|
||||
true, true, true, false, false,
|
||||
this->location());
|
||||
}
|
||||
|
||||
return this->fndecl_;
|
||||
}
|
||||
|
||||
// Build the descriptor for a function declaration. This won't
|
||||
// necessarily happen if the package has just a declaration for the
|
||||
// function and no other reference to it, but we may still need the
|
||||
// descriptor for references from other packages.
|
||||
void
|
||||
Function_declaration::build_backend_descriptor(Gogo* gogo)
|
||||
{
|
||||
if (this->descriptor_ != NULL)
|
||||
{
|
||||
Translate_context context(gogo, NULL, NULL, NULL);
|
||||
this->descriptor_->get_tree(&context);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the function's decl after it has been built.
|
||||
|
||||
Bfunction*
|
||||
|
@ -575,35 +575,10 @@ class Gogo
|
||||
void
|
||||
write_globals();
|
||||
|
||||
// Create trees for implicit builtin functions.
|
||||
void
|
||||
define_builtin_function_trees();
|
||||
|
||||
// Build a call to a builtin function. PDECL should point to a NULL
|
||||
// initialized static pointer which will hold the fndecl. NAME is
|
||||
// the name of the function. NARGS is the number of arguments.
|
||||
// RETTYPE is the return type. It is followed by NARGS pairs of
|
||||
// type and argument (both trees).
|
||||
static tree
|
||||
call_builtin(tree* pdecl, Location, const char* name, int nargs,
|
||||
tree rettype, ...);
|
||||
|
||||
// Build a call to the runtime error function.
|
||||
Expression*
|
||||
runtime_error(int code, Location);
|
||||
|
||||
// Mark a function declaration as a builtin library function.
|
||||
static void
|
||||
mark_fndecl_as_builtin_library(tree fndecl);
|
||||
|
||||
// Build a constructor for a slice. SLICE_TYPE_TREE is the type of
|
||||
// the slice. VALUES points to the values. COUNT is the size,
|
||||
// CAPACITY is the capacity. If CAPACITY is NULL, it is set to
|
||||
// COUNT.
|
||||
static tree
|
||||
slice_constructor(tree slice_type_tree, tree values, tree count,
|
||||
tree capacity);
|
||||
|
||||
// Build required interface method tables.
|
||||
void
|
||||
build_interface_method_tables();
|
||||
|
Loading…
x
Reference in New Issue
Block a user