This patch adds support for emitting functions read from a PPH image. With this, we ...
13 years, 10 months ago
(2011-06-29 01:50:59 UTC)
#1
This patch adds support for emitting functions read from a PPH image.
With this, we can now run some simple C++ programs whose header has
been reconstructed from a single PPH image.
The core problem it fixes was in the saving and restoring of functions
with a body.
1- When the parser wants to register a function for code
generation, it calls expand_or_defer_fn(). When reading from the
pph image, we were not calling this, so the callgraph manager was
tossing these functions out.
2- Even when we call expand_or_defer_fn, we need to take care of
another side-effect. In the writer, the call to expand_or_defer_fn
sets DECL_EXTERNAL to 1 (for reasons that I'm not too sure I
understand). At the same time, it remembers that it forced
DECL_EXTERNAL by setting DECL_NOT_REALLY_EXTERN. Since I don't
think I understand why it does this, I'm simply using
DECL_NOT_REALLY_EXTERN in the reader to recognize that the decl is
should have DECL_EXTERNAL set to 0. Jason, does this make any
sense?
This fixed a whole bunch of tests: c1builtin-object-size-2.cc,
c1funcstatic.cc, c1return-5.cc, c1simple.cc, x1autometh.cc,
x1funcstatic.cc, x1struct1.cc, x1ten-hellos.cc and x1tmplfunc.cc.
It also exposed other bugs in c c1attr-warn-unused-result.cc and
x1template.cc. Lawrence, Gab, I think this affects some of the
failures you were looking at today. Please double check.
I also added support for 'dg-do run' tests to support x1ten-hellos.cc
which now actually works (though it is not completely bug-free, I see
that the counter it initializes starts with a bogus value).
Tested on x86_64. Committed to branch.
cp/ChangeLog.pph
2011-06-28 Diego Novillo <dnovillo@google.com>
* pph-streamer-in.c (pph_in_ld_fn): Instantiate
DECL_STRUCT_FUNCTION by calling allocate_struct_function.
Remove assertion for stream->data_in.
(pph_in_function_decl): Factor out of ...
(pph_read_tree): ... here.
* pph-streamer-out.c (pph_out_function_decl): Factor out of ...
(pph_write_tree): ... here.
testsuite/ChangeLog.pph
* g++.dg/pph/c1attr-warn-unused-result.cc: Expect an ICE.
* g++.dg/pph/x1template.cc: Likewise.
* g++.dg/pph/c1builtin-object-size-2.cc: Expect no asm difference.
* g++.dg/pph/c1funcstatic.cc: Likewise.
* g++.dg/pph/c1return-5.cc: Likewise.
* g++.dg/pph/c1simple.cc: Likewise.
* g++.dg/pph/x1autometh.cc: Likewise.
* g++.dg/pph/x1funcstatic.cc: Likewise.
* g++.dg/pph/x1struct1.cc: Likewise.
* g++.dg/pph/x1ten-hellos.cc: Likewise.
* g++.dg/pph/x1tmplfunc.cc: Likewise.
* g++.dg/pph/c1meteor-contest.cc: Adjust timeout.
* g++.dg/pph/x1dynarray1.cc: Adjust expected ICE.
* g++.dg/pph/x1namespace.cc: Likewise.
* lib/dg-pph.exp: Do not compare assembly output if the test
is marked 'dg-do run'.
diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c
index 7f70b65..1dabcf1 100644
--- a/gcc/cp/pph-streamer-in.c
+++ b/gcc/cp/pph-streamer-in.c
@@ -767,18 +767,17 @@ pph_in_ld_fn (pph_stream *stream, struct lang_decl_fn
*ldf)
}
-/* Read applicable fields of struct function instance FN from STREAM. */
+/* Read applicable fields of struct function from STREAM. Associate
+ the read structure to DECL. */
static struct function *
-pph_in_struct_function (pph_stream *stream)
+pph_in_struct_function (pph_stream *stream, tree decl)
{
size_t count, i;
unsigned ix;
enum pph_record_marker marker;
struct function *fn;
- gcc_assert (stream->data_in != NULL);
-
marker = pph_in_start_record (stream, &ix);
if (marker == PPH_RECORD_END)
return NULL;
@@ -786,7 +785,8 @@ pph_in_struct_function (pph_stream *stream)
/* Since struct function is embedded in every decl, fn cannot be shared. */
gcc_assert (marker != PPH_RECORD_SHARED);
- fn = ggc_alloc_cleared_function ();
+ allocate_struct_function (decl, false);
+ fn = DECL_STRUCT_FUNCTION (decl);
input_struct_function_base (fn, stream->data_in, stream->ib);
@@ -1355,6 +1355,35 @@ pph_read_file (const char *filename)
}
+/* Read the attributes for a FUNCTION_DECL FNDECL. If FNDECL had
+ a body, mark it for expansion. */
+
+static void
+pph_in_function_decl (pph_stream *stream, tree fndecl)
+{
+ DECL_INITIAL (fndecl) = pph_in_tree (stream);
+ pph_in_lang_specific (stream, fndecl);
+ DECL_SAVED_TREE (fndecl) = pph_in_tree (stream);
+ DECL_STRUCT_FUNCTION (fndecl) = pph_in_struct_function (stream, fndecl);
+ DECL_CHAIN (fndecl) = pph_in_tree (stream);
+ if (DECL_SAVED_TREE (fndecl))
+ {
+ /* FIXME pph - This is somewhat gross. When we generated the
+ PPH image, the parser called expand_or_defer_fn on FNDECL,
+ which marked it DECL_EXTERNAL (see expand_or_defer_fn_1 for
+ details).
+
+ However, this is not really an extern definition, so it was
+ also marked not-really-extern (yes, I know...). If this
+ happens, we need to unmark it, otherwise the code generator
+ will toss it out. */
+ if (DECL_NOT_REALLY_EXTERN (fndecl))
+ DECL_EXTERNAL (fndecl) = 0;
+ expand_or_defer_fn (fndecl);
+ }
+}
+
+
/* Callback for reading ASTs from a stream. This reads all the fields
that are not processed by default by the common tree pickler.
IB, DATA_IN are as in lto_read_tree. EXPR is the partially materialized
@@ -1394,11 +1423,7 @@ pph_read_tree (struct lto_input_block *ib
ATTRIBUTE_UNUSED,
break;
case FUNCTION_DECL:
- DECL_INITIAL (expr) = pph_in_tree (stream);
- pph_in_lang_specific (stream, expr);
- DECL_SAVED_TREE (expr) = pph_in_tree (stream);
- DECL_STRUCT_FUNCTION (expr) = pph_in_struct_function (stream);
- DECL_CHAIN (expr) = pph_in_tree (stream);
+ pph_in_function_decl (stream, expr);
break;
case TYPE_DECL:
diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c
index 045f68a..acc0352 100644
--- a/gcc/cp/pph-streamer-out.c
+++ b/gcc/cp/pph-streamer-out.c
@@ -1241,6 +1241,19 @@ pph_out_tree_header (struct output_block *ob, tree expr)
}
+/* Emit the fields of FUNCTION_DECL FNDECL to STREAM. REF_P is as
+ in pph_write_tree. */
+
+static void
+pph_out_function_decl (pph_stream *stream, tree fndecl, bool ref_p)
+{
+ pph_out_tree_or_ref_1 (stream, DECL_INITIAL (fndecl), ref_p, 3);
+ pph_out_lang_specific (stream, fndecl, ref_p);
+ pph_out_tree_or_ref_1 (stream, DECL_SAVED_TREE (fndecl), ref_p, 3);
+ pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (fndecl), ref_p);
+ pph_out_tree_or_ref_1 (stream, DECL_CHAIN (fndecl), ref_p, 3);
+}
+
/* Callback for writing ASTs to a stream. This writes all the fields
that are not processed by default by the common tree pickler.
OB and REF_P are as in lto_write_tree. EXPR is the tree to write. */
@@ -1278,11 +1291,7 @@ pph_write_tree (struct output_block *ob, tree expr, bool
ref_p)
break;
case FUNCTION_DECL:
- pph_out_tree_or_ref_1 (stream, DECL_INITIAL (expr), ref_p, 3);
- pph_out_lang_specific (stream, expr, ref_p);
- pph_out_tree_or_ref_1 (stream, DECL_SAVED_TREE (expr), ref_p, 3);
- pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (expr), ref_p);
- pph_out_tree_or_ref_1 (stream, DECL_CHAIN (expr), ref_p, 3);
+ pph_out_function_decl (stream, expr, ref_p);
break;
case TYPE_DECL:
diff --git a/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc
b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc
index da75561..4633106 100644
--- a/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc
+++ b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc
@@ -1,3 +1,6 @@
+/* { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } } */
+// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
+// { dg-prune-output "In file included from" }
/* { dg-options "-w" } */
// pph asm xdiff
#include "c1attr-warn-unused-result.h"
diff --git a/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc
b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc
index 17fe707..615e7da 100644
--- a/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc
+++ b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc
@@ -1,3 +1,2 @@
/* { dg-options "-O2 -w -fpermissive" } */
-// pph asm xdiff
#include "c1builtin-object-size-2.h"
diff --git a/gcc/testsuite/g++.dg/pph/c1funcstatic.cc
b/gcc/testsuite/g++.dg/pph/c1funcstatic.cc
index 05a487c..b6cd27e 100644
--- a/gcc/testsuite/g++.dg/pph/c1funcstatic.cc
+++ b/gcc/testsuite/g++.dg/pph/c1funcstatic.cc
@@ -1,3 +1,2 @@
-// pph asm xdiff
#include "c1funcstatic.h"
int g() { return f(); }
diff --git a/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc
b/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc
index 58d2c89..e745afe 100644
--- a/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc
+++ b/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc
@@ -1,4 +1,4 @@
-/* { dg-timeout 5 { target *-*-* } } */
+/* { dg-timeout 2 { target *-*-* } } */
// { dg-xfail-if "INFINITE" { "*-*-*" } { "-fpph-map=pph.map" } }
/* { dg-options "-w" } */
#include "c1meteor-contest.h"
diff --git a/gcc/testsuite/g++.dg/pph/c1return-5.cc
b/gcc/testsuite/g++.dg/pph/c1return-5.cc
index aa7dfe4..a29c8a9 100644
--- a/gcc/testsuite/g++.dg/pph/c1return-5.cc
+++ b/gcc/testsuite/g++.dg/pph/c1return-5.cc
@@ -1,5 +1,4 @@
// { dg-options "-mpreferred-stack-boundary=4" }
// { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-64,\[^\\n\]*sp" } }
-// pph asm xdiff
#include "c1return-5.h"
diff --git a/gcc/testsuite/g++.dg/pph/c1simple.cc
b/gcc/testsuite/g++.dg/pph/c1simple.cc
index f4d8f1b..60aed2e 100644
--- a/gcc/testsuite/g++.dg/pph/c1simple.cc
+++ b/gcc/testsuite/g++.dg/pph/c1simple.cc
@@ -1,5 +1,3 @@
-// pph asm xdiff
-
/* comment */
#include "c1simple2.h"
diff --git a/gcc/testsuite/g++.dg/pph/x1autometh.cc
b/gcc/testsuite/g++.dg/pph/x1autometh.cc
index 783c667..0c31028 100644
--- a/gcc/testsuite/g++.dg/pph/x1autometh.cc
+++ b/gcc/testsuite/g++.dg/pph/x1autometh.cc
@@ -1,5 +1,3 @@
-// pph asm xdiff
-
#include "x1autometh.h"
void function() {
diff --git a/gcc/testsuite/g++.dg/pph/x1dynarray1.cc
b/gcc/testsuite/g++.dg/pph/x1dynarray1.cc
index 6fa12df..19f5b4c 100644
--- a/gcc/testsuite/g++.dg/pph/x1dynarray1.cc
+++ b/gcc/testsuite/g++.dg/pph/x1dynarray1.cc
@@ -1,5 +1,5 @@
// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x1dynarray1.cc:1:0: internal compiler error: in
pph_in_lang_specific, at cp/pph-streamer-in.c:887" "" { xfail *-*-* } 0 }
+// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
#include "x1dynarray1.h"
#include <iostream>
diff --git a/gcc/testsuite/g++.dg/pph/x1funcstatic.cc
b/gcc/testsuite/g++.dg/pph/x1funcstatic.cc
index a920c5a..31166f6 100644
--- a/gcc/testsuite/g++.dg/pph/x1funcstatic.cc
+++ b/gcc/testsuite/g++.dg/pph/x1funcstatic.cc
@@ -1,3 +1,2 @@
-// pph asm xdiff
#include "c1funcstatic.h"
int a = f();
diff --git a/gcc/testsuite/g++.dg/pph/x1namespace.cc
b/gcc/testsuite/g++.dg/pph/x1namespace.cc
index 547150c..16afff9 100644
--- a/gcc/testsuite/g++.dg/pph/x1namespace.cc
+++ b/gcc/testsuite/g++.dg/pph/x1namespace.cc
@@ -1,5 +1,5 @@
// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x1namespace.h:18:13: internal compiler error: in resume_scope"
"" { xfail *-*-* } 0 }
+// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
// { dg-prune-output "In file included from " }
#include "x1namespace.h"
diff --git a/gcc/testsuite/g++.dg/pph/x1struct1.cc
b/gcc/testsuite/g++.dg/pph/x1struct1.cc
index 5a4fbd6..69aed1b 100644
--- a/gcc/testsuite/g++.dg/pph/x1struct1.cc
+++ b/gcc/testsuite/g++.dg/pph/x1struct1.cc
@@ -1,5 +1,3 @@
-// pph asm xdiff
-
#include "x1struct1.h"
type D::method()
diff --git a/gcc/testsuite/g++.dg/pph/x1template.cc
b/gcc/testsuite/g++.dg/pph/x1template.cc
index a50abb0..fbcb1bf 100644
--- a/gcc/testsuite/g++.dg/pph/x1template.cc
+++ b/gcc/testsuite/g++.dg/pph/x1template.cc
@@ -1,3 +1,6 @@
+/* { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } } */
+// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
+// { dg-prune-output "In file included from" }
// pph asm xdiff
#include "x1template.h"
diff --git a/gcc/testsuite/g++.dg/pph/x1ten-hellos.cc
b/gcc/testsuite/g++.dg/pph/x1ten-hellos.cc
index 4ca7273..865b149 100644
--- a/gcc/testsuite/g++.dg/pph/x1ten-hellos.cc
+++ b/gcc/testsuite/g++.dg/pph/x1ten-hellos.cc
@@ -1,6 +1,4 @@
// { dg-do run }
-// { dg-xfail-if "LINK ERROR" { "*-*-*" } { "-fpph-map=pph.map" } }
-// pph asm xdiff
#include "x1ten-hellos.h"
int main(void)
diff --git a/gcc/testsuite/g++.dg/pph/x1tmplfunc.cc
b/gcc/testsuite/g++.dg/pph/x1tmplfunc.cc
index 35b4cab..dc1c413 100644
--- a/gcc/testsuite/g++.dg/pph/x1tmplfunc.cc
+++ b/gcc/testsuite/g++.dg/pph/x1tmplfunc.cc
@@ -1,5 +1,3 @@
-// pph asm xdiff
-
#include "x1tmplfunc.h"
type val = 3;
diff --git a/gcc/testsuite/lib/dg-pph.exp b/gcc/testsuite/lib/dg-pph.exp
index c773aa0..39a24b7 100644
--- a/gcc/testsuite/lib/dg-pph.exp
+++ b/gcc/testsuite/lib/dg-pph.exp
@@ -93,8 +93,10 @@ proc dg-pph-pos { subdir test options mapflag suffix } {
# Quit if it did not compile successfully.
if { ![file_on_host exists "$bname.s"] } {
- # Expect assembly to be missing when the compile is an expected fail.
- if { ![llength [grep $test "dg-xfail-if.*-fpph-map"]] } {
+ # Expect assembly to be missing when the compile is an
+ # expected fail or when this was an executable test.
+ if { ![string compare "dg-do-what" "run"] \
+ && ![llength [grep $test "dg-xfail-if.*-fpph-map"]] } {
fail "$nshort $options (pph assembly missing)"
}
return
--
This patch is available for review at http://codereview.appspot.com/4630074
Issue 4630074: [pph] Support simple C++ programs
(Closed)
Created 13 years, 10 months ago by Diego Novillo
Modified 13 years, 8 months ago
Reviewers:
Base URL:
Comments: 0