| /* go-backend.c -- Go frontend interface to gcc backend. |
| Copyright (C) 2010-2020 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 |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "target.h" |
| #include "tree.h" |
| #include "memmodel.h" |
| #include "tm_p.h" |
| #include "diagnostic.h" |
| #include "simple-object.h" |
| #include "stor-layout.h" |
| #include "intl.h" |
| #include "output.h" /* for assemble_string */ |
| #include "common/common-target.h" |
| #include "go-c.h" |
| |
| /* The segment name we pass to simple_object_start_read to find Go |
| export data. */ |
| |
| #ifndef GO_EXPORT_SEGMENT_NAME |
| #define GO_EXPORT_SEGMENT_NAME "__GNU_GO" |
| #endif |
| |
| /* The section name we use when reading and writing export data. */ |
| |
| #ifndef GO_EXPORT_SECTION_NAME |
| #define GO_EXPORT_SECTION_NAME ".go_export" |
| #endif |
| |
| #ifndef TARGET_AIX |
| #define TARGET_AIX 0 |
| #endif |
| |
| /* This file holds all the cases where the Go frontend needs |
| information from gcc's backend. */ |
| |
| /* Return whether or not GCC has reported any errors. */ |
| |
| bool |
| saw_errors (void) |
| { |
| return errorcount != 0 || sorrycount != 0; |
| } |
| |
| /* Return the alignment in bytes of a struct field of type T. */ |
| |
| unsigned int |
| go_field_alignment (tree t) |
| { |
| unsigned int v; |
| |
| v = TYPE_ALIGN (t); |
| |
| #ifdef BIGGEST_FIELD_ALIGNMENT |
| if (v > BIGGEST_FIELD_ALIGNMENT) |
| v = BIGGEST_FIELD_ALIGNMENT; |
| #endif |
| |
| #ifdef ADJUST_FIELD_ALIGN |
| v = ADJUST_FIELD_ALIGN (NULL_TREE, t, v); |
| #endif |
| |
| return v / BITS_PER_UNIT; |
| } |
| |
| /* This is called by the Go frontend proper if the unsafe package was |
| imported. When that happens we cannot do type-based alias |
| analysis. */ |
| |
| void |
| go_imported_unsafe (void) |
| { |
| flag_strict_aliasing = false; |
| TREE_OPTIMIZATION (optimization_default_node)->x_flag_strict_aliasing = false; |
| |
| /* Let the backend know that the options have changed. */ |
| targetm.override_options_after_change (); |
| } |
| |
| /* This is called by the Go frontend proper to add data to the |
| section containing Go export data. */ |
| |
| void |
| go_write_export_data (const char *bytes, unsigned int size) |
| { |
| static section* sec; |
| |
| if (sec == NULL) |
| { |
| gcc_assert (targetm_common.have_named_sections); |
| sec = get_section (GO_EXPORT_SECTION_NAME, |
| TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, |
| NULL); |
| } |
| |
| switch_to_section (sec); |
| assemble_string (bytes, size); |
| } |
| |
| /* The go_read_export_data function is called by the Go frontend |
| proper to read Go export data from an object file. FD is a file |
| descriptor open for reading. OFFSET is the offset within the file |
| where the object file starts; this will be 0 except when reading an |
| archive. On success this returns NULL and sets *PBUF to a buffer |
| allocated using malloc, of size *PLEN, holding the export data. If |
| the data is not found, this returns NULL and sets *PBUF to NULL and |
| *PLEN to 0. If some error occurs, this returns an error message |
| and sets *PERR to an errno value or 0 if there is no relevant |
| errno. */ |
| |
| const char * |
| go_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, |
| int *perr) |
| { |
| simple_object_read *sobj; |
| const char *errmsg; |
| off_t sec_offset; |
| off_t sec_length; |
| int found; |
| char *buf; |
| ssize_t c; |
| |
| *pbuf = NULL; |
| *plen = 0; |
| |
| sobj = simple_object_start_read (fd, offset, GO_EXPORT_SEGMENT_NAME, |
| &errmsg, perr); |
| if (sobj == NULL) |
| { |
| /* If we get an error here, just pretend that we didn't find any |
| export data. This is the right thing to do if the error is |
| that the file was not recognized as an object file. This |
| will ignore file I/O errors, but it's not too big a deal |
| because we will wind up giving some other error later. */ |
| return NULL; |
| } |
| |
| found = simple_object_find_section (sobj, GO_EXPORT_SECTION_NAME, |
| &sec_offset, &sec_length, |
| &errmsg, perr); |
| simple_object_release_read (sobj); |
| if (!found) |
| return errmsg; |
| |
| if (lseek (fd, offset + sec_offset, SEEK_SET) < 0) |
| { |
| *perr = errno; |
| return _("lseek failed while reading export data"); |
| } |
| |
| buf = XNEWVEC (char, sec_length); |
| if (buf == NULL) |
| { |
| *perr = errno; |
| return _("memory allocation failed while reading export data"); |
| } |
| |
| c = read (fd, buf, sec_length); |
| if (c < 0) |
| { |
| *perr = errno; |
| free (buf); |
| return _("read failed while reading export data"); |
| } |
| |
| if (c < sec_length) |
| { |
| free (buf); |
| return _("short read while reading export data"); |
| } |
| |
| *pbuf = buf; |
| *plen = sec_length; |
| |
| return NULL; |
| } |