From b13c0682ab290166a4a4c25513fec96beab5e211 Mon Sep 17 00:00:00 2001 From: Rishi Raj Date: Thu, 6 Jul 2023 18:43:51 +0530 Subject: lto: Bypass assembler when generating LTO object files. This patch applies Jan Hubicka previous patch on current sources. Now compiler is able to produce object files without assembler although a lot of things are missing such as __lto_slim symbol, debug symbols etc. They will be added in future patches. To test this current patch, use these command below. 1) ./xgcc -B ./ -O3 a.c -flto -S -fbypass-asm=crtbegin.o -o a.o 2) ./xgcc -B ./ -O2 a.o -flto 3) ./a.out We are currntly working with elf-only support (mach-o, coff, xcoff etc will be dealt later) so this will only work on a linux machine. I have tested this on my machine ( Arch linux, Machine: Advanced Micro Devices X86-64) and all LTO test cases passed as expected. gcc/ChangeLog: * Makefile.in: * common.opt: * langhooks.cc (lhd_begin_section): (lhd_append_data): (lhd_end_section): * lto/lto-object.cc: Moved to... * lto-object.cc: ...here. * lto-streamer.h (struct lto_section_slot): (struct lto_section_list): (struct lto_file): (lto_obj_file_open): (lto_obj_file_close): (lto_obj_build_section_table): (lto_obj_create_section_hash_table): (lto_obj_begin_section): (lto_obj_append_data): (lto_obj_end_section): (lto_set_current_out_file): (lto_get_current_out_file): * toplev.cc (compile_file): (lang_dependent_init): gcc/lto/ChangeLog: * Make-lang.in: * lto-common.cc (lto_file_read): * lto-lang.cc: * lto.h (struct lto_file): (lto_obj_file_open): (lto_obj_file_close): (struct lto_section_list): (lto_obj_build_section_table): (lto_obj_create_section_hash_table): (lto_obj_begin_section): (lto_obj_append_data): (lto_obj_end_section): (lto_set_current_out_file): (lto_get_current_out_file): (struct lto_section_slot): Signed-off-by: Rishi Raj --- gcc/Makefile.in | 1 + gcc/common.opt | 3 + gcc/langhooks.cc | 29 +++- gcc/lto-object.cc | 389 ++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/lto-streamer.h | 35 +++++ gcc/lto/Make-lang.in | 4 +- gcc/lto/lto-common.cc | 3 +- gcc/lto/lto-lang.cc | 1 + gcc/lto/lto-object.cc | 374 ------------------------------------------------ gcc/lto/lto.h | 38 ----- gcc/toplev.cc | 19 ++- 11 files changed, 477 insertions(+), 419 deletions(-) create mode 100644 gcc/lto-object.cc delete mode 100644 gcc/lto/lto-object.cc (limited to 'gcc') diff --git a/gcc/Makefile.in b/gcc/Makefile.in index c478ec8..c9ae222 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1560,6 +1560,7 @@ OBJS = \ lto-section-out.o \ lto-opts.o \ lto-compress.o \ + lto-object.o \ mcf.o \ mode-switching.o \ modulo-sched.o \ diff --git a/gcc/common.opt b/gcc/common.opt index 25f650e..ba7a18e 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1169,6 +1169,9 @@ fbtr-bb-exclusive Common Ignore Does nothing. Preserved for backward compatibility. +fbypass-asm= +Common Joined Var(flag_bypass_asm) + fcallgraph-info Common RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO); Output callgraph information on a per-file basis. diff --git a/gcc/langhooks.cc b/gcc/langhooks.cc index 9a1a9ec..a76ed97 100644 --- a/gcc/langhooks.cc +++ b/gcc/langhooks.cc @@ -38,6 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "cgraph.h" #include "debug.h" +#include "function.h" +#include "basic-block.h" +#include "gimple.h" +#include "lto-streamer.h" /* Do nothing; in many cases the default hook. */ @@ -817,6 +821,19 @@ lhd_begin_section (const char *name) { section *section; + if (flag_bypass_asm) + { + static int initialized = false; + if (!initialized) + { + gcc_assert (asm_out_file == NULL); + lto_set_current_out_file (lto_obj_file_open (asm_file_name, true)); + initialized = true; + } + lto_obj_begin_section (name); + return; + } + /* Save the old section so we can restore it in lto_end_asm_section. */ gcc_assert (!saved_section); saved_section = in_section; @@ -833,8 +850,13 @@ lhd_begin_section (const char *name) implementation just calls assemble_string. */ void -lhd_append_data (const void *data, size_t len, void *) +lhd_append_data (const void *data, size_t len, void *v) { + if (flag_bypass_asm) + { + lto_obj_append_data (data, len, v); + return; + } if (data) { timevar_push (TV_IPA_LTO_OUTPUT); @@ -851,6 +873,11 @@ lhd_append_data (const void *data, size_t len, void *) void lhd_end_section (void) { + if (flag_bypass_asm) + { + lto_obj_end_section (); + return; + } if (saved_section) { switch_to_section (saved_section); diff --git a/gcc/lto-object.cc b/gcc/lto-object.cc new file mode 100644 index 0000000..cb1c3a6 --- /dev/null +++ b/gcc/lto-object.cc @@ -0,0 +1,389 @@ +/* LTO routines to use object files. + Copyright (C) 2010-2023 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +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 "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" +#include "function.h" +#include "gimple.h" +#include "diagnostic-core.h" +#include "tm.h" +#include "lto-streamer.h" +#include "lto-section-names.h" +#include "simple-object.h" + +/* An LTO file wrapped around an simple_object. */ + +struct lto_simple_object +{ + /* The base information. */ + lto_file base; + + /* The system file descriptor. */ + int fd; + + /* The simple_object if we are reading the file. */ + simple_object_read *sobj_r; + + /* The simple_object if we are writing the file. */ + simple_object_write *sobj_w; + + /* The currently active section. */ + simple_object_write_section *section; +}; + +/* Saved simple_object attributes. FIXME: Once set, this is never + cleared. */ + +static simple_object_attributes *saved_attributes; + +/* Initialize FILE, an LTO file object for FILENAME. */ + +static void +lto_file_init (lto_file *file, const char *filename, off_t offset) +{ + file->filename = filename; + file->offset = offset; +} + +/* Open the file FILENAME. It WRITABLE is true, the file is opened + for write and, if necessary, created. Otherwise, the file is + opened for reading. Returns the opened file. */ + +lto_file * +lto_obj_file_open (const char *filename, bool writable) +{ + const char *offset_p; + long loffset; + int consumed; + char *fname; + off_t offset; + struct lto_simple_object *lo; + const char *errmsg; + int err; + + offset_p = strrchr (filename, '@'); + if (offset_p != NULL + && offset_p != filename + && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1 + && strlen (offset_p) == (unsigned int) consumed) + { + fname = XNEWVEC (char, offset_p - filename + 1); + memcpy (fname, filename, offset_p - filename); + fname[offset_p - filename] = '\0'; + offset = (off_t) loffset; + } + else + { + fname = xstrdup (filename); + offset = 0; + } + + lo = XCNEW (struct lto_simple_object); + lto_file_init ((lto_file *) lo, fname, offset); + + lo->fd = open (fname, + (writable + ? O_WRONLY | O_CREAT | O_BINARY + : O_RDONLY | O_BINARY), + 0666); + if (lo->fd == -1) + fatal_error (input_location, "open %s failed: %s", fname, xstrerror (errno)); + + if (!writable) + { + simple_object_attributes *attrs; + + lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME, + &errmsg, &err); + if (lo->sobj_r == NULL) + goto fail_errmsg; + + attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err); + if (attrs == NULL) + goto fail_errmsg; + + if (saved_attributes == NULL) + saved_attributes = attrs; + else + { + errmsg = simple_object_attributes_merge (saved_attributes, attrs, + &err); + if (errmsg != NULL) + { + free (attrs); + goto fail_errmsg; + } + } + } + else + { + if (!saved_attributes) + { + lto_file *tmp = lto_obj_file_open (flag_bypass_asm, false); + if (!tmp) + goto fail; + lto_obj_file_close (tmp); + } + lo->sobj_w = simple_object_start_write (saved_attributes, + LTO_SEGMENT_NAME, + &errmsg, &err); + if (lo->sobj_w == NULL) + goto fail_errmsg; + } + + return &lo->base; + +fail_errmsg: + if (err == 0) + error ("%s: %s", fname, errmsg); + else + error ("%s: %s: %s", fname, errmsg, xstrerror (err)); + +fail: + if (lo->fd != -1) + lto_obj_file_close ((lto_file *) lo); + free (lo); + return NULL; +} + + +/* Close FILE. If FILE was opened for writing, it is written out + now. */ + +void +lto_obj_file_close (lto_file *file) +{ + struct lto_simple_object *lo = (struct lto_simple_object *) file; + + if (lo->sobj_r != NULL) + simple_object_release_read (lo->sobj_r); + else if (lo->sobj_w != NULL) + { + const char *errmsg; + int err; + + gcc_assert (lo->base.offset == 0); + + errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err); + if (errmsg != NULL) + { + if (err == 0) + fatal_error (input_location, "%s", errmsg); + else + fatal_error (input_location, "%s: %s", errmsg, xstrerror (err)); + } + + simple_object_release_write (lo->sobj_w); + } + + if (lo->fd != -1) + { + if (close (lo->fd) < 0) + fatal_error (input_location, "close: %s", xstrerror (errno)); + } +} + +/* This is passed to lto_obj_add_section. */ + +struct lto_obj_add_section_data +{ + /* The hash table of sections. */ + htab_t section_hash_table; + /* The offset of this file. */ + off_t base_offset; + /* List in linker order */ + struct lto_section_list *list; +}; + +/* This is called for each section in the file. */ + +static int +lto_obj_add_section (void *data, const char *name, off_t offset, + off_t length) +{ + struct lto_obj_add_section_data *loasd = + (struct lto_obj_add_section_data *) data; + htab_t section_hash_table = (htab_t) loasd->section_hash_table; + char *new_name; + struct lto_section_slot s_slot; + void **slot; + struct lto_section_list *list = loasd->list; + + if (strncmp (name, section_name_prefix, strlen (section_name_prefix))) + return 1; + + new_name = xstrdup (name); + s_slot.name = new_name; + slot = htab_find_slot (section_hash_table, &s_slot, INSERT); + if (*slot == NULL) + { + struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot); + + new_slot->name = new_name; + new_slot->start = loasd->base_offset + offset; + new_slot->len = length; + *slot = new_slot; + + if (list != NULL) + { + if (!list->first) + list->first = new_slot; + if (list->last) + list->last->next = new_slot; + list->last = new_slot; + } + } + else + { + error ("two or more sections for %s", new_name); + return 0; + } + + return 1; +} + +/* Build a hash table whose key is the section name and whose data is + the start and size of each section in the .o file. */ + +htab_t +lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list, + htab_t section_hash_table) +{ + struct lto_simple_object *lo = (struct lto_simple_object *) lto_file; + + struct lto_obj_add_section_data loasd; + const char *errmsg; + int err; + + + gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL); + loasd.section_hash_table = section_hash_table; + loasd.base_offset = lo->base.offset; + loasd.list = list; + errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section, + &loasd, &err); + if (errmsg != NULL) + { + if (err == 0) + error ("%s", errmsg); + else + error ("%s: %s", errmsg, xstrerror (err)); + htab_delete (section_hash_table); + return NULL; + } + + return section_hash_table; +} + +/* The current output file. */ + +static lto_file *current_out_file; + +/* Set the current output file. Return the old one. */ + +lto_file * +lto_set_current_out_file (lto_file *file) +{ + lto_file *old_file; + + old_file = current_out_file; + current_out_file = file; + return old_file; +} + +/* Return the current output file. */ + +lto_file * +lto_get_current_out_file (void) +{ + return current_out_file; +} + +/* Begin writing a new section named NAME in the current output + file. */ + +void +lto_obj_begin_section (const char *name) +{ + struct lto_simple_object *lo; + int align; + const char *errmsg; + int err; + + lo = (struct lto_simple_object *) current_out_file; + gcc_assert (lo != NULL + && lo->sobj_r == NULL + && lo->sobj_w != NULL + && lo->section == NULL); + + align = ceil_log2 (POINTER_SIZE_UNITS); + lo->section = simple_object_write_create_section (lo->sobj_w, name, align, + &errmsg, &err); + if (lo->section == NULL) + { + if (err == 0) + fatal_error (input_location, "%s", errmsg); + else + fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); + } +} + +/* Add data to a section. BLOCK is a pointer to memory containing + DATA. */ + +void +lto_obj_append_data (const void *data, size_t len, void *) +{ + struct lto_simple_object *lo; + const char *errmsg; + int err; + + lo = (struct lto_simple_object *) current_out_file; + gcc_assert (lo != NULL && lo->section != NULL); + + errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len, + 1, &err); + if (errmsg != NULL) + { + if (err == 0) + fatal_error (input_location, "%s", errmsg); + else + fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); + } +} + +/* Stop writing to the current output section. */ + +void +lto_obj_end_section (void) +{ + struct lto_simple_object *lo; + + lo = (struct lto_simple_object *) current_out_file; + gcc_assert (lo != NULL && lo->section != NULL); + lo->section = NULL; +} diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 0556b34..0c8e5d6 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -764,6 +764,30 @@ public: lto_location_cache location_cache; }; +/* Hash table entry to hold the start offset and length of an LTO + section in a .o file. */ +struct lto_section_slot +{ + const char *name; + intptr_t start; + size_t len; + struct lto_section_slot *next; +}; + +/* A list of section slots */ +struct lto_section_list +{ + struct lto_section_slot *first, *last; +}; + +/* A file. */ +struct lto_file +{ + /* The name of the file. */ + const char *filename; + /* The offset for the object inside an ar archive file (or zero). */ + off_t offset; +}; /* In lto-section-in.cc */ extern class lto_input_block * lto_create_simple_input_block ( @@ -903,6 +927,17 @@ void lto_output_location_and_block (struct output_block *, struct bitpack_d *, void lto_output_init_mode_table (void); void lto_prepare_function_for_streaming (cgraph_node *); +/* In lto-elf.c or lto-coff.c */ +extern lto_file *lto_obj_file_open (const char *filename, bool writable); +extern void lto_obj_file_close (lto_file *file); +struct lto_section_list; +extern htab_t lto_obj_build_section_table (lto_file *file, struct lto_section_list *list, htab_t section_hash_table); +extern htab_t lto_obj_create_section_hash_table (void); +extern void lto_obj_begin_section (const char *name); +extern void lto_obj_append_data (const void *data, size_t len, void *block); +extern void lto_obj_end_section (void); +extern lto_file *lto_set_current_out_file (lto_file *file); +extern lto_file *lto_get_current_out_file (void); /* In lto-cgraph.cc */ extern bool asm_nodes_output; diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in index 98aa9f4..70144ce 100644 --- a/gcc/lto/Make-lang.in +++ b/gcc/lto/Make-lang.in @@ -24,9 +24,9 @@ LTO_EXE = lto1$(exeext) LTO_DUMP_EXE = lto-dump$(exeext) LTO_DUMP_INSTALL_NAME := $(shell echo lto-dump|sed '$(program_transform_name)') # The LTO-specific object files inclued in $(LTO_EXE). -LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o +LTO_OBJS = lto/lto-lang.o lto/lto.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o lto_OBJS = $(LTO_OBJS) -LTO_DUMP_OBJS = lto/lto-lang.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-dump.o lto/lto-common.o +LTO_DUMP_OBJS = lto/lto-lang.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-dump.o lto/lto-common.o lto_dump_OBJS = $(LTO_DUMP_OBJS) # this is only useful in a LTO bootstrap, but this does not work right diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc index 703e665..1ec488a 100644 --- a/gcc/lto/lto-common.cc +++ b/gcc/lto/lto-common.cc @@ -2326,7 +2326,8 @@ lto_file_read (lto_file *file, FILE *resolution_file, int *count) struct lto_section_list section_list; memset (§ion_list, 0, sizeof (struct lto_section_list)); - section_hash_table = lto_obj_build_section_table (file, §ion_list); + section_hash_table = lto_obj_create_section_hash_table (); + section_hash_table = lto_obj_build_section_table (file, §ion_list, section_hash_table); /* Dump the details of LTO objects. */ if (flag_lto_dump_objects) diff --git a/gcc/lto/lto-lang.cc b/gcc/lto/lto-lang.cc index 14d419c..cf33bf1 100644 --- a/gcc/lto/lto-lang.cc +++ b/gcc/lto/lto-lang.cc @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "lto-tree.h" #include "lto.h" #include "lto-common.h" +#include "lto-streamer.h" #include "stringpool.h" #include "attribs.h" diff --git a/gcc/lto/lto-object.cc b/gcc/lto/lto-object.cc deleted file mode 100644 index 965d31e..0000000 --- a/gcc/lto/lto-object.cc +++ /dev/null @@ -1,374 +0,0 @@ -/* LTO routines to use object files. - Copyright (C) 2010-2023 Free Software Foundation, Inc. - Written by Ian Lance Taylor, Google. - -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 "tm.h" -#include "diagnostic-core.h" -#include "lto.h" -#include "lto-section-names.h" -#include "simple-object.h" - -/* An LTO file wrapped around an simple_object. */ - -struct lto_simple_object -{ - /* The base information. */ - lto_file base; - - /* The system file descriptor. */ - int fd; - - /* The simple_object if we are reading the file. */ - simple_object_read *sobj_r; - - /* The simple_object if we are writing the file. */ - simple_object_write *sobj_w; - - /* The currently active section. */ - simple_object_write_section *section; -}; - -/* Saved simple_object attributes. FIXME: Once set, this is never - cleared. */ - -static simple_object_attributes *saved_attributes; - -/* Initialize FILE, an LTO file object for FILENAME. */ - -static void -lto_file_init (lto_file *file, const char *filename, off_t offset) -{ - file->filename = filename; - file->offset = offset; -} - -/* Open the file FILENAME. It WRITABLE is true, the file is opened - for write and, if necessary, created. Otherwise, the file is - opened for reading. Returns the opened file. */ - -lto_file * -lto_obj_file_open (const char *filename, bool writable) -{ - const char *offset_p; - long loffset; - int consumed; - char *fname; - off_t offset; - struct lto_simple_object *lo; - const char *errmsg; - int err; - - offset_p = strrchr (filename, '@'); - if (offset_p != NULL - && offset_p != filename - && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1 - && strlen (offset_p) == (unsigned int) consumed) - { - fname = XNEWVEC (char, offset_p - filename + 1); - memcpy (fname, filename, offset_p - filename); - fname[offset_p - filename] = '\0'; - offset = (off_t) loffset; - } - else - { - fname = xstrdup (filename); - offset = 0; - } - - lo = XCNEW (struct lto_simple_object); - lto_file_init ((lto_file *) lo, fname, offset); - - lo->fd = open (fname, - (writable - ? O_WRONLY | O_CREAT | O_BINARY - : O_RDONLY | O_BINARY), - 0666); - if (lo->fd == -1) - fatal_error (input_location, "open %s failed: %s", fname, xstrerror (errno)); - - if (!writable) - { - simple_object_attributes *attrs; - - lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME, - &errmsg, &err); - if (lo->sobj_r == NULL) - goto fail_errmsg; - - attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err); - if (attrs == NULL) - goto fail_errmsg; - - if (saved_attributes == NULL) - saved_attributes = attrs; - else - { - errmsg = simple_object_attributes_merge (saved_attributes, attrs, - &err); - if (errmsg != NULL) - { - free (attrs); - goto fail_errmsg; - } - } - } - else - { - gcc_assert (saved_attributes != NULL); - lo->sobj_w = simple_object_start_write (saved_attributes, - LTO_SEGMENT_NAME, - &errmsg, &err); - if (lo->sobj_w == NULL) - goto fail_errmsg; - } - - return &lo->base; - -fail_errmsg: - if (err == 0) - error ("%s: %s", fname, errmsg); - else - error ("%s: %s: %s", fname, errmsg, xstrerror (err)); - - if (lo->fd != -1) - lto_obj_file_close ((lto_file *) lo); - free (lo); - return NULL; -} - - -/* Close FILE. If FILE was opened for writing, it is written out - now. */ - -void -lto_obj_file_close (lto_file *file) -{ - struct lto_simple_object *lo = (struct lto_simple_object *) file; - - if (lo->sobj_r != NULL) - simple_object_release_read (lo->sobj_r); - else if (lo->sobj_w != NULL) - { - const char *errmsg; - int err; - - gcc_assert (lo->base.offset == 0); - - errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err); - if (errmsg != NULL) - { - if (err == 0) - fatal_error (input_location, "%s", errmsg); - else - fatal_error (input_location, "%s: %s", errmsg, xstrerror (err)); - } - - simple_object_release_write (lo->sobj_w); - } - - if (lo->fd != -1) - { - if (close (lo->fd) < 0) - fatal_error (input_location, "close: %s", xstrerror (errno)); - } -} - -/* This is passed to lto_obj_add_section. */ - -struct lto_obj_add_section_data -{ - /* The hash table of sections. */ - htab_t section_hash_table; - /* The offset of this file. */ - off_t base_offset; - /* List in linker order */ - struct lto_section_list *list; -}; - -/* This is called for each section in the file. */ - -static int -lto_obj_add_section (void *data, const char *name, off_t offset, - off_t length) -{ - struct lto_obj_add_section_data *loasd = - (struct lto_obj_add_section_data *) data; - htab_t section_hash_table = (htab_t) loasd->section_hash_table; - char *new_name; - struct lto_section_slot s_slot; - void **slot; - struct lto_section_list *list = loasd->list; - - if (strncmp (name, section_name_prefix, strlen (section_name_prefix))) - return 1; - - new_name = xstrdup (name); - s_slot.name = new_name; - slot = htab_find_slot (section_hash_table, &s_slot, INSERT); - if (*slot == NULL) - { - struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot); - - new_slot->name = new_name; - new_slot->start = loasd->base_offset + offset; - new_slot->len = length; - *slot = new_slot; - - if (list != NULL) - { - if (!list->first) - list->first = new_slot; - if (list->last) - list->last->next = new_slot; - list->last = new_slot; - } - } - else - { - error ("two or more sections for %s", new_name); - return 0; - } - - return 1; -} - -/* Build a hash table whose key is the section name and whose data is - the start and size of each section in the .o file. */ - -htab_t -lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list) -{ - struct lto_simple_object *lo = (struct lto_simple_object *) lto_file; - htab_t section_hash_table; - struct lto_obj_add_section_data loasd; - const char *errmsg; - int err; - - section_hash_table = lto_obj_create_section_hash_table (); - - gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL); - loasd.section_hash_table = section_hash_table; - loasd.base_offset = lo->base.offset; - loasd.list = list; - errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section, - &loasd, &err); - if (errmsg != NULL) - { - if (err == 0) - error ("%s", errmsg); - else - error ("%s: %s", errmsg, xstrerror (err)); - htab_delete (section_hash_table); - return NULL; - } - - return section_hash_table; -} - -/* The current output file. */ - -static lto_file *current_out_file; - -/* Set the current output file. Return the old one. */ - -lto_file * -lto_set_current_out_file (lto_file *file) -{ - lto_file *old_file; - - old_file = current_out_file; - current_out_file = file; - return old_file; -} - -/* Return the current output file. */ - -lto_file * -lto_get_current_out_file (void) -{ - return current_out_file; -} - -/* Begin writing a new section named NAME in the current output - file. */ - -void -lto_obj_begin_section (const char *name) -{ - struct lto_simple_object *lo; - int align; - const char *errmsg; - int err; - - lo = (struct lto_simple_object *) current_out_file; - gcc_assert (lo != NULL - && lo->sobj_r == NULL - && lo->sobj_w != NULL - && lo->section == NULL); - - align = ceil_log2 (POINTER_SIZE_UNITS); - lo->section = simple_object_write_create_section (lo->sobj_w, name, align, - &errmsg, &err); - if (lo->section == NULL) - { - if (err == 0) - fatal_error (input_location, "%s", errmsg); - else - fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); - } -} - -/* Add data to a section. BLOCK is a pointer to memory containing - DATA. */ - -void -lto_obj_append_data (const void *data, size_t len, void *) -{ - struct lto_simple_object *lo; - const char *errmsg; - int err; - - lo = (struct lto_simple_object *) current_out_file; - gcc_assert (lo != NULL && lo->section != NULL); - - errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len, - 1, &err); - if (errmsg != NULL) - { - if (err == 0) - fatal_error (input_location, "%s", errmsg); - else - fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); - } -} - -/* Stop writing to the current output section. */ - -void -lto_obj_end_section (void) -{ - struct lto_simple_object *lo; - - lo = (struct lto_simple_object *) current_out_file; - gcc_assert (lo != NULL && lo->section != NULL); - lo->section = NULL; -} diff --git a/gcc/lto/lto.h b/gcc/lto/lto.h index 810d662..4c3c84b 100644 --- a/gcc/lto/lto.h +++ b/gcc/lto/lto.h @@ -21,16 +21,6 @@ along with GCC; see the file COPYING3. If not see #ifndef LTO_H #define LTO_H - -/* A file. */ -struct lto_file -{ - /* The name of the file. */ - const char *filename; - /* The offset for the object inside an ar archive file (or zero). */ - off_t offset; -}; - /* In lto-lang.cc */ extern const char *resolution_file_name; @@ -39,36 +29,8 @@ extern tree lto_eh_personality (void); extern void lto_main (void); extern void lto_read_all_file_options (void); -/* In lto-elf.c or lto-coff.c */ -extern lto_file *lto_obj_file_open (const char *filename, bool writable); -extern void lto_obj_file_close (lto_file *file); -struct lto_section_list; -extern htab_t lto_obj_build_section_table (lto_file *file, struct lto_section_list *list); -extern htab_t lto_obj_create_section_hash_table (void); -extern void lto_obj_begin_section (const char *name); -extern void lto_obj_append_data (const void *data, size_t len, void *block); -extern void lto_obj_end_section (void); -extern lto_file *lto_set_current_out_file (lto_file *file); -extern lto_file *lto_get_current_out_file (void); - extern int lto_link_dump_id, decl_merge_dump_id, partition_dump_id; -/* Hash table entry to hold the start offset and length of an LTO - section in a .o file. */ -struct lto_section_slot -{ - const char *name; - intptr_t start; - size_t len; - struct lto_section_slot *next; -}; - -/* A list of section slots */ -struct lto_section_list -{ - struct lto_section_slot *first, *last; -}; - extern unsigned int lto_option_lang_mask (void); #endif /* LTO_H */ diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 6c1a6f4..fec4163 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-modref.h" #include "ipa-param-manipulation.h" #include "dbgcnt.h" +#include "lto-streamer.h" #include "selftest.h" @@ -539,6 +540,12 @@ compile_file (void) even when user did not ask for it. */ if (flag_generate_lto && !flag_fat_lto_objects) { + if (flag_bypass_asm) + { + /* TODO */ + } + else + { #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE, "__gnu_lto_slim", HOST_WIDE_INT_1U, 8); @@ -550,12 +557,13 @@ compile_file (void) HOST_WIDE_INT_1U, HOST_WIDE_INT_1U); #endif + } } /* Attach a special .ident directive to the end of the file to identify the version of GCC which compiled this code. The format of the .ident string is patterned after the ones produced by native SVR4 compilers. */ - if (!flag_no_ident) + if (!flag_no_ident && !flag_bypass_asm) { const char *pkg_version = "(GNU) "; char *ident_str; @@ -577,7 +585,11 @@ compile_file (void) /* This must be at the end. Some target ports emit end of file directives into the assembly file here, and hence we cannot output anything to the assembly file after this point. */ - targetm.asm_out.file_end (); + + if (flag_bypass_asm) + lto_obj_file_close (lto_get_current_out_file ()); + else + targetm.asm_out.file_end (); timevar_stop (TV_PHASE_LATE_ASM); } @@ -1819,7 +1831,8 @@ lang_dependent_init (const char *name) if (!flag_wpa) { - init_asm_output (name); + if (!flag_bypass_asm) + init_asm_output (name); if (!flag_generate_lto && !flag_compare_debug) { -- cgit v1.1