From 518151f2c06eb758e33e1db2b9fb533f111ed0e8 Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 30 Apr 2014 16:47:02 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209941 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/go/ChangeLog | 9 + gcc/go/go-gcc.cc | 219 ++++++++++++++- gcc/go/gofrontend/backend.h | 5 + gcc/go/gofrontend/go.cc | 3 - gcc/go/gofrontend/gogo-tree.cc | 622 ++++++++--------------------------------- gcc/go/gofrontend/gogo.cc | 60 ++++ gcc/go/gofrontend/gogo.h | 25 -- 7 files changed, 412 insertions(+), 531 deletions(-) rewrite gcc/go/gofrontend/gogo-tree.cc (81%) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 1a863b04dbc..8d86e746d6e 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,12 @@ +2014-04-30 Chris Manghane + + * 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 * go-gcc.cc: Include "cgraph.h" and "gimplify.h". diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 499b6702303..0f3f44b32b8 100644 --- a/gcc/go/go-gcc.cc +++ b/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&, const std::vector&, @@ -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 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 diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index aca3dc6f90e..786223fe736 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -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, diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index ac772a095f7..d2331f3e0ae 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -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. diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc dissimilarity index 81% index 6b19a1d82e1..5b9a8180287 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -1,500 +1,122 @@ -// gogo-tree.cc -- convert Go frontend Gogo IR to gcc trees. - -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "go-system.h" - -#include "toplev.h" -#include "tree.h" -#include "stringpool.h" -#include "stor-layout.h" -#include "varasm.h" -#include "gimple-expr.h" -#include "gimplify.h" -#include "tree-iterator.h" -#include "cgraph.h" -#include "langhooks.h" -#include "convert.h" -#include "output.h" -#include "diagnostic.h" -#include "go-c.h" - -#include "types.h" -#include "expressions.h" -#include "statements.h" -#include "runtime.h" -#include "backend.h" -#include "gogo.h" - -// Whether we have seen any errors. - -bool -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 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::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 -tree -go_type_for_size(unsigned int bits, int unsignedp) -{ - const char* name; - switch (bits) - { - case 8: - name = unsignedp ? "uint8" : "int8"; - break; - case 16: - name = unsignedp ? "uint16" : "int16"; - break; - case 32: - name = unsignedp ? "uint32" : "int32"; - break; - case 64: - name = unsignedp ? "uint64" : "int64"; - break; - default: - if (bits == POINTER_SIZE && unsignedp) - name = "uintptr"; - else - return NULL_TREE; - } - Type* type = Type::lookup_integer_type(name); - return type_to_tree(type->get_backend(go_get_gogo())); -} - -// Return the type to use for a mode. - -GO_EXTERN_C -tree -go_type_for_mode(enum machine_mode mode, int unsignedp) -{ - // FIXME: This static_cast should be in machmode.h. - enum mode_class mc = static_cast(GET_MODE_CLASS(mode)); - if (mc == MODE_INT) - return go_type_for_size(GET_MODE_BITSIZE(mode), unsignedp); - else if (mc == MODE_FLOAT) - { - Type* type; - switch (GET_MODE_BITSIZE (mode)) - { - case 32: - type = Type::lookup_float_type("float32"); - break; - case 64: - type = Type::lookup_float_type("float64"); - break; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (mode == TYPE_MODE(long_double_type_node)) - return long_double_type_node; - return NULL_TREE; - } - return type_to_tree(type->get_backend(go_get_gogo())); - } - else if (mc == MODE_COMPLEX_FLOAT) - { - Type *type; - switch (GET_MODE_BITSIZE (mode)) - { - case 64: - type = Type::lookup_complex_type("complex64"); - break; - case 128: - type = Type::lookup_complex_type("complex128"); - break; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - return NULL_TREE; - } - return type_to_tree(type->get_backend(go_get_gogo())); - } - 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 *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; -} +// gogo-tree.cc -- convert Go frontend Gogo IR to gcc trees. + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go-system.h" + +#include "toplev.h" +#include "tree.h" +#include "stringpool.h" +#include "stor-layout.h" +#include "varasm.h" +#include "gimple-expr.h" +#include "gimplify.h" +#include "tree-iterator.h" +#include "cgraph.h" +#include "langhooks.h" +#include "convert.h" +#include "output.h" +#include "diagnostic.h" +#include "go-c.h" + +#include "types.h" +#include "expressions.h" +#include "statements.h" +#include "runtime.h" +#include "backend.h" +#include "gogo.h" + +// Whether we have seen any errors. + +bool +saw_errors() +{ + return errorcount != 0 || sorrycount != 0; +} + +// Return the integer type to use for a size. + +GO_EXTERN_C +tree +go_type_for_size(unsigned int bits, int unsignedp) +{ + const char* name; + switch (bits) + { + case 8: + name = unsignedp ? "uint8" : "int8"; + break; + case 16: + name = unsignedp ? "uint16" : "int16"; + break; + case 32: + name = unsignedp ? "uint32" : "int32"; + break; + case 64: + name = unsignedp ? "uint64" : "int64"; + break; + default: + if (bits == POINTER_SIZE && unsignedp) + name = "uintptr"; + else + return NULL_TREE; + } + Type* type = Type::lookup_integer_type(name); + return type_to_tree(type->get_backend(go_get_gogo())); +} + +// Return the type to use for a mode. + +GO_EXTERN_C +tree +go_type_for_mode(enum machine_mode mode, int unsignedp) +{ + // FIXME: This static_cast should be in machmode.h. + enum mode_class mc = static_cast(GET_MODE_CLASS(mode)); + if (mc == MODE_INT) + return go_type_for_size(GET_MODE_BITSIZE(mode), unsignedp); + else if (mc == MODE_FLOAT) + { + Type* type; + switch (GET_MODE_BITSIZE (mode)) + { + case 32: + type = Type::lookup_float_type("float32"); + break; + case 64: + type = Type::lookup_float_type("float64"); + break; + default: + // We have to check for long double in order to support + // i386 excess precision. + if (mode == TYPE_MODE(long_double_type_node)) + return long_double_type_node; + return NULL_TREE; + } + return type_to_tree(type->get_backend(go_get_gogo())); + } + else if (mc == MODE_COMPLEX_FLOAT) + { + Type *type; + switch (GET_MODE_BITSIZE (mode)) + { + case 64: + type = Type::lookup_complex_type("complex64"); + break; + case 128: + type = Type::lookup_complex_type("complex128"); + break; + default: + // We have to check for long double in order to support + // i386 excess precision. + if (mode == TYPE_MODE(complex_long_double_type_node)) + return complex_long_double_type_node; + return NULL_TREE; + } + return type_to_tree(type->get_backend(go_get_gogo())); + } + else + return NULL_TREE; +} diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index c6ff9886090..995a4f2d2da 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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* diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 0be81b2aafe..37cbbdf4411 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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(); -- 2.11.4.GIT