From: Kyrylo Tkachov <[email protected]>
Let genattrtab write multiple attribute outputs, following genemit and
genrecog. Reuse --with-insnemit-partitions and make -A repeatable. Register
the -A, -D, and -L outputs through the common gensupport machinery. This gives
all output roles one validation, open, selection, and close lifecycle. Also
distribute the fixed delay and length functions. Keep DFA and latency
functions in their existing single files.
choose_output places each function in the shortest partition so far, which
only balances well if the large functions are placed early. Attribute
functions differ in size by two orders of magnitude, so an arbitrary order
lets a late large function land on an already full partition. Sort the
functions by the amount of text write_attr_get will produce, largest first.
For a derived attribute that amount is the length of its lookup table, and
otherwise the number of case labels that survive find_most_used.
The functions refer to one another through insn-attr.h and
insn-attr-common.h, so generated headers do not change. With one -A option
the delay and latency outputs are byte-identical to the previous generator.
The attribute output holds the same lines at the same total size, reordered,
because the sort applies at any partition count.
On AArch64 with eight partitions the sorted order reduces the spread between
the largest and smallest partition from 5.9x to 2.3x. The largest partition
is then within 0.1% of the size that no assignment can beat, since one
attribute function alone accounts for that much of the total. The largest
attribute part is about 83% smaller than the original single source, and the
slowest attribute object compiles about 76% faster. Native AArch64 and
RISC-V cross all-gcc builds pass.
Bootstrapped on aarch64-none-linux-gnu. Ok for trunk?
gcc/ChangeLog:
* Makefile.in (INSNATTRTAB_SPLITS_SEQ, INSNATTRTAB_SEQ_SRC)
(INSNATTRTAB_SEQ_TMP, INSNATTRTAB_SEQ_O): New variables.
(OBJS): Replace insn-attrtab.o with $(INSNATTRTAB_SEQ_O).
(MOSTLYCLEANFILES): Add $(INSNATTRTAB_SEQ_SRC), retaining the legacy
unnumbered source for cleanup.
(.PRECIOUS): Use $(INSNATTRTAB_SEQ_SRC).
(s-attrtab): Generate and move numbered attribute files. Stop when a
move fails.
* configure.ac (--with-insnemit-partitions): Document all generators
which use the option.
* configure: Regenerate.
* genattrtab.cc (attr_file_name, attr_file): Remove.
(output_files): New variable.
(dfa_file_name, latency_file_name): Retain output names.
(make_automaton_attrs): Write to the first attribute partition.
(handle_arg): Register repeatable attribute outputs.
(attr_output_size, cmp_attr_output_size): New functions.
(main): Register fixed outputs and use the common output helpers.
Distribute attribute, delay, and length functions, largest first.
* final.cc (length_unit_log): Update comment for partitioned output.
* config/arc/arc-protos.h (regno_clobbered_p): Likewise.
* config/ia64/ia64.cc (bundling): Likewise.
* config/ia64/t-ia64 (insn-attrtab.o-warn): Replace with per-partition
warning variables.
* config/sh/sh.h (code_for_indirect_jump_scratch): Update comment for
partitioned output.
contrib/ChangeLog:
* filter-clang-warnings.py (skip_warning): Match numbered attribute
files.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
contrib/filter-clang-warnings.py | 2 +-
gcc/Makefile.in | 32 +++++--
gcc/config/arc/arc-protos.h | 3 +-
gcc/config/ia64/ia64.cc | 4 +-
gcc/config/ia64/t-ia64 | 3 +-
gcc/config/sh/sh.h | 5 +-
gcc/configure | 11 +--
gcc/configure.ac | 6 +-
gcc/final.cc | 2 +-
gcc/genattrtab.cc | 150 ++++++++++++++++++++-----------
10 files changed, 143 insertions(+), 75 deletions(-)
diff --git a/contrib/filter-clang-warnings.py b/contrib/filter-clang-warnings.py
index 9de005990b5..ba2fa532f82 100755
--- a/contrib/filter-clang-warnings.py
+++ b/contrib/filter-clang-warnings.py
@@ -56,7 +56,7 @@ def skip_warning(filename, message):
'ipa-strub.cc': ['-Wunused-but-set-variable'],
'insn-modes.cc': ['-Wshift-count-overflow'],
'insn-emit': ['-Wtautological-compare'],
- 'insn-attrtab.cc': ['-Wparentheses-equality'],
+ 'insn-attrtab': ['-Wparentheses-equality'],
'omp-builtins.def': ['-Wc++11-narrowing'],
'wide-int.h': ['-Wnontrivial-memcall'],
'i386.md': ['-Wparentheses-equality', '-Wtautological-compare',
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ee2f9022eab..19957477e5b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -241,6 +241,14 @@ INSNRECOG_SEQ_SRC = $(patsubst %, insn-recog-%.cc, $(INSNRECOG_SPLITS_SEQ))
INSNRECOG_SEQ_TMP = $(patsubst %, tmp-recog-%.cc, $(INSNRECOG_SPLITS_SEQ))
INSNRECOG_SEQ_O = $(patsubst %, insn-recog-%.o, $(INSNRECOG_SPLITS_SEQ))
+# Re-use the split number for insn-attrtab as well.
+INSNATTRTAB_SPLITS_SEQ = $(wordlist 1,$(NUM_INSNEMIT_SPLITS),$(one_to_9999))
+INSNATTRTAB_SEQ_SRC = $(patsubst %, insn-attrtab-%.cc, \
+ $(INSNATTRTAB_SPLITS_SEQ))
+INSNATTRTAB_SEQ_TMP = $(patsubst %, tmp-attrtab-%.cc, \
+ $(INSNATTRTAB_SPLITS_SEQ))
+INSNATTRTAB_SEQ_O = $(patsubst %, insn-attrtab-%.o, $(INSNATTRTAB_SPLITS_SEQ))
+
# These files are to have specific diagnostics suppressed, or are not to
# be subject to -Werror:
# flex output may yield harmless "no previous prototype" warnings
@@ -1405,7 +1413,7 @@ OBJS = \
$(GIMPLE_MATCH_PD_SEQ_O) \
gimple-match-exports.o \
$(GENERIC_MATCH_PD_SEQ_O) \
- insn-attrtab.o \
+ $(INSNATTRTAB_SEQ_O) \
insn-automata.o \
insn-dfatab.o \
$(INSNEMIT_SEQ_O) \
@@ -1986,8 +1994,10 @@ FULL_DRIVER_NAME=$(target_noncanonical)-gcc-$(version)$(exeext)
MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
insn-output.cc $(INSNRECOG_SEQ_SRC) insn-recog.h \
$(INSNEMIT_SEQ_SRC) insn-extract.cc insn-peep.cc \
- insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \
- insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc insn-constants.h \
+ insn-attr.h insn-attr-common.h $(INSNATTRTAB_SEQ_SRC) insn-attrtab.cc \
+ insn-dfatab.cc insn-latencytab.cc insn-opinit.cc \
+ insn-opinit.h insn-preds.cc \
+ insn-constants.h \
tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \
$(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \
tree-check.h min-insn-modes.cc insn-modes.cc insn-modes.h insn-modes-inline.h \
@@ -2763,7 +2773,7 @@ $(common_out_object_file): $(common_out_file)
.PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
$(INSNEMIT_SEQ_SRC) insn-recog.h $(INSNRECOG_SEQ_SRC) \
insn-extract.cc insn-output.cc \
- insn-peep.cc insn-attr.h insn-attr-common.h insn-attrtab.cc \
+ insn-peep.cc insn-attr.h insn-attr-common.h $(INSNATTRTAB_SEQ_SRC) \
insn-dfatab.cc insn-latencytab.cc insn-preds.cc \
$(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
gimple-match-auto.h generic-match-auto.h insn-target-def.h
@@ -2850,13 +2860,19 @@ s-check : build/gencheck$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
$(STAMP) s-check
-# genattrtab produces three files: tmp-{attrtab.cc,dfatab.cc,latencytab.cc}
-insn-attrtab.cc insn-dfatab.cc insn-latencytab.cc: s-attrtab ; @true
+# genattrtab splits the attribute functions like genemit and additionally
+# produces tmp-dfatab.cc and tmp-latencytab.cc.
+$(INSNATTRTAB_SEQ_SRC): s-attrtab ; @true
+insn-dfatab.cc insn-latencytab.cc: s-attrtab ; @true
s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
insn-conditions.md
$(RUN_GEN) build/genattrtab$(build_exeext) $(md_file) insn-conditions.md \
- -Atmp-attrtab.cc -Dtmp-dfatab.cc -Ltmp-latencytab.cc
- $(SHELL) $(srcdir)/../move-if-change tmp-attrtab.cc insn-attrtab.cc
+ $(addprefix -A,${INSNATTRTAB_SEQ_TMP}) \
+ -Dtmp-dfatab.cc -Ltmp-latencytab.cc
+ for id in $(INSNATTRTAB_SPLITS_SEQ); do \
+ $(SHELL) $(srcdir)/../move-if-change tmp-attrtab-$$id.cc \
+ insn-attrtab-$$id.cc || exit 1; \
+ done
$(SHELL) $(srcdir)/../move-if-change tmp-dfatab.cc insn-dfatab.cc
$(SHELL) $(srcdir)/../move-if-change tmp-latencytab.cc insn-latencytab.cc
$(STAMP) s-attrtab
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index fc36d52ead0..380f2c39777 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -93,7 +93,8 @@ extern bool arc_text_label (rtx_insn *insn);
extern bool arc_short_comparison_p (rtx, int);
extern bool arc_epilogue_uses (int regno);
extern bool arc_eh_uses (int regno);
-/* insn-attrtab.cc doesn't include reload.h, which declares regno_clobbered_p. */
+/* Generated attribute code does not include reload.h, which declares
+ regno_clobbered_p. */
extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
index b06158ba7bc..292c6b3d939 100644
--- a/gcc/config/ia64/ia64.cc
+++ b/gcc/config/ia64/ia64.cc
@@ -9286,8 +9286,8 @@ bundling (FILE *dump, int verbose, rtx_insn *prev_head_insn, rtx_insn *tail)
curr_state = curr_state->next)
if (verbose >= 2 && dump)
{
- /* This structure is taken from generated code of the
- pipeline hazard recognizer (see file insn-attrtab.cc).
+ /* This structure is taken from the generated pipeline hazard
+ recognizer code.
Please don't forget to change the structure if a new
automaton is added to .md file. */
struct DFA_chip
diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64
index 4c37dd89fba..2bf590d89df 100644
--- a/gcc/config/ia64/t-ia64
+++ b/gcc/config/ia64/t-ia64
@@ -22,7 +22,8 @@ ia64-c.o: $(srcdir)/config/ia64/ia64-c.cc $(CONFIG_H) $(SYSTEM_H) \
$(srcdir)/config/ia64/ia64-c.cc
# genattrtab generates very long string literals.
-insn-attrtab.o-warn = -Wno-error
+$(foreach id, $(INSNATTRTAB_SPLITS_SEQ), \
+ $(eval insn-attrtab-$(id).o-warn = -Wno-error))
ia64.o: $(srcdir)/config/ia64/ia64.cc debug.h $(PARAMS_H) sel-sched.h reload.h \
$(OPTS_H) dumpfile.h $(HASH_TABLE_H)
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 9b2ed6a33db..f3973e7fcab 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -24,8 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include "config/vxworks-dummy.h"
-/* Unfortunately, insn-attrtab.cc doesn't include insn-codes.h. We can't
- include it here, because bconfig.h is also included by gencodes.cc . */
+/* Unfortunately, generated attribute code does not include insn-codes.h.
+ We can't include it here, because bconfig.h is also included by
+ gencodes.cc . */
/* ??? No longer true. */
extern int code_for_indirect_jump_scratch;
diff --git a/gcc/configure b/gcc/configure
index eea63c9721c..c9f1feee86b 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1882,8 +1882,8 @@ Optional Packages:
Set the number of partitions to make for gimple and
generic when splitting match.pd. [default=10]
--with-insnemit-partitions=num
- Set the number of partitions of insn-emit.cc for
- genemit and genrecog to create. [default=10]
+ Set the number of partitions used by genemit,
+ genrecog and genattrtab. [default=10]
--with-dwarf2 force the default debug format to be DWARF 2 (or
later)
--with-specs=SPECS add SPECS to driver command-line processing
@@ -7907,7 +7907,8 @@ fi
-# Specify the number of splits of insn-emit.cc and insn-recog.cc to generate.
+# Specify the number of output partitions used by the machine-description
+# generators.
# Check whether --with-insnemit-partitions was given.
if test "${with_insnemit_partitions+set}" = set; then :
@@ -21921,7 +21922,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21924 "configure"
+#line 21925 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -22027,7 +22028,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 22030 "configure"
+#line 22031 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 58576227136..a8b0a08f20d 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -902,10 +902,12 @@ fi
AC_SUBST(DEFAULT_MATCHPD_PARTITIONS)
-# Specify the number of splits of insn-emit.cc and insn-recog.cc to generate.
+# Specify the number of output partitions used by the machine-description
+# generators.
AC_ARG_WITH(insnemit-partitions,
[AS_HELP_STRING([--with-insnemit-partitions=num],
-[Set the number of partitions of insn-emit.cc for genemit and genrecog to create. [default=10]])],
+[Set the number of partitions used by genemit, genrecog and genattrtab.
+[default=10]])],
[DEFAULT_INSNEMIT_PARTITIONS="$with_insnemit_partitions"], [DEFAULT_INSNEMIT_PARTITIONS=10])
if (test $DEFAULT_INSNEMIT_PARTITIONS -lt 1); then
AC_MSG_ERROR(m4_normalize([
diff --git a/gcc/final.cc b/gcc/final.cc
index 0152be59fc8..e2761d056ea 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -142,7 +142,7 @@ static int override_discriminator;
/* Whether to force emission of a line note before the next insn. */
static bool force_source_line = false;
-extern const int length_unit_log; /* This is defined in insn-attrtab.cc. */
+extern const int length_unit_log; /* Defined in generated attribute code. */
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't die.
diff --git a/gcc/genattrtab.cc b/gcc/genattrtab.cc
index 07982b74c81..54f3dc7f887 100644
--- a/gcc/genattrtab.cc
+++ b/gcc/genattrtab.cc
@@ -314,16 +314,17 @@ static rtx min_fn (rtx);
functions and tables. This made insn-attrtab.cc _the_ bottle-neck in
a parallel build, and even made it impossible to build GCC on machines
with relatively small RAM space (PR other/29442). Therefore, the
- attribute functions/tables are now written out to three separate
- files: all "*insn_default_latency" functions go to LATENCY_FILE_NAME,
- all "*internal_dfa_insn_code" functions go to DFA_FILE_NAME, and the
- rest goes to ATTR_FILE_NAME. */
+ attribute functions/tables are now written out to separate files: all
+ "*insn_default_latency" functions go to the latency output, all
+ "*internal_dfa_insn_code" functions go to the DFA output, and the rest is
+ distributed across the attribute outputs the way genemit and genrecog
+ distribute their output. */
-static const char *attr_file_name = NULL;
-static const char *dfa_file_name = NULL;
-static const char *latency_file_name = NULL;
+/* The files produced by the generator. */
+static auto_vec<generator_output, 10> output_files;
-static FILE *attr_file, *dfa_file, *latency_file;
+static FILE *dfa_file, *latency_file;
+static const char *dfa_file_name, *latency_file_name;
/* Hash table for sharing RTL and strings. */
@@ -5233,6 +5234,9 @@ make_automaton_attrs (void)
tune_attr = find_tune_attr (all_insn_reservs->condexp);
if (tune_attr != NULL)
{
+ /* The function pointers and init_sched_attrs go to the first
+ attribute file. */
+ FILE *attr_file = output_files[0].file;
rtx *condexps = XNEWVEC (rtx, n_insn_reservs * 3);
struct attr_value *val;
bool first = true;
@@ -5458,29 +5462,22 @@ write_header (FILE *outf)
fprintf (outf, "#define operands recog_data.operand\n\n");
}
-static FILE *
-open_outfile (const char *file_name)
-{
- FILE *outf;
- outf = fopen (file_name, "w");
- if (! outf)
- fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
- write_header (outf);
- return outf;
-}
-
static bool
handle_arg (const char *arg)
{
switch (arg[1])
{
case 'A':
- attr_file_name = &arg[2];
+ add_generator_output (output_files, &arg[2], true);
return true;
case 'D':
+ if (dfa_file_name)
+ fatal ("option -D specified more than once");
dfa_file_name = &arg[2];
return true;
case 'L':
+ if (latency_file_name)
+ fatal ("option -L specified more than once");
latency_file_name = &arg[2];
return true;
default:
@@ -5488,6 +5485,36 @@ handle_arg (const char *arg)
}
}
+/* Return a measure of how much text write_attr_get will produce for ATTR.
+ For a derived attribute that is the length of its lookup table, and
+ otherwise the number of case labels, since find_most_used turns the
+ remaining value into the default arm. */
+
+static int
+attr_output_size (class attr_desc *attr)
+{
+ if (attr->derived_from)
+ return attr->derived_from->num_values;
+
+ struct attr_value *common = find_most_used (attr);
+ int size = 0;
+ for (struct attr_value *av = attr->first_value; av; av = av->next)
+ if (av != common)
+ size += av->num_insns;
+ return size;
+}
+
+/* Sort attributes so that the ones producing the most text come first. */
+
+static int
+cmp_attr_output_size (const void *a, const void *b)
+{
+ class attr_desc *aa = *(class attr_desc *const *) a;
+ class attr_desc *bb = *(class attr_desc *const *) b;
+ int diff = attr_output_size (bb) - attr_output_size (aa);
+ return diff ? diff : strcmp (aa->name, bb->name);
+}
+
int
main (int argc, const char **argv)
{
@@ -5500,9 +5527,22 @@ main (int argc, const char **argv)
if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
return FATAL_EXIT_CODE;
- attr_file = open_outfile (attr_file_name);
- dfa_file = open_outfile (dfa_file_name);
- latency_file = open_outfile (latency_file_name);
+ if (output_files.is_empty ())
+ fatal ("no -A output file specified");
+ if (!dfa_file_name)
+ fatal ("no -D output file specified");
+ if (!latency_file_name)
+ fatal ("no -L output file specified");
+
+ unsigned int dfa_index
+ = add_generator_output (output_files, dfa_file_name, false);
+ unsigned int latency_index
+ = add_generator_output (output_files, latency_file_name, false);
+ open_generator_outputs (output_files);
+ dfa_file = output_files[dfa_index].file;
+ latency_file = output_files[latency_index].file;
+ for (generator_output &output : output_files)
+ write_header (output.file);
obstack_init (hash_obstack);
obstack_init (temp_obstack);
@@ -5619,50 +5659,56 @@ main (int argc, const char **argv)
/* Perform any possible optimizations to speed up compilation. */
optimize_attrs (num_insn_codes);
- /* Now write out all the `gen_attr_...' routines. Do these before the
- special routines so that they get defined before they are used. */
+ /* Now write out all the `get_attr_...' routines. The DFA and latency
+ routines go to their own files; the rest are distributed across the
+ attribute files. They only refer to each other through the extern
+ declarations in insn-attr.h and insn-attr-common.h. */
+ auto_vec<class attr_desc *> to_write;
for (i = 0; i < MAX_ATTRS_INDEX; i++)
for (attr = attrs[i]; attr; attr = attr->next)
- {
- FILE *outf;
+ if (!attr->is_special && !attr->is_const)
+ to_write.safe_push (attr);
- if (startswith(attr->name, "*internal_dfa_insn_code"))
- outf = dfa_file;
- else if (startswith (attr->name, "*insn_default_latency"))
- outf = latency_file;
- else
- outf = attr_file;
+ /* Give choose_output the largest functions first. It assigns each one to
+ the shortest output so far, and feeding it an arbitrary order lets a
+ late large function land on an already full partition. Attribute
+ functions differ in size by two orders of magnitude, so that happens
+ easily. */
+ to_write.qsort (cmp_attr_output_size);
- if (! attr->is_special && ! attr->is_const)
- write_attr_get (outf, attr);
- }
+ for (class attr_desc *a : to_write)
+ {
+ FILE *outf;
+
+ if (startswith (a->name, "*internal_dfa_insn_code"))
+ outf = dfa_file;
+ else if (startswith (a->name, "*insn_default_latency"))
+ outf = latency_file;
+ else
+ outf = choose_output (output_files);
+
+ write_attr_get (outf, a);
+ }
/* Write out delay eligibility information, if DEFINE_DELAY present.
(The function to compute the number of delay slots will be written
below.) */
- write_eligible_delay (attr_file, "delay");
+ write_eligible_delay (choose_output (output_files), "delay");
if (have_annul_true)
- write_eligible_delay (attr_file, "annul_true");
+ write_eligible_delay (choose_output (output_files), "annul_true");
else
- write_dummy_eligible_delay (attr_file, "annul_true");
+ write_dummy_eligible_delay (choose_output (output_files), "annul_true");
if (have_annul_false)
- write_eligible_delay (attr_file, "annul_false");
+ write_eligible_delay (choose_output (output_files), "annul_false");
else
- write_dummy_eligible_delay (attr_file, "annul_false");
+ write_dummy_eligible_delay (choose_output (output_files), "annul_false");
/* Write out constant delay slot info. */
- write_const_num_delay_slots (attr_file);
-
- write_length_unit_log (attr_file);
+ write_const_num_delay_slots (choose_output (output_files));
- if (fclose (attr_file) != 0)
- fatal ("cannot close file %s: %s", attr_file_name, xstrerror (errno));
- if (fclose (dfa_file) != 0)
- fatal ("cannot close file %s: %s", dfa_file_name, xstrerror (errno));
- if (fclose (latency_file) != 0)
- fatal ("cannot close file %s: %s", latency_file_name, xstrerror (errno));
+ write_length_unit_log (choose_output (output_files));
- return SUCCESS_EXIT_CODE;
+ return (close_generator_outputs (output_files)
+ ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
}
-
--
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.