195 lines
5.0 KiB
C
195 lines
5.0 KiB
C
/* go-backend.c -- Go frontend interface to gcc backend.
|
|
Copyright (C) 2010-2021 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;
|
|
}
|