From 280a041afacfca5a76e695cccbf28748588b9894 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 18 Mar 2016 17:56:28 -0400 Subject: [PATCH 01/91] FIXME: enough to build an rtl1 --- gcc/rtl/Make-lang.in | 145 +++++++++++++++++ gcc/rtl/config-lang.in | 36 +++++ gcc/rtl/rtl-frontend.c | 419 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 600 insertions(+) create mode 100644 gcc/rtl/Make-lang.in create mode 100644 gcc/rtl/config-lang.in create mode 100644 gcc/rtl/rtl-frontend.c diff --git a/gcc/rtl/Make-lang.in b/gcc/rtl/Make-lang.in new file mode 100644 index 0000000..f92ec24 --- /dev/null +++ b/gcc/rtl/Make-lang.in @@ -0,0 +1,145 @@ +# Make-lang.in -- Top level -*- makefile -*- fragment for RTL frontend. + +# Copyright (C) 2016 Free Software Foundation, Inc. + +# 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 +# . + +# This file provides the language dependent support in the main Makefile. + +# The name for selecting the RTL frontend in LANGUAGES. +rtl: rtl1$(exeext) + +.PHONY: rtl + +# Use strict warnings. +rtl-warn = $(STRICT_WARN) + +RTL_OBJS = \ + rtl/rtl-frontend.o + +rtl1$(exeext): $(RTL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) + +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + $(RTL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) + +# Build hooks: + +rtl.all.cross: +rtl.start.encap: +rtl.rest.encap: +rtl.info: +rtl.man: + +lang_checks += check-rtl +lang_checks_parallelized += check-rtl +check_rtl_parallelize = 10 + +# Install hooks. + +rtl.install-common: installdirs + -rm -f $(DESTDIR)$(bindir)/$(GCCRTL_INSTALL_NAME)$(exeext) + $(INSTALL_PROGRAM) gccrtl$(exeext) $(DESTDIR)$(bindir)/$(GCCRTL_INSTALL_NAME)$(exeext) + -if test -f rtl1$(exeext); then \ + if test -f gccrtl-cross$(exeext); then \ + :; \ + else \ + rm -f $(DESTDIR)$(bindir)/$(GCCRTL_TARGET_INSTALL_NAME)$(exeext); \ + ( cd $(DESTDIR)$(bindir) && \ + $(LN) $(GCCRTL_INSTALL_NAME)$(exeext) $(GCCRTL_TARGET_INSTALL_NAME)$(exeext) ); \ + fi; \ + fi + +rtl.install-plugin: + +rtl.install-info: $(DESTDIR)$(infodir)/gccrtl.info + +rtl.install-pdf: doc/gccrtl.pdf + @$(NORMAL_INSTALL) + test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc" + @for p in doc/gccrtl.pdf; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(pdf__strip_dir) \ + echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \ + $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \ + done + +rtl.install-html: $(build_htmldir)/rtl + @$(NORMAL_INSTALL) + test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)" + @for p in $(build_htmldir)/rtl; do \ + if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \ + f=$(html__strip_dir) \ + if test -d "$$d$$p"; then \ + echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \ + $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ + echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \ + else \ + echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \ + fi; \ + done + +rtl.install-man: $(DESTDIR)$(man1dir)/$(GCCRTL_INSTALL_NAME)$(man1ext) + +$(DESTDIR)$(man1dir)/$(GCCRTL_INSTALL_NAME)$(man1ext): doc/gccrtl.1 installdirs + -rm -f $@ + -$(INSTALL_DATA) $< $@ + -chmod a-x $@ + +rtl.uninstall: + rm -rf $(DESTDIR)$(bindir)/$(GCCRTL_INSTALL_NAME)$(exeext) + rm -rf $(DESTDIR)$(man1dir)/$(GCCRTL_INSTALL_NAME)$(man1ext) + rm -rf $(DESTDIR)$(bindir)/$(GCCRTL_TARGET_INSTALL_NAME)$(exeext) + rm -rf $(DESTDIR)$(infodir)/gccrtl.info* + +# Clean hooks. + +rtl.mostlyclean: + -rm -f rtl/*$(objext) + -rm -f rtl/*$(coverageexts) + -rm -f gccrtl$(exeext) gccrtl-cross$(exeext) rtl1$(exeext) +rtl.clean: +rtl.distclean: +rtl.maintainer-clean: + -rm -f $(docobjdir)/gccrtl.1 + +# Stage hooks. + +rtl.stage1: stage1-start + -mv rtl/*$(objext) stage1/rtl +rtl.stage2: stage2-start + -mv rtl/*$(objext) stage2/rtl +rtl.stage3: stage3-start + -mv rtl/*$(objext) stage3/rtl +rtl.stage4: stage4-start + -mv rtl/*$(objext) stage4/rtl +rtl.stageprofile: stageprofile-start + -mv rtl/*$(objext) stageprofile/rtl +rtl.stagefeedback: stagefeedback-start + -mv rtl/*$(objext) stagefeedback/rtl + +CFLAGS-rtl/rtl-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ + -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" + +RTLINCLUDES = -I $(srcdir)/rtl -I $(srcdir)/rtl/rtlfrontend + +CFLAGS-rtl/rtl-gcc.o += $(RTLINCLUDES) +CFLAGS-rtl/rtl-linemap.o += $(RTLINCLUDES) + +rtl/%.o: rtl/rtlfrontend/%.c + $(COMPILE) $(RTLINCLUDES) $< + $(POSTCOMPILE) diff --git a/gcc/rtl/config-lang.in b/gcc/rtl/config-lang.in new file mode 100644 index 0000000..3b101ce --- /dev/null +++ b/gcc/rtl/config-lang.in @@ -0,0 +1,36 @@ +# config-lang.in -- Top level configure fragment for RTL frontend. + +# Copyright (C) 2016 Free Software Foundation, Inc. + +# 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 +# . + +# Configure looks for the existence of this file to auto-config each language. +# We define several parameters used by configure: +# +# language - name of language as it would appear in $(LANGUAGES) +# compilers - value to add to $(COMPILERS) + +language="rtl" + +compilers="rtl1\$(exeext)" + +target_libs="" + +gtfiles="\$(srcdir)/rtl/rtl-frontend.c" + +# Do not build by default. +build_by_default="no" diff --git a/gcc/rtl/rtl-frontend.c b/gcc/rtl/rtl-frontend.c new file mode 100644 index 0000000..44ef921 --- /dev/null +++ b/gcc/rtl/rtl-frontend.c @@ -0,0 +1,419 @@ +/* rtl-frontend.c - Top-level of RTL frontend + Copyright (C) 2016 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "gimple-expr.h" +#include "diagnostic.h" +#include "opts.h" +#include "fold-const.h" +#include "gimplify.h" +#include "stor-layout.h" +#include "debug.h" +#include "convert.h" +#include "langhooks.h" +#include "langhooks-def.h" +#include "common/common-target.h" + +#include + +/* Language-dependent contents of a type. */ + +struct GTY(()) lang_type +{ + char dummy; +}; + +/* Language-dependent contents of a decl. */ + +struct GTY(()) lang_decl +{ + char dummy; +}; + +/* Language-dependent contents of an identifier. This must include a + tree_identifier. */ + +struct GTY(()) lang_identifier +{ + struct tree_identifier common; +}; + +/* The resulting tree type. */ + +union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), + chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) +lang_tree_node +{ + union tree_node GTY((tag ("0"), + desc ("tree_node_structure (&%h)"))) generic; + struct lang_identifier GTY((tag ("1"))) identifier; +}; + +/* We don't use language_function. */ + +struct GTY(()) language_function +{ + int dummy; +}; + +/* Language hooks. */ + +static bool +rtl_langhook_init (void) +{ + build_common_tree_nodes (false); + + /* I don't know why this has to be done explicitly. */ + void_list_node = build_tree_list (NULL_TREE, void_type_node); + + build_common_builtin_nodes (); + + /* The default precision for floating point numbers. This is used + for floating point constants with abstract type. This may + eventually be controllable by a command line option. */ + mpfr_set_default_prec (256); + + return true; +} + +/* The option mask. */ + +static unsigned int +rtl_langhook_option_lang_mask (void) +{ + return CL_Go; +} + +/* Initialize the options structure. */ + +static void +rtl_langhook_init_options_struct (struct gcc_options *opts) +{ + /* Go says that signed overflow is precisely defined. */ + opts->x_flag_wrapv = 1; + + /* We default to using strict aliasing, since Go pointers are safe. + This is turned off for code that imports the "unsafe" package, + because using unsafe.pointer violates C style aliasing + requirements. */ + opts->x_flag_strict_aliasing = 1; + + /* Default to avoiding range issues for complex multiply and + divide. */ + opts->x_flag_complex_method = 2; + + /* The builtin math functions should not set errno. */ + opts->x_flag_errno_math = 0; + opts->frontend_set_flag_errno_math = true; + + /* Exceptions are used to handle recovering from panics. */ + opts->x_flag_exceptions = 1; + opts->x_flag_non_call_exceptions = 1; + + /* We need to keep pointers live for the garbage collector. */ + opts->x_flag_keep_gc_roots_live = 1; + + /* Go programs expect runtime.Callers to work, and that uses + libbacktrace that uses debug info. Set the debug info level to 1 + by default. In post_options we will set the debug type if the + debug info level was not set back to 0 on the command line. */ + opts->x_debug_info_level = DINFO_LEVEL_TERSE; +} + +static void +rtl_langhook_parse_file (void) +{ +#if 0 + rtl_parse_input_files (in_fnames, num_in_fnames, flag_syntax_only, + rtl_require_return_statement); + + /* Final processing of globals and early debug info generation. */ + rtl_write_globals (); +#endif +} + +static tree +rtl_langhook_type_for_size (unsigned int bits, int unsignedp) +{ + tree type; + if (unsignedp) + { + if (bits == INT_TYPE_SIZE) + type = unsigned_type_node; + else if (bits == CHAR_TYPE_SIZE) + type = unsigned_char_type_node; + else if (bits == SHORT_TYPE_SIZE) + type = short_unsigned_type_node; + else if (bits == LONG_TYPE_SIZE) + type = long_unsigned_type_node; + else if (bits == LONG_LONG_TYPE_SIZE) + type = long_long_unsigned_type_node; + else + type = make_unsigned_type(bits); + } + else + { + if (bits == INT_TYPE_SIZE) + type = integer_type_node; + else if (bits == CHAR_TYPE_SIZE) + type = signed_char_type_node; + else if (bits == SHORT_TYPE_SIZE) + type = short_integer_type_node; + else if (bits == LONG_TYPE_SIZE) + type = long_integer_type_node; + else if (bits == LONG_LONG_TYPE_SIZE) + type = long_long_integer_type_node; + else + type = make_signed_type(bits); + } + return type; +} + +static tree +rtl_langhook_type_for_mode (machine_mode mode, int unsignedp) +{ + tree type; + /* Go has no vector types. Build them here. FIXME: It does not + make sense for the middle-end to ask the frontend for a type + which the frontend does not support. However, at least for now + it is required. See PR 46805. */ + if (VECTOR_MODE_P (mode)) + { + tree inner; + + inner = rtl_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp); + if (inner != NULL_TREE) + return build_vector_type_for_mode (inner, mode); + return NULL_TREE; + } + + // FIXME: This static_cast should be in machmode.h. + enum mode_class mc = static_cast(GET_MODE_CLASS(mode)); + if (mc == MODE_INT) + return rtl_langhook_type_for_size(GET_MODE_BITSIZE(mode), unsignedp); + else if (mc == MODE_FLOAT) + { + switch (GET_MODE_BITSIZE (mode)) + { + case 32: + return float_type_node; + case 64: + return double_type_node; + 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; + } + } + else if (mc == MODE_COMPLEX_FLOAT) + { + switch (GET_MODE_BITSIZE (mode)) + { + case 64: + return complex_float_type_node; + case 128: + return complex_double_type_node; + 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; + } + } + +#if HOST_BITS_PER_WIDE_INT >= 64 + /* The middle-end and some backends rely on TImode being supported + for 64-bit HWI. */ + if (mode == TImode) + { + type = build_nonstandard_integer_type (GET_MODE_BITSIZE (TImode), + unsignedp); + if (type && TYPE_MODE (type) == TImode) + return type; + } +#endif + return NULL_TREE; +} + +/* Record a builtin function. We just ignore builtin functions. */ + +static tree +rtl_langhook_builtin_function (tree decl) +{ + return decl; +} + +/* Return true if we are in the global binding level. */ + +static bool +rtl_langhook_global_bindings_p (void) +{ + return current_function_decl == NULL_TREE; +} + +/* Push a declaration into the current binding level. We can't + usefully implement this since we don't want to convert from tree + back to one of our internal data structures. I think the only way + this is used is to record a decl which is to be returned by + getdecls, and we could implement it for that purpose if + necessary. */ + +static tree +rtl_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + +/* This hook is used to get the current list of declarations as trees. + We don't support that; instead we use the write_globals hook. This + can't simply crash because it is called by -gstabs. */ + +static tree +rtl_langhook_getdecls (void) +{ + return NULL; +} + +/* Go specific gimplification. We need to gimplify + CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle + it. */ + +static int +rtl_langhook_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) +{ + if (TREE_CODE (*expr_p) == CALL_EXPR + && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE) + gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, + is_gimple_val, fb_rvalue); + return GS_UNHANDLED; +} + +#if 0 +/* Return a decl for the exception personality function. The function + itself is implemented in libgo/runtime/go-unwind.c. */ + +static tree +rtl_langhook_eh_personality (void) +{ + static tree personality_decl; + if (personality_decl == NULL_TREE) + { + personality_decl = build_personality_function ("gccgo"); + rtl_preserve_from_gc (personality_decl); + } + return personality_decl; +} +#endif + +/* Functions called directly by the generic backend. */ + +tree +convert (tree type, tree expr) +{ + if (type == error_mark_node + || expr == error_mark_node + || TREE_TYPE (expr) == error_mark_node) + return error_mark_node; + + if (type == TREE_TYPE (expr)) + return expr; + + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold_convert (type, expr); + + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case BOOLEAN_TYPE: + return fold_convert (type, expr); + case INTEGER_TYPE: + return fold (convert_to_integer (type, expr)); + case POINTER_TYPE: + return fold (convert_to_pointer (type, expr)); + case REAL_TYPE: + return fold (convert_to_real (type, expr)); + case COMPLEX_TYPE: + return fold (convert_to_complex (type, expr)); + default: + break; + } + + gcc_unreachable (); +} + +/* FIXME: This is a hack to preserve trees that we create from the + garbage collector. */ + +static GTY(()) tree rtl_gc_root; + +void +rtl_preserve_from_gc (tree t) +{ + rtl_gc_root = tree_cons (NULL_TREE, t, rtl_gc_root); +} + +/* Convert an identifier for use in an error message. */ + +const char * +rtl_localize_identifier (const char *ident) +{ + return identifier_to_locale (ident); +} + +#undef LANG_HOOKS_NAME +#undef LANG_HOOKS_INIT +#undef LANG_HOOKS_OPTION_LANG_MASK +#undef LANG_HOOKS_INIT_OPTIONS_STRUCT +//#undef LANG_HOOKS_HANDLE_OPTION +//#undef LANG_HOOKS_POST_OPTIONS +#undef LANG_HOOKS_PARSE_FILE +#undef LANG_HOOKS_TYPE_FOR_MODE +#undef LANG_HOOKS_TYPE_FOR_SIZE +#undef LANG_HOOKS_BUILTIN_FUNCTION +#undef LANG_HOOKS_GLOBAL_BINDINGS_P +#undef LANG_HOOKS_PUSHDECL +#undef LANG_HOOKS_GETDECLS +#undef LANG_HOOKS_GIMPLIFY_EXPR +//#undef LANG_HOOKS_EH_PERSONALITY + +#define LANG_HOOKS_NAME "GCC RTL frontend" +#define LANG_HOOKS_INIT rtl_langhook_init +#define LANG_HOOKS_OPTION_LANG_MASK rtl_langhook_option_lang_mask +#define LANG_HOOKS_INIT_OPTIONS_STRUCT rtl_langhook_init_options_struct +//#define LANG_HOOKS_HANDLE_OPTION rtl_langhook_handle_option +//#define LANG_HOOKS_POST_OPTIONS rtl_langhook_post_options +#define LANG_HOOKS_PARSE_FILE rtl_langhook_parse_file +#define LANG_HOOKS_TYPE_FOR_MODE rtl_langhook_type_for_mode +#define LANG_HOOKS_TYPE_FOR_SIZE rtl_langhook_type_for_size +#define LANG_HOOKS_BUILTIN_FUNCTION rtl_langhook_builtin_function +#define LANG_HOOKS_GLOBAL_BINDINGS_P rtl_langhook_global_bindings_p +#define LANG_HOOKS_PUSHDECL rtl_langhook_pushdecl +#define LANG_HOOKS_GETDECLS rtl_langhook_getdecls +#define LANG_HOOKS_GIMPLIFY_EXPR rtl_langhook_gimplify_expr +//#define LANG_HOOKS_EH_PERSONALITY rtl_langhook_eh_personality + +struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; + +#include "gt-rtl-rtl-frontend.h" +#include "gtype-rtl.h" -- 1.8.5.3